From e1ddecd2bf4a137451983e4937dbe4b0f9d11ae4 Mon Sep 17 00:00:00 2001 From: Jeffrey Townsend Date: Tue, 21 Feb 2017 18:06:48 +0000 Subject: [PATCH] 3.2 LTS Kernel Build This kernel tracks the 3.2 LTS kernel with minimal patches to support the Broadcom IPROC. This replaces the previous 3.2.71 patched kernel put in place temporarily to support ARM. IPROC systems will be moved to this kernel (which will continue to track 3.2 LTS) until IPROC support is integrated with the 3.16 LTS package. This kernel is available for IPROC systems only. --- .../3.2-lts/configs/arm-iproc-all/.gitignore | 2 + .../3.2-lts/configs/arm-iproc-all/Makefile | 41 + .../arm-iproc-all/arm-iproc-all.config | 2432 + packages/base/any/kernels/3.2-lts/kconfig.mk | 27 + .../kernels/3.2-lts/patches/Makefile.patch | 131 + .../3.2-lts/patches/arch_arm_Kconfig.patch | 85 + .../3.2-lts/patches/arch_arm_Makefile.patch | 28 + .../arch_arm_boot_compressed_head.S.patch | 13 + ...ch_arm_boot_dts_accton_as4610_54.dts.patch | 256 + .../arch_arm_boot_dts_dni_3448p.dts.patch | 172 + .../arch_arm_boot_dts_helix4.dtsi.patch | 65 + .../patches/arch_arm_common_gic.c.patch | 44 + .../arch_arm_configs_iproc_defconfig.patch | 2430 + .../patches/arch_arm_include_asm_bug.h.patch | 12 + .../arch_arm_include_asm_hardware_gic.h.patch | 12 + .../arch_arm_include_asm_pgtable.h.patch | 39 + .../arch_arm_include_asm_processor.h.patch | 13 + .../arch_arm_kernel_entry-armv.S.patch | 39 + .../arch_arm_kernel_entry-header.S.patch | 15 + .../patches/arch_arm_kernel_head.S.patch | 32 + .../patches/arch_arm_kernel_module.c.patch | 74 + .../patches/arch_arm_kernel_process.c.patch | 27 + .../patches/arch_arm_kernel_smp_scu.c.patch | 49 + .../patches/arch_arm_kernel_smp_twd.c.patch | 70 + .../patches/arch_arm_mach-iproc_Kconfig.patch | 113 + .../arch_arm_mach-iproc_Makefile.boot.patch | 8 + .../arch_arm_mach-iproc_Makefile.patch | 21 + .../arch_arm_mach-iproc_board_bu.c.patch | 1103 + .../arch_arm_mach-iproc_common.c.patch | 353 + .../arch_arm_mach-iproc_common.h.patch | 34 + .../patches/arch_arm_mach-iproc_flash.c.patch | 381 + .../patches/arch_arm_mach-iproc_idm.c.patch | 729 + ...arm_mach-iproc_include_mach_io_map.h.patch | 92 + ...mach-iproc_include_mach_iproc_regs.h.patch | 830 + ...mach-iproc_include_mach_nand_iproc.h.patch | 43 + ...mach-iproc_include_mach_qspi_iproc.h.patch | 33 + ..._mach-iproc_include_mach_reg_utils.h.patch | 166 + ...proc_include_mach_socregs_ing_open.h.patch | 781 + ...iproc_include_mach_socregs_ns_open.h.patch | 87 + ...proc_include_mach_socregs_nsp_open.h.patch | 404 + ...iproc_include_mach_socregs_p7_open.h.patch | 267 + ...rm_mach-iproc_include_mach_vmalloc.h.patch | 30 + .../arch_arm_mach-iproc_io_map.c.patch | 63 + .../arch_arm_mach-iproc_localtimer.c.patch | 33 + .../arch_arm_mach-iproc_northstar.c.patch | 172 + .../arch_arm_mach-iproc_northstar.h.patch | 33 + .../arch_arm_mach-iproc_northstar_dmu.c.patch | 808 + .../patches/arch_arm_mach-iproc_pm.c.patch | 45 + .../3.2-lts/patches/arch_arm_mm_Kconfig.patch | 14 + .../3.2-lts/patches/arch_arm_mm_init.c.patch | 13 + .../patches/arch_arm_mm_ioremap.c.patch | 131 + .../3.2-lts/patches/arch_arm_mm_mm.h.patch | 25 + .../3.2-lts/patches/arch_arm_mm_mmap.c.patch | 204 + .../3.2-lts/patches/arch_arm_mm_mmu.c.patch | 110 + .../3.2-lts/patches/arch_arm_mm_nommu.c.patch | 14 + .../patches/arch_arm_net_Makefile.patch | 9 + .../patches/arch_arm_net_bpf_jit_32.c.patch | 921 + .../patches/arch_arm_net_bpf_jit_32.h.patch | 196 + .../patches/arch_arm_plat-iproc_Kconfig.patch | 102 + .../arch_arm_plat-iproc_Makefile.patch | 23 + .../arch_arm_plat-iproc_bcm5301x.c.patch | 90 + .../patches/arch_arm_plat-iproc_clock.c.patch | 171 + .../arch_arm_plat-iproc_headsmp.S.patch | 112 + .../arch_arm_plat-iproc_hotplug.c.patch | 153 + ...at-iproc_include_mach_brcm_rdb_rng.h.patch | 70 + ...lat-iproc_include_mach_bridge-regs.h.patch | 74 + ...arm_plat-iproc_include_mach_clkdev.h.patch | 49 + ..._arm_plat-iproc_include_mach_clock.h.patch | 41 + ...arm_plat-iproc_include_mach_common.h.patch | 57 + ...lat-iproc_include_mach_debug-macro.S.patch | 41 + ...lat-iproc_include_mach_entry-macro.S.patch | 105 + ...h_arm_plat-iproc_include_mach_gpio.h.patch | 36 + ...m_plat-iproc_include_mach_hardware.h.patch | 49 + ...rch_arm_plat-iproc_include_mach_io.h.patch | 41 + ..._arm_plat-iproc_include_mach_iproc.h.patch | 32 + ...lat-iproc_include_mach_iproc_timer.h.patch | 154 + ...h_arm_plat-iproc_include_mach_irqs.h.patch | 255 + ...rch_arm_plat-iproc_include_mach_lm.h.patch | 54 + ...arm_plat-iproc_include_mach_memory.h.patch | 84 + ...t-iproc_include_mach_sdio_platform.h.patch | 73 + ...ch_arm_plat-iproc_include_mach_smp.h.patch | 48 + ...arm_plat-iproc_include_mach_system.h.patch | 42 + ..._arm_plat-iproc_include_mach_timer.h.patch | 55 + ..._arm_plat-iproc_include_mach_timex.h.patch | 31 + ...plat-iproc_include_mach_uncompress.h.patch | 60 + ..._plat-iproc_include_plat_dma-pl330.h.patch | 109 + ...rm_plat-iproc_include_plat_dma_drv.h.patch | 609 + ...h_arm_plat-iproc_include_plat_dmux.h.patch | 82 + ...m_plat-iproc_include_plat_osdal_os.h.patch | 66 + ...ch_arm_plat-iproc_include_plat_shm.h.patch | 50 + ..._plat-iproc_include_plat_spi_iproc.h.patch | 33 + ...lat-iproc_include_plat_swreset_rec.h.patch | 46 + ...m_plat-iproc_include_plat_timer-sp.h.patch | 24 + ..._arm_plat-iproc_include_plat_types.h.patch | 26 + .../arch_arm_plat-iproc_iproc-cache.S.patch | 126 + .../arch_arm_plat-iproc_iproc_cru.c.patch | 566 + .../patches/arch_arm_plat-iproc_irq.c.patch | 51 + .../patches/arch_arm_plat-iproc_lm.c.patch | 144 + .../arch_arm_plat-iproc_localtimer.c.patch | 42 + .../arch_arm_plat-iproc_platsmp.c.patch | 271 + .../patches/arch_arm_plat-iproc_shm.c.patch | 177 + .../arch_arm_plat-iproc_swreset_rec.c.patch | 181 + .../patches/arch_arm_plat-iproc_sysfs.c.patch | 222 + .../arch_arm_plat-iproc_timer-sp.c.patch | 256 + .../patches/arch_arm_plat-iproc_timer.c.patch | 285 + .../patches/arch_arm_tools_mach-types.patch | 9 + .../3.2-lts/patches/drivers_Kconfig.patch | 11 + .../3.2-lts/patches/drivers_Makefile.patch | 9 + .../patches/drivers_base_Kconfig.patch | 15 + .../patches/drivers_base_Makefile.patch | 22 + .../3.2-lts/patches/drivers_base_base.h.patch | 63 + .../3.2-lts/patches/drivers_base_bus.c.patch | 382 + .../patches/drivers_base_class.c.patch | 53 + .../3.2-lts/patches/drivers_base_core.c.patch | 166 + .../3.2-lts/patches/drivers_base_cpu.c.patch | 363 + .../3.2-lts/patches/drivers_base_init.c.patch | 12 + .../3.2-lts/patches/drivers_base_node.c.patch | 34 + .../3.2-lts/patches/drivers_base_sys.c.patch | 28 + .../patches/drivers_base_topology.c.patch | 119 + .../patches/drivers_bcma_host_pci.c.patch | 20 + .../patches/drivers_bcmdrivers_Kconfig.patch | 90 + .../patches/drivers_bcmdrivers_Makefile.patch | 27 + .../drivers_bcmdrivers_dma_.gitignore.patch | 10 + .../drivers_bcmdrivers_dma_Kconfig.patch | 21 + .../drivers_bcmdrivers_dma_Makefile.patch | 9 + .../drivers_bcmdrivers_dma_dma-pl330.h.patch | 109 + .../drivers_bcmdrivers_dma_dma.c.patch | 892 + .../drivers_bcmdrivers_dma_dma_drv.h.patch | 608 + ...drivers_bcmdrivers_dma_pl330-pdata.h.patch | 42 + ...rivers_bcmdrivers_gmac_et_.gitignore.patch | 12 + .../drivers_bcmdrivers_gmac_et_Kconfig.patch | 20 + .../drivers_bcmdrivers_gmac_et_Makefile.patch | 103 + ...ivers_bcmdrivers_gmac_hnd_.gitignore.patch | 12 + .../drivers_bcmdrivers_gmac_hnd_Kconfig.patch | 203 + ...drivers_bcmdrivers_gmac_hnd_Makefile.patch | 181 + ...s_bcmdrivers_gmac_hnd_shared_ksyms.c.patch | 68 + ..._bcmdrivers_gmac_hnd_shared_ksyms.sh.patch | 36 + ...cmdrivers_gmac_src_et_sys_.gitignore.patch | 12 + ..._bcmdrivers_gmac_src_et_sys_et_cfg.h.patch | 30 + ..._bcmdrivers_gmac_src_et_sys_et_dbg.h.patch | 65 + ...mdrivers_gmac_src_et_sys_et_export.h.patch | 49 + ...cmdrivers_gmac_src_et_sys_et_linux.c.patch | 3902 + ...cmdrivers_gmac_src_et_sys_et_linux.h.patch | 74 + ...ers_bcmdrivers_gmac_src_et_sys_etc.c.patch | 905 + ...ers_bcmdrivers_gmac_src_et_sys_etc.h.patch | 323 + ...bcmdrivers_gmac_src_et_sys_etcgmac.c.patch | 2573 + ...bcmdrivers_gmac_src_et_sys_etcgmac.h.patch | 74 + ...bcmdrivers_gmac_src_include_Makefile.patch | 59 + ..._bcmdrivers_gmac_src_include_aidmp.h.patch | 389 + ...bcmdrivers_gmac_src_include_arminc.h.patch | 323 + ...cmdrivers_gmac_src_include_bcm_cfg.h.patch | 34 + ...ers_gmac_src_include_bcm_mpool_pub.h.patch | 361 + ...bcmdrivers_gmac_src_include_bcmcdc.h.patch | 128 + ...cmdrivers_gmac_src_include_bcmdefs.h.patch | 342 + ...cmdrivers_gmac_src_include_bcmdevs.h.patch | 868 + ...drivers_gmac_src_include_bcmendian.h.patch | 330 + ...rivers_gmac_src_include_bcmenetmib.h.patch | 94 + ...rivers_gmac_src_include_bcmenetphy.h.patch | 93 + ...rivers_gmac_src_include_bcmenetrxh.h.patch | 56 + ...rivers_gmac_src_include_bcmgmacmib.h.patch | 123 + ...rivers_gmac_src_include_bcmgmacrxh.h.patch | 59 + ...vers_gmac_src_include_bcmiproc_phy.h.patch | 273 + ..._gmac_src_include_bcmiproc_phy5221.h.patch | 51 + ...gmac_src_include_bcmiproc_phy5461s.h.patch | 52 + ...c_src_include_bcmiproc_robo_serdes.h.patch | 84 + ...s_gmac_src_include_bcmiproc_serdes.h.patch | 84 + ...ac_src_include_bcmiproc_serdes_def.h.patch | 312 + ...mdrivers_gmac_src_include_bcmnvram.h.patch | 301 + ...bcmdrivers_gmac_src_include_bcmotp.h.patch | 87 + ...drivers_gmac_src_include_bcmparams.h.patch | 38 + ...cmdrivers_gmac_src_include_bcmperf.h.patch | 46 + ...cmdrivers_gmac_src_include_bcmrobo.h.patch | 209 + ...bcmdrivers_gmac_src_include_bcmsdh.h.patch | 232 + ...mdrivers_gmac_src_include_bcmsdpcm.h.patch | 274 + ...cmdrivers_gmac_src_include_bcmsrom.h.patch | 61 + ...ivers_gmac_src_include_bcmsrom_fmt.h.patch | 555 + ...ivers_gmac_src_include_bcmsrom_tbl.h.patch | 884 + ...drivers_gmac_src_include_bcmstdlib.h.patch | 134 + ...mdrivers_gmac_src_include_bcmutils.h.patch | 870 + ...cmdrivers_gmac_src_include_bcmwifi.h.patch | 462 + ...drivers_gmac_src_include_compvers.sh.patch | 128 + ...ivers_gmac_src_include_ctf_ctf_cfg.h.patch | 82 + ...rivers_gmac_src_include_ctf_hndctf.h.patch | 305 + ...rivers_gmac_src_include_epivers.h.in.patch | 52 + ...cmdrivers_gmac_src_include_epivers.h.patch | 51 + ...mdrivers_gmac_src_include_epivers.sh.patch | 301 + ...cmdrivers_gmac_src_include_etioctl.h.patch | 164 + ...ivers_gmac_src_include_gmac_common.h.patch | 566 + ...drivers_gmac_src_include_gmac_core.h.patch | 308 + ...bcmdrivers_gmac_src_include_hndarm.h.patch | 102 + ...mdrivers_gmac_src_include_hndchipc.h.patch | 44 + ...bcmdrivers_gmac_src_include_hndcpu.h.patch | 46 + ...bcmdrivers_gmac_src_include_hnddma.h.patch | 323 + ...bcmdrivers_gmac_src_include_hndfwd.h.patch | 142 + ...bcmdrivers_gmac_src_include_hndsoc.h.patch | 275 + ...cmdrivers_gmac_src_include_hndtcam.h.patch | 101 + ...drivers_gmac_src_include_linux_osl.h.patch | 985 + ...mdrivers_gmac_src_include_linuxver.h.patch | 668 + ...rs_bcmdrivers_gmac_src_include_osl.h.patch | 151 + ...mac_src_include_packed_section_end.h.patch | 77 + ...c_src_include_packed_section_start.h.patch | 82 + ...bcmdrivers_gmac_src_include_pcicfg.h.patch | 575 + ...vers_gmac_src_include_proto_802.11.h.patch | 2362 + ...vers_gmac_src_include_proto_802.1d.h.patch | 50 + ...cmdrivers_gmac_src_include_proto_BOM.patch | 10 + ...vers_gmac_src_include_proto_Makefile.patch | 15 + ...vers_gmac_src_include_proto_bcmeth.h.patch | 112 + ...rs_gmac_src_include_proto_bcmevent.h.patch | 319 + ...ivers_gmac_src_include_proto_bcmip.h.patch | 211 + ...ers_gmac_src_include_proto_bcmipv6.h.patch | 107 + ...rs_gmac_src_include_proto_ethernet.h.patch | 208 + ...rivers_gmac_src_include_proto_vlan.h.patch | 73 + ...drivers_gmac_src_include_proto_wpa.h.patch | 175 + ...cmdrivers_gmac_src_include_sbchipc.h.patch | 2523 + ...mdrivers_gmac_src_include_sbconfig.h.patch | 282 + ...mdrivers_gmac_src_include_sbhndarm.h.patch | 299 + ...mdrivers_gmac_src_include_sbhnddma.h.patch | 409 + ...mdrivers_gmac_src_include_sbsocram.h.patch | 199 + ...cmdrivers_gmac_src_include_siutils.h.patch | 262 + ...bcmdrivers_gmac_src_include_trxhdr.h.patch | 92 + ...mdrivers_gmac_src_include_typedefs.h.patch | 458 + ...cmdrivers_gmac_src_include_wlioctl.h.patch | 4889 + ...bcmdrivers_gmac_src_shared_aiutils.c.patch | 1269 + ...s_gmac_src_shared_bcmiproc_phy5221.c.patch | 515 + ..._gmac_src_shared_bcmiproc_phy5461s.c.patch | 740 + ...ac_src_shared_bcmiproc_robo_serdes.c.patch | 434 + ...rs_gmac_src_shared_bcmiproc_serdes.c.patch | 487 + ..._bcmdrivers_gmac_src_shared_bcmotp.c.patch | 3797 + ...bcmdrivers_gmac_src_shared_bcmrobo.c.patch | 1554 + ...bcmdrivers_gmac_src_shared_bcmsrom.c.patch | 5115 ++ ...cmdrivers_gmac_src_shared_bcmutils.c.patch | 3259 + ..._bcmdrivers_gmac_src_shared_hnddma.c.patch | 3575 + ..._bcmdrivers_gmac_src_shared_hndfwd.c.patch | 231 + ...cmdrivers_gmac_src_shared_hr2_erom.c.patch | 70 + ...cmdrivers_gmac_src_shared_hr2_erom.h.patch | 32 + ...cmdrivers_gmac_src_shared_hx4_erom.c.patch | 71 + ...cmdrivers_gmac_src_shared_hx4_erom.h.patch | 32 + ...cmdrivers_gmac_src_shared_kt2_erom.c.patch | 71 + ...cmdrivers_gmac_src_shared_kt2_erom.h.patch | 32 + ...mdrivers_gmac_src_shared_linux_osl.c.patch | 1719 + ...cmdrivers_gmac_src_shared_nsp_erom.c.patch | 73 + ...cmdrivers_gmac_src_shared_nsp_erom.h.patch | 32 + ...drivers_gmac_src_shared_nvramstubs.c.patch | 371 + ...bcmdrivers_gmac_src_shared_siutils.c.patch | 1542 + ...ivers_gmac_src_shared_siutils_priv.h.patch | 265 + ...bcmdrivers_gmac_src_shared_wl_config.patch | 32 + .../drivers_bcmdrivers_gpio_.gitignore.patch | 18 + .../drivers_bcmdrivers_gpio_Kconfig.patch | 17 + .../drivers_bcmdrivers_gpio_Makefile.patch | 9 + .../drivers_bcmdrivers_gpio_gpio.c.patch | 750 + .../drivers_bcmdrivers_gpio_gpio.h.patch | 107 + .../drivers_bcmdrivers_gpio_gpio_cfg.c.patch | 408 + .../drivers_bcmdrivers_gpio_gpio_cfg.h.patch | 113 + .../drivers_bcmdrivers_gpio_gpiolib.c.patch | 265 + ...rivers_bcmdrivers_include_Readme.txt.patch | 7 + .../drivers_bcmdrivers_mdio_.gitignore.patch | 14 + .../drivers_bcmdrivers_mdio_Kconfig.patch | 14 + .../drivers_bcmdrivers_mdio_Makefile.patch | 9 + ...drivers_bcmdrivers_mdio_iproc_mdio.c.patch | 591 + ...drivers_bcmdrivers_mdio_iproc_mdio.h.patch | 88 + ...ers_bcmdrivers_mdio_iproc_mdio_dev.h.patch | 50 + .../drivers_bcmdrivers_nand_.gitignore.patch | 14 + .../drivers_bcmdrivers_nand_Kconfig.patch | 30 + .../drivers_bcmdrivers_nand_Makefile.patch | 8 + ...drivers_bcmdrivers_nand_nand_iproc.c.patch | 1739 + .../drivers_bcmdrivers_pmu_.gitignore.patch | 14 + .../drivers_bcmdrivers_pmu_Kconfig.patch | 15 + .../drivers_bcmdrivers_pmu_Makefile.patch | 14 + .../drivers_bcmdrivers_pmu_iproc-pmu.c.patch | 67 + .../drivers_bcmdrivers_pwm_.gitignore.patch | 14 + .../drivers_bcmdrivers_pwm_Kconfig.patch | 14 + .../drivers_bcmdrivers_pwm_Makefile.patch | 9 + .../drivers_bcmdrivers_pwm_iproc_pwmc.c.patch | 417 + ...ivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch | 581 + .../drivers_bcmdrivers_qspi_.gitignore.patch | 14 + .../drivers_bcmdrivers_qspi_Kconfig.patch | 78 + .../drivers_bcmdrivers_qspi_Makefile.patch | 9 + ...drivers_bcmdrivers_qspi_qspi_iproc.c.patch | 1813 + .../drivers_bcmdrivers_smbus_.gitignore.patch | 14 + .../drivers_bcmdrivers_smbus_Kconfig.patch | 14 + .../drivers_bcmdrivers_smbus_Makefile.patch | 9 + ...ivers_bcmdrivers_smbus_iproc_smbus.c.patch | 2049 + ...ivers_bcmdrivers_smbus_iproc_smbus.h.patch | 195 + ..._bcmdrivers_smbus_iproc_smbus_defs.h.patch | 53 + ..._bcmdrivers_smbus_iproc_smbus_regs.h.patch | 296 + .../drivers_bcmdrivers_timer_.gitignore.patch | 10 + .../drivers_bcmdrivers_timer_Kconfig.patch | 12 + .../drivers_bcmdrivers_timer_Makefile.patch | 8 + ...ivers_bcmdrivers_timer_iproc_timer.c.patch | 485 + ...ivers_bcmdrivers_timer_iproc_timer.h.patch | 100 + .../drivers_bcmdrivers_usb2h_.gitignore.patch | 14 + .../drivers_bcmdrivers_usb2h_Kconfig.patch | 31 + .../drivers_bcmdrivers_usb2h_Makefile.patch | 9 + ...drivers_bcmdrivers_usb2h_bcm-iproc.c.patch | 404 + .../drivers_bcmdrivers_usb2h_bcm_usbh.h.patch | 31 + .../drivers_bcmdrivers_usb2h_ehci-bcm.c.patch | 389 + .../drivers_bcmdrivers_usb2h_ohci-bcm.c.patch | 320 + .../drivers_bcmdrivers_usb2h_usbh_cfg.h.patch | 57 + .../drivers_bcmdrivers_wdt_.gitignore.patch | 10 + .../drivers_bcmdrivers_wdt_Kconfig.patch | 13 + .../drivers_bcmdrivers_wdt_Makefile.patch | 8 + .../drivers_bcmdrivers_wdt_iproc_wdt.c.patch | 496 + .../patches/drivers_cpuidle_cpuidle.c.patch | 53 + .../patches/drivers_cpuidle_cpuidle.h.patch | 29 + .../patches/drivers_cpuidle_sysfs.c.patch | 156 + .../drivers_crypto_padlock-aes.c.patch | 32 + .../drivers_crypto_padlock-sha.c.patch | 42 + .../3.2-lts/patches/drivers_dma_Kconfig.patch | 16 + .../patches/drivers_dma_imx-sdma.c.patch | 16 + .../patches/drivers_gpio_Kconfig.patch | 49 + .../patches/drivers_gpio_gpio-mpc8xxx.c.patch | 12 + .../patches/drivers_gpio_gpio-pca953x.c.patch | 837 + .../patches/drivers_gpio_gpio-sch.c.patch | 195 + .../patches/drivers_hwmon_Kconfig.patch | 87 + .../patches/drivers_hwmon_Makefile.patch | 28 + .../patches/drivers_hwmon_adt7470.c.patch | 35 + .../patches/drivers_hwmon_adt7475.c.patch | 26 + .../patches/drivers_hwmon_coretemp.c.patch | 40 + .../patches/drivers_hwmon_cy8c3245r1.c.patch | 1087 + .../patches/drivers_hwmon_cy8cxx.c.patch | 1090 + .../patches/drivers_hwmon_emc2305.c.patch | 880 + .../patches/drivers_hwmon_it87.c.patch | 189 + .../patches/drivers_hwmon_max6620.c.patch | 666 + .../patches/drivers_hwmon_max6639.c.patch | 456 + .../patches/drivers_hwmon_max6697.c.patch | 707 + .../patches/drivers_hwmon_pmbus_Kconfig.patch | 39 + .../drivers_hwmon_pmbus_Makefile.patch | 12 + .../drivers_hwmon_pmbus_cpr4011.c.patch | 89 + .../drivers_hwmon_pmbus_dps460.c.patch | 106 + .../patches/drivers_hwmon_pmbus_pmbus.h.patch | 20 + .../drivers_hwmon_pmbus_pmbus_core.c.patch | 267 + .../drivers_hwmon_pmbus_ps2471.c.patch | 94 + .../patches/drivers_hwmon_via-cputemp.c.patch | 38 + .../patches/drivers_i2c_busses_Kconfig.patch | 39 + .../patches/drivers_i2c_busses_Makefile.patch | 21 + .../patches/drivers_i2c_i2c-mux.c.patch | 112 + .../patches/drivers_i2c_muxes_Kconfig.patch | 21 + .../patches/drivers_i2c_muxes_Makefile.patch | 13 + .../drivers_i2c_muxes_gpio-i2cmux.c.patch | 14 + .../patches/drivers_i2c_muxes_pca9541.c.patch | 14 + .../patches/drivers_i2c_muxes_pca954x.c.patch | 45 + .../patches/drivers_misc_Kconfig.patch | 60 + .../patches/drivers_misc_Makefile.patch | 12 + .../patches/drivers_misc_ds100df410.c.patch | 332 + .../drivers_misc_early_dma_alloc.c.patch | 228 + .../patches/drivers_misc_eeprom_Kconfig.patch | 38 + .../drivers_misc_eeprom_Makefile.patch | 14 + .../patches/drivers_misc_eeprom_at24.c.patch | 205 + .../drivers_misc_eeprom_eeprom_class.c.patch | 200 + ...rivers_misc_eeprom_sff_8436_eeprom.c.patch | 1231 + ...ivers_misc_iwmc3200top_fw-download.c.patch | 18 + .../drivers_misc_retimer_class.c.patch | 165 + .../patches/drivers_misc_ti-st_st_kim.c.patch | 17 + .../patches/drivers_mtd_chips_Kconfig.patch | 25 + .../drivers_mtd_chips_cfi_cmdset_0020.c.patch | 15 + .../patches/drivers_mtd_devices_Kconfig.patch | 20 + .../drivers_mtd_devices_m25p80.c.patch | 143 + .../drivers_mtd_maps_physmap_of.c.patch | 31 + .../patches/drivers_mtd_mtdoops.c.patch | 14 + .../patches/drivers_mtd_ubi_build.c.patch | 13 + .../patches/drivers_net_Makefile.patch | 27 + ...drivers_net_can_softing_softing_fw.c.patch | 18 + ...drivers_net_ethernet_broadcom_bnx2.c.patch | 65 + ..._ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch | 98 + ...ernet_broadcom_bnx2x_bnx2x_ethtool.c.patch | 21 + ...ethernet_broadcom_bnx2x_bnx2x_main.c.patch | 17 + .../drivers_net_ethernet_broadcom_tg3.c.patch | 50 + .../patches/drivers_net_phy_mdio_bus.c.patch | 77 + .../patches/drivers_net_phy_phy.c.patch | 51 + .../drivers_net_phy_phy_device.c.patch | 342 + .../patches/drivers_of_of_mdio.c.patch | 48 + .../patches/drivers_of_platform.c.patch | 41 + .../patches/drivers_pci_access.c.patch | 210 + .../3.2-lts/patches/drivers_pci_msi.c.patch | 190 + .../3.2-lts/patches/drivers_pci_pci.c.patch | 23 + .../patches/drivers_pci_pcie_aspm.c.patch | 30 + .../3.2-lts/patches/drivers_pci_probe.c.patch | 14 + .../patches/drivers_pci_quirks.c.patch | 63 + .../patches/drivers_pci_setup-res.c.patch | 17 + .../patches/drivers_rtc_hctosys.c.patch | 86 + .../patches/drivers_rtc_rtc-m41t80.c.patch | 170 + .../patches/drivers_rtc_rtc-mv.c.patch | 32 + .../patches/drivers_rtc_rtc-s35390a.c.patch | 161 + .../patches/drivers_tty_cyclades.c.patch | 16 + .../3.2-lts/patches/drivers_tty_moxa.c.patch | 19 + .../patches/drivers_tty_serial_icom.c.patch | 28 + .../drivers_tty_serial_ucc_uart.c.patch | 16 + .../patches/drivers_usb_host_ehci-hcd.c.patch | 63 + .../patches/drivers_usb_host_ehci-hub.c.patch | 91 + .../patches/drivers_usb_host_ohci-hcd.c.patch | 17 + .../patches/drivers_usb_misc_emi26.c.patch | 29 + .../patches/drivers_usb_misc_emi62.c.patch | 27 + .../drivers_usb_serial_io_edgeport.c.patch | 17 + .../patches/drivers_usb_serial_io_ti.c.patch | 22 + .../drivers_usb_serial_keyspan.c.patch | 16 + .../drivers_usb_serial_keyspan_pda.c.patch | 17 + ...rivers_usb_serial_ti_usb_3410_5052.c.patch | 16 + .../drivers_usb_serial_whiteheat.c.patch | 25 + .../patches/drivers_watchdog_Kconfig.patch | 24 + .../patches/drivers_watchdog_Makefile.patch | 12 + .../drivers_watchdog_booke_wdt.c.patch | 314 + .../patches/drivers_watchdog_iTCO_wdt.c.patch | 283 + .../drivers_watchdog_ie6xx_wdt.c.patch | 353 + .../drivers_watchdog_sp5100_tco.c.patch | 15 + .../base/any/kernels/3.2-lts/patches/foopatch | 74956 ++++++++++++++++ ..._asm-generic_io-64-nonatomic-hi-lo.h.patch | 34 + ..._asm-generic_io-64-nonatomic-lo-hi.h.patch | 33 + .../patches/include_linux_amba_bus.h.patch | 42 + .../patches/include_linux_audit.h.patch | 30 + .../patches/include_linux_bitops.h.patch | 28 + .../include_linux_ceph_messenger.h.patch | 16 + .../patches/include_linux_connector.h.patch | 12 + .../3.2-lts/patches/include_linux_cpu.h.patch | 63 + .../patches/include_linux_dcache.h.patch | 36 + .../include_linux_device-mapper.h.patch | 15 + .../patches/include_linux_device.h.patch | 177 + .../patches/include_linux_dma-mapping.h.patch | 25 + .../patches/include_linux_dmaengine.h.patch | 27 + .../3.2-lts/patches/include_linux_dmi.h.patch | 20 + ...include_linux_dynamic_queue_limits.h.patch | 103 + .../include_linux_early_dma_alloc.h.patch | 42 + .../include_linux_eeprom_class.h.patch | 84 + .../3.2-lts/patches/include_linux_efi.h.patch | 193 + .../patches/include_linux_ethtool.h.patch | 61 + .../include_linux_ftrace_event.h.patch | 23 + .../patches/include_linux_hashtable.h.patch | 197 + .../include_linux_i2c-mux-gpio.h.patch | 48 + .../patches/include_linux_i2c-mux.h.patch | 14 + .../3.2-lts/patches/include_linux_i2c.h.patch | 24 + .../patches/include_linux_i2c_at24.h.patch | 24 + .../patches/include_linux_i2c_pca953x.h.patch | 14 + .../include_linux_i2c_sff-8436.h.patch | 38 + .../patches/include_linux_if_bridge.h.patch | 132 + .../patches/include_linux_if_ether.h.patch | 14 + .../patches/include_linux_if_link.h.patch | 210 + .../patches/include_linux_if_tun.h.patch | 40 + .../patches/include_linux_init.h.patch | 27 + .../patches/include_linux_irqdesc.h.patch | 24 + .../patches/include_linux_jbd2.h.patch | 14 + .../patches/include_linux_jiffies.h.patch | 16 + .../patches/include_linux_kvm_host.h.patch | 12 + .../patches/include_linux_mdio.h.patch | 61 + .../3.2-lts/patches/include_linux_mii.h.patch | 27 + .../patches/include_linux_mm_types.h.patch | 23 + .../include_linux_mod_devicetable.h.patch | 44 + .../patches/include_linux_mroute.h.patch | 13 + .../3.2-lts/patches/include_linux_msi.h.patch | 12 + .../patches/include_linux_mtd_cfi.h.patch | 60 + .../include_linux_mtd_cfi_endian.h.patch | 77 + .../patches/include_linux_mtd_map.h.patch | 15 + .../patches/include_linux_neighbour.h.patch | 26 + .../patches/include_linux_of_mdio.h.patch | 13 + .../3.2-lts/patches/include_linux_pci.h.patch | 101 + .../patches/include_linux_pci_ids.h.patch | 28 + .../patches/include_linux_pci_regs.h.patch | 27 + .../patches/include_linux_percpu.h.patch | 16 + .../patches/include_linux_perf_event.h.patch | 38 + .../3.2-lts/patches/include_linux_phy.h.patch | 112 + .../include_linux_pid_namespace.h.patch | 13 + .../patches/include_linux_pkt_sched.h.patch | 90 + ...nclude_linux_platform_data_max6697.h.patch | 41 + .../include_linux_platform_device.h.patch | 34 + .../patches/include_linux_port.h.patch | 84 + .../patches/include_linux_pps_kernel.h.patch | 20 + .../patches/include_linux_ptrace.h.patch | 14 + .../patches/include_linux_random.h.patch | 47 + .../include_linux_regulator_consumer.h.patch | 19 + .../include_linux_retimer_class.h.patch | 40 + .../patches/include_linux_rmap.h.patch | 40 + .../patches/include_linux_skbuff.h.patch | 31 + .../patches/include_linux_slab_def.h.patch | 13 + .../patches/include_linux_snmp.h.patch | 23 + .../patches/include_linux_swiotlb.h.patch | 13 + .../patches/include_linux_sysctl.h.patch | 12 + .../patches/include_linux_sysfs.h.patch | 19 + .../patches/include_linux_sysrq.h.patch | 13 + .../3.2-lts/patches/include_linux_tcp.h.patch | 15 + .../include_linux_u64_stats_sync.h.patch | 17 + .../3.2-lts/patches/include_linux_usb.h.patch | 51 + .../include_linux_usb_ehci_def.h.patch | 60 + .../patches/include_linux_usb_hcd.h.patch | 16 + .../patches/include_linux_vmalloc.h.patch | 12 + .../patches/include_linux_watchdog.h.patch | 18 + .../patches/include_trace_syscall.h.patch | 14 + .../3.2-lts/patches/init_Kconfig.patch | 19 + .../patches/kernel-fs-overlayfs-inode.patch | 12 + .../patches/kernel-overlayfs-v11.patch | 3178 + .../3.2-lts/patches/lib_Kconfig.debug.patch | 35 + .../kernels/3.2-lts/patches/lib_Kconfig.patch | 14 + .../3.2-lts/patches/lib_Makefile.patch | 14 + .../patches/lib_dynamic_queue_limits.c.patch | 143 + .../3.2-lts/patches/lib_nlattr.c.patch | 15 + .../3.2-lts/patches/lib_swiotlb.c.patch | 26 + .../3.2-lts/patches/mm_backing-dev.c.patch | 13 + .../3.2-lts/patches/mm_memcontrol.c.patch | 14 + .../kernels/3.2-lts/patches/mm_rmap.c.patch | 14 + .../kernels/3.2-lts/patches/mm_slab.c.patch | 13 + .../3.2-lts/patches/mm_sparse-vmemmap.c.patch | 20 + .../kernels/3.2-lts/patches/mm_swap.c.patch | 14 + .../3.2-lts/patches/mm_truncate.c.patch | 14 + .../3.2-lts/patches/mm_vmalloc.c.patch | 47 + .../kernels/3.2-lts/patches/mm_vmscan.c.patch | 13 + .../3.2-lts/patches/overlayfs_notify.patch | 264 + ...latform-accton-as4610-device-drivers.patch | 3932 + .../patches/scripts_Makefile.fwinst.patch | 13 + .../patches/scripts_kconfig_conf.c.patch | 121 + .../patches/scripts_kconfig_confdata.c.patch | 27 + .../patches/scripts_kconfig_expr.h.patch | 13 + .../patches/scripts_kconfig_lkc_proto.h.patch | 12 + .../patches/scripts_mod_file2alias.c.patch | 46 + .../patches/scripts_package_Makefile.patch | 31 + .../base/any/kernels/3.2-lts/patches/series | 508 + .../tools_include_tools_be_byteshift.h.patch | 76 + .../tools_include_tools_le_byteshift.h.patch | 73 + 514 files changed, 196892 insertions(+) create mode 100644 packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore create mode 100644 packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/Makefile create mode 100644 packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config create mode 100644 packages/base/any/kernels/3.2-lts/kconfig.mk create mode 100644 packages/base/any/kernels/3.2-lts/patches/Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc_cru.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_sysfs.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm-iproc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/foopatch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/series create mode 100644 packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch create mode 100644 packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore new file mode 100644 index 00000000..3898a1cf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/.gitignore @@ -0,0 +1,2 @@ +linux-3.2* +kernel-3.2* diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/Makefile b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/Makefile new file mode 100644 index 00000000..06577e25 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/Makefile @@ -0,0 +1,41 @@ +############################################################ +# +# +# Copyright 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ + +THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +include $(ONL)/make/config.mk + +ifndef K_TARGET_DIR +K_TARGET_DIR := $(THIS_DIR) +endif + +include ../../kconfig.mk +K_CONFIG := arm-iproc-all.config +K_BUILD_TARGET := Image +K_COPY_SRC := arch/arm/boot/Image +K_COPY_GZIP := 1 +ifndef K_COPY_DST +K_COPY_DST := kernel-3.2-deb7-arm-iproc-all.bin.gz +endif + +export ARCH=arm +DTS_LIST := accton_as4610_54 + +include $(ONL)/make/kbuild.mk diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config new file mode 100644 index 00000000..8aa366c4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config @@ -0,0 +1,2432 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.2.84 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="arm-linux-gnueabi-" +CONFIG_LOCALVERSION="-OpenNetworkLinux" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="onl" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +CONFIG_RD_XZ=y +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_ZYNQ is not set +CONFIG_ARCH_IPROC=y +CONFIG_BCM_ZRELADDR=0x61008000 +CONFIG_GPIO_PCA953X=y + +# +# Broadcom IPROC architecture based implementations +# +# CONFIG_ARCH_NORTHSTAR is not set +CONFIG_MACH_IPROC=y +# CONFIG_IPROC_64K_PAGE is not set +CONFIG_GP_TIMER_COMPARATOR_LOAD_DELAY=y +CONFIG_IPROC_DCACHE_INVALIDATION=y +# CONFIG_IPROC_TIMER_UNIT_TESTS is not set +# CONFIG_IPROC_SW_RESET_RECORD is not set +# CONFIG_BRCM_PROP_MODULES is not set +# CONFIG_BCM_STM is not set +CONFIG_BCM_PARAMS_PHYS=0x61000000 +CONFIG_BCM_RAM_BASE=0x60000000 +CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000 + +# +# iProc SoC based Machine types +# +# CONFIG_MACH_CYGNUS is not set +# CONFIG_MACH_NS is not set +# CONFIG_MACH_HX4 is not set +# CONFIG_MACH_HR2 is not set +# CONFIG_MACH_NSP is not set +# CONFIG_MACH_KT2 is not set +# CONFIG_MACH_GH is not set +# CONFIG_MACH_DNI_3448P is not set +CONFIG_MACH_ACCTON_AS4610_54=y +# CONFIG_MACH_IPROC_EMULATION is not set + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_SWP_EMULATE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCCARD=y +CONFIG_PCMCIA=y +# CONFIG_PCMCIA_LOAD_CIS is not set +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +# CONFIG_YENTA is not set +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IP_PIMSM_V1 is not set +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETWORK_PHY_TIMESTAMPING=y +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_HAVE_BPF_JIT=y +# CONFIG_BPF_JIT is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_OF_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_INTEL_VR_NOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M25PXX_STAY_IN_3BYTE_MODE is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_DENALI is not set +CONFIG_MTD_NAND_GPIO=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +CONFIG_VIRTIO_BLK=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_PHANTOM is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +CONFIG_EARLY_DMA_ALLOC=y +CONFIG_EDA_DEF_SIZE=0x04000000 +CONFIG_EDA_DEF_ALIGN=0x00100000 +# CONFIG_RETIMER_CLASS is not set +# CONFIG_DS100DF410 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_CLASS=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_SFF_8436 is not set +CONFIG_EEPROM_ACCTON_AS4610_SFP=y +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_SATA_PMP is not set + +# +# Controllers with non-SFF native interface +# +# CONFIG_SATA_AHCI is not set +# CONFIG_SATA_AHCI_PLATFORM is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +# CONFIG_ATA_BMDMA is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +CONFIG_PATA_PCMCIA=y +CONFIG_PATA_PLATFORM=y +CONFIG_PATA_OF_PLATFORM=y +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y +# CONFIG_MULTICORE_RAID456 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=y +CONFIG_DM_SNAPSHOT=y +# CONFIG_DM_THIN_PROVISIONING is not set +CONFIG_DM_MIRROR=y +CONFIG_DM_RAID=y +# CONFIG_DM_LOG_USERSPACE is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +CONFIG_MII=y +# CONFIG_MACVLAN is not set +CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +# CONFIG_NET_VENDOR_AMD is not set +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_FARADAY is not set +CONFIG_NET_VENDOR_FUJITSU=y +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_FEALNX is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMC911X is not set +CONFIG_SMSC911X=y +# CONFIG_SMSC911X_ARCH_HOOKS is not set +# CONFIG_SMSC9420 is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_XIRCOM is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +CONFIG_SMSC_PHY=y +CONFIG_BROADCOM_PHY=y +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_TR is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_CS=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_HVC_DRIVER=y +# CONFIG_HVC_DCC is not set +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_VIRTIO=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_MUX_GPIO=y +CONFIG_I2C_MUX_PCA9541=y +CONFIG_I2C_MUX_PCA954x=y +# CONFIG_I2C_MUX_DNI_6448 is not set +# CONFIG_I2C_MUX_QUANTA is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_INTEL_MID is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set +# CONFIG_I2C_EG20T is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_VX855 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +CONFIG_SENSORS_ADM1021=y +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CY8CXX is not set +# CONFIG_SENSORS_CY8C3245R1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +CONFIG_SENSORS_LM75=y +CONFIG_SENSORS_LM77=y +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +CONFIG_SENSORS_LM85=y +# CONFIG_SENSORS_LM87 is not set +CONFIG_SENSORS_LM90=y +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4151 is not set +CONFIG_SENSORS_LTC4215=y +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +CONFIG_SENSORS_MAX6650=y +CONFIG_SENSORS_MAX6620=y +CONFIG_SENSORS_MAX6697=y +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +CONFIG_SENSORS_EMC2305=y +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +CONFIG_SENSORS_W83781D=y +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_SENSORS_ACCTON_I2C_CPLD=y +CONFIG_SENSORS_ACCTON_AS4610_FAN=y +CONFIG_SENSORS_ACCTON_AS4610_PSU=y +CONFIG_SENSORS_YM2651Y=y +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_DRM is not set +# CONFIG_STUB_POULSBO is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set +# CONFIG_HID_PID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_XHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CONSOLE=y +# CONFIG_USB_EZUSB is not set +# CONFIG_USB_SERIAL_GENERIC is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SDRICOH_CS is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +CONFIG_LEDS_ACCTON_AS4610=y +# CONFIG_LEDS_TRIGGERS is not set + +# +# LED Triggers +# +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS1374=y +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +CONFIG_RTC_DRV_M41T80=y +# CONFIG_RTC_DRV_M41T80_WDT is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +CONFIG_VIRTIO=y +CONFIG_VIRTIO_RING=y + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_MACH_CLKDEV=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# Broadcom iProc Drivers +# +# CONFIG_IPROC_CCB_TIMER is not set +CONFIG_IPROC_MDIO=y +# CONFIG_IPROC_DMA is not set +CONFIG_IPROC_GPIO=y +CONFIG_IPROC_QSPI=y +CONFIG_IPROC_QSPI_SINGLE_MODE=y +# CONFIG_IPROC_QSPI_DUAL_MODE is not set +# CONFIG_IPROC_QSPI_QUAD_MODE is not set +CONFIG_IPROC_QSPI_MAX_HZ=62500000 +# CONFIG_IPROC_MTD_NAND is not set +# CONFIG_IPROC_PWM is not set +CONFIG_IPROC_USB2H=y +CONFIG_USB_EHCI_BCM=y +CONFIG_IPROC_GMAC=y + +# +# Broadcom HND network devices +# +CONFIG_HND=y +CONFIG_ET=y +CONFIG_ET_47XX=y +# CONFIG_ET_NAPI2_POLL is not set +# CONFIG_BCM_CTF is not set +# CONFIG_BCM_CTF2 is not set +# CONFIG_BCM_IPROC_GMAC_ACP is not set +# CONFIG_BCM_IPROC_GMAC_PREFETCH is not set +# CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING is not set +# CONFIG_BCM_IPROC_GMAC_LOCK_OPT is not set +# CONFIG_BCM_IPROC_GMAC_RWREG_OPT is not set +# CONFIG_BCM_IPROC_GMAC_SG is not set +# CONFIG_WL_EMULATOR is not set +# CONFIG_BCM57XX is not set +# CONFIG_WL is not set +# CONFIG_WL_USBAP is not set +CONFIG_WL_AP="" +CONFIG_WL_AP_SDSTD="" +CONFIG_WL_STA="" +CONFIG_WL_APSTA="" +CONFIG_WL_AP_ONCHIP_G="" +CONFIG_WL_STA_ONCHIP_G="" +CONFIG_WL_HIGH="" +CONFIG_IPROC_SDK_MGT_PORT_HANDOFF=y +# CONFIG_IPROC_2STAGE_RX is not set +CONFIG_IPROC_I2C=y +# CONFIG_IPROC_PMU is not set +# CONFIG_BCM_IPROC_CA9_PREFETCH is not set +# CONFIG_BCM_BARRIER_PERFORMANCE is not set +# CONFIG_BCM_MEM_OPTIMIZATION is not set +# CONFIG_BROADCOM_CUSTOM_SENDFILE is not set +# CONFIG_BCM_CUSTOM_RECVFILE is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INOTIFY_STACKFS=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_OVERLAYFS_FS=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFS_USE_NEW_IDMAPPER is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_MASK=0x1 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y +CONFIG_ASYNC_PQ=y +CONFIG_ASYNC_RAID6_RECOV=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=y +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set diff --git a/packages/base/any/kernels/3.2-lts/kconfig.mk b/packages/base/any/kernels/3.2-lts/kconfig.mk new file mode 100644 index 00000000..bbaa91cb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/kconfig.mk @@ -0,0 +1,27 @@ +############################################################ +# +# +# Copyright 2015 Big Switch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ + +THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +K_MAJOR_VERSION := 3 +K_PATCH_LEVEL := 2 +K_SUB_LEVEL := 84 +K_SUFFIX := +K_PATCH_DIR := $(THIS_DIR)/patches diff --git a/packages/base/any/kernels/3.2-lts/patches/Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/Makefile.patch new file mode 100644 index 00000000..fb3eefaf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/Makefile.patch @@ -0,0 +1,131 @@ +--- a/Makefile ++++ b/Makefile +@@ -195,46 +195,6 @@ export KBUILD_BUILDHOST := $(SUBARCH) + ARCH ?= $(SUBARCH) + CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) + +-# Architecture as present in compile.h +-UTS_MACHINE := $(ARCH) +-SRCARCH := $(ARCH) +- +-# Additional ARCH settings for x86 +-ifeq ($(ARCH),i386) +- SRCARCH := x86 +-endif +-ifeq ($(ARCH),x86_64) +- SRCARCH := x86 +-endif +- +-# Additional ARCH settings for sparc +-ifeq ($(ARCH),sparc32) +- SRCARCH := sparc +-endif +-ifeq ($(ARCH),sparc64) +- SRCARCH := sparc +-endif +- +-# Additional ARCH settings for sh +-ifeq ($(ARCH),sh64) +- SRCARCH := sh +-endif +- +-# Additional ARCH settings for tile +-ifeq ($(ARCH),tilepro) +- SRCARCH := tile +-endif +-ifeq ($(ARCH),tilegx) +- SRCARCH := tile +-endif +- +-# Where to locate arch specific headers +-hdr-arch := $(SRCARCH) +- +-ifeq ($(ARCH),m68knommu) +- hdr-arch := m68k +-endif +- + KCONFIG_CONFIG ?= .config + export KCONFIG_CONFIG + +@@ -354,6 +314,44 @@ CFLAGS_KERNEL = + AFLAGS_KERNEL = + CFLAGS_GCOV = -fprofile-arcs -ftest-coverage + ++-include $(obj)/.kernelvariables ++ ++# Architecture as present in compile.h ++UTS_MACHINE := $(ARCH) ++SRCARCH := $(ARCH) ++ ++# Additional ARCH settings for x86 ++ifeq ($(ARCH),i386) ++ SRCARCH := x86 ++endif ++ifeq ($(ARCH),x86_64) ++ SRCARCH := x86 ++endif ++ ++# Additional ARCH settings for sparc ++ifeq ($(ARCH),sparc64) ++ SRCARCH := sparc ++endif ++ ++# Additional ARCH settings for sh ++ifeq ($(ARCH),sh64) ++ SRCARCH := sh ++endif ++ ++# Additional ARCH settings for tile ++ifeq ($(ARCH),tilepro) ++ SRCARCH := tile ++endif ++ifeq ($(ARCH),tilegx) ++ SRCARCH := tile ++endif ++ ++# Where to locate arch specific headers ++hdr-arch := $(SRCARCH) ++ ++ifeq ($(ARCH),m68knommu) ++ hdr-arch := m68k ++endif + + # Use LINUXINCLUDE when you must reference the include/ directory. + # Needed to be compatible with the O= option +@@ -978,7 +976,7 @@ endif + prepare2: prepare3 outputmakefile asm-generic + + prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ +- include/config/auto.conf ++ include/config/auto.conf include/generated/package.h + $(cmd_crmodverdir) + + archprepare: archscripts prepare1 scripts_basic +@@ -1010,12 +1008,25 @@ define filechk_version.h + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) + endef + ++ifneq ($(DISTRIBUTION_OFFICIAL_BUILD),) ++define filechk_package.h ++ echo \#define LINUX_PACKAGE_ID \" $(DISTRIBUTOR) $(DISTRIBUTION_VERSION)\" ++endef ++else ++define filechk_package.h ++ echo \#define LINUX_PACKAGE_ID \"\" ++endef ++endif ++ + include/linux/version.h: $(srctree)/Makefile FORCE + $(call filechk,version.h) + + include/generated/utsrelease.h: include/config/kernel.release FORCE + $(call filechk,utsrelease.h) + ++include/generated/package.h: $(srctree)/Makefile FORCE ++ $(call filechk,package.h) ++ + PHONY += headerdep + headerdep: + $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 082bd36..7a06e22 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch new file mode 100644 index 00000000..47cb8e3e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Kconfig.patch @@ -0,0 +1,85 @@ +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -30,6 +30,7 @@ config ARM + select HAVE_SPARSE_IRQ + select GENERIC_IRQ_SHOW + select CPU_PM if (SUSPEND || CPU_IDLE) ++ select HAVE_BPF_JIT + help + The ARM series is a line of low-power-consumption RISC chip designs + licensed by ARM Ltd and targeted at embedded applications and +@@ -161,6 +162,13 @@ config ARCH_HAS_CPUFREQ + config ARCH_HAS_CPU_IDLE_WAIT + def_bool y + ++-config ARCH_SUPPORTS_BIG_ENDIAN ++ bool ++ default y if ARCH_IXP4XX ++ help ++ Internal node to specify the architecture can run in Big Endian ++ mode. ++ + config GENERIC_HWEIGHT + bool + default y +@@ -978,6 +986,30 @@ config ARCH_ZYNQ + select USE_OF + help + Support for Xilinx Zynq ARM Cortex A9 Platform ++ ++config ARCH_IPROC ++ bool "Broadcom ARMv7 iProc boards" ++ depends on MMU ++ select CPU_V7 ++ select HAVE_CLK ++ select HAVE_SMP ++ select HAVE_MACH_CLKDEV ++ select COMMON_CLKDEV ++ select CLKDEV_LOOKUP ++ select ARM_GIC ++ select HAVE_ARM_SCU ++ select GENERIC_CLOCKEVENTS_BUILD ++ select GENERIC_CLOCKEVENTS ++ select PCI ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select CACHE_L2X0 ++ select ARM_AMBA ++ select ARCH_HAS_CPUFREQ ++ select MULTI_IRQ_HANDLER ++ help ++ This is a common family of Broadcom Cortex A9 based boards ++ + endchoice + + # +@@ -1013,6 +1045,8 @@ source "arch/arm/mach-iop33x/Kconfig" + + source "arch/arm/mach-iop13xx/Kconfig" + ++source "arch/arm/plat-iproc/Kconfig" ++ + source "arch/arm/mach-ixp4xx/Kconfig" + + source "arch/arm/mach-ixp2000/Kconfig" +@@ -1023,6 +1057,8 @@ source "arch/arm/mach-kirkwood/Kconfig" + + source "arch/arm/mach-ks8695/Kconfig" + ++source "arch/arm/mach-iproc/Kconfig" ++ + source "arch/arm/mach-lpc32xx/Kconfig" + + source "arch/arm/mach-msm/Kconfig" +@@ -1452,7 +1488,8 @@ config SMP + depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ + MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ + ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ +- ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q ++ ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q || \ ++ ARCH_IPROC + depends on MMU + select USE_GENERIC_SMP_HELPERS + select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 362c7ca..e11f8ee 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch new file mode 100644 index 00000000..937a0d51 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_Makefile.patch @@ -0,0 +1,28 @@ +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -198,6 +198,7 @@ machine-$(CONFIG_MACH_SPEAR310) := spear3xx + machine-$(CONFIG_MACH_SPEAR320) := spear3xx + machine-$(CONFIG_MACH_SPEAR600) := spear6xx + machine-$(CONFIG_ARCH_ZYNQ) := zynq ++machine-$(CONFIG_MACH_IPROC) := iproc + + # Platform directory name. This list is sorted alphanumerically + # by CONFIG_* macro name. +@@ -214,6 +215,7 @@ plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung + plat-$(CONFIG_PLAT_S5P) := s5p samsung + plat-$(CONFIG_PLAT_SPEAR) := spear + plat-$(CONFIG_PLAT_VERSATILE) := versatile ++plat-$(CONFIG_ARCH_IPROC) := iproc + + ifeq ($(CONFIG_ARCH_EBSA110),y) + # This is what happens if you forget the IOCS16 line. +@@ -255,6 +257,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/ + + # If we have a machine-specific directory, then include it in the build. + core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ ++core-y += arch/arm/net/ + core-y += $(machdirs) $(platdirs) + + drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index 8c57359..6bfca86 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch new file mode 100644 index 00000000..f09f0cb3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_compressed_head.S.patch @@ -0,0 +1,13 @@ +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -18,6 +18,7 @@ + * 100% relocatable. Any attempt to do so will result in a crash. + * Please select one of the following when turning on debugging. + */ ++#define DEBUG 1 + #ifdef DEBUG + + #if defined(CONFIG_DEBUG_ICEDCC) +diff --git a/arch/arm/boot/dts/accton_as4610_54.dts b/arch/arm/boot/dts/accton_as4610_54.dts +new file mode 100644 +index 0000000..9276c0a diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch new file mode 100644 index 00000000..7737f9ef --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch @@ -0,0 +1,256 @@ +--- /dev/null ++++ b/arch/arm/boot/dts/accton_as4610_54.dts +@@ -0,0 +1,250 @@ ++/* ++ * Accton AS4610 54 Device Tree Source ++ * ++ * Copyright 2015, Cumulus Networks, Inc. ++ * ++ * 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; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++/dts-v1/; ++/include/ "helix4.dtsi" ++ ++/ { ++ model = "accton,as4610_54"; ++ compatible = "accton,as4610_54"; ++ ++ aliases { ++ serial0 = &uart0; ++ i2c-controller0 = &i2c0; ++ i2c-controller1 = &i2c1; ++ }; ++ ++ memory { ++ reg = <0x61000000 0x7f000000>; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x00>; ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x01>; ++ }; ++ }; ++ ++ localbus@1c000000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ /* NAND Flash */ ++ ranges = < ++ 0x0 0x0 0x0 0x1c000000 0x00120000 ++ 0x1 0x0 0x0 0x1c120000 0x00040000 ++ >; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x02000000>; ++ byteswap; ++ ++ partition@0 { ++ /* uboot */ ++ reg = <0x00000000 0x00100000>; ++ label = "uboot"; ++ }; ++ partition@1 { ++ /* uboot-env */ ++ reg = <0x00100000 0x00100000>; ++ label = "uboot-env"; ++ env_size = <0x2000>; ++ }; ++ partition@2 { ++ /* board_eeprom */ ++ reg = <0x00200000 0x00100000>; ++ label = "board_eeprom"; ++ }; ++ partition@3 { ++ /* shmoo */ ++ reg = <0x00300000 0x00100000>; ++ label = "shmoo"; ++ }; ++ partition@4 { ++ /* onie */ ++ reg = <0x00400000 0x00800000>; ++ label = "onie"; ++ }; ++ partition@5 { ++ /* open */ ++ reg = <0x00c00000 0x03c00000>; ++ label = "open"; ++ }; ++ partition@6 { ++ /* open2 */ ++ reg = <0x04800000 0x7d000000>; ++ label = "open2"; ++ }; ++ partition@7 { ++ /* diag */ ++ reg = <0xfec00000 0x01000000>; ++ label = "diag"; ++ }; ++ }; ++ }; ++ ++ i2c0: i2c@18038000 { ++ compatible = "iproc-smb"; ++ reg = <0x18038000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = < 127 >; ++ clock-frequency = <400000>; ++ cpld@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "accton,as4610-54-cpld"; ++ label = "cpld"; ++ reg = <0x30>; ++ }; ++ }; ++ ++ i2c1: i2c@1803b000 { ++ compatible = "iproc-smb"; ++ reg = <0x1803b000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = < 128 >; ++ clock-frequency = <100000>; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ deselect-on-exit; ++ ++ // SFP+ 1 ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port49"; ++ }; ++ }; ++ ++ // SFP+ 2 ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port50"; ++ }; ++ }; ++ ++ // SFP+ 3 ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port51"; ++ }; ++ }; ++ ++ // SFP+ 4 ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "port52"; ++ }; ++ }; ++ ++ // QSFP+ STK1 ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ }; ++ }; ++ ++ // QSFP+ STK2 ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ sfp_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ }; ++ }; ++ ++ // PSU EEPROM ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ psu_eeprom@50 { ++ compatible = "at,24c02"; ++ reg = <0x50>; ++ label = "psu1_eeprom"; ++ read-only; ++ }; ++ psu_eeprom@51 { ++ compatible = "at,24c02"; ++ reg = <0x51>; ++ label = "psu2_eeprom"; ++ read-only; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ ++ temp@48 { ++ compatible = "nxp,lm77"; ++ reg = <0x48>; ++ }; ++ ++ rtc@68 { ++ /* Actually M41T11 */ ++ compatible = "dallas,ds1307"; ++ reg = <0x68>; ++ }; ++ ++ board_eeprom@50 { ++ compatible = "at,24c04"; ++ reg = <0x50>; ++ label = "board_eeprom"; ++ }; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/dni_3448p.dts b/arch/arm/boot/dts/dni_3448p.dts +new file mode 100644 +index 0000000..29ce09c diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch new file mode 100644 index 00000000..61a1af5f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_dni_3448p.dts.patch @@ -0,0 +1,172 @@ +--- /dev/null ++++ b/arch/arm/boot/dts/dni_3448p.dts +@@ -0,0 +1,166 @@ ++/* ++ * Delta Networks, Inc. 3448p Device Tree Source ++ * ++ * Copyright 2015, Cumulus Networks, Inc. ++ * ++ * 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; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++/dts-v1/; ++/include/ "helix4.dtsi" ++ ++/ { ++ model = "dni,3448p"; ++ compatible = "dni,dni_3448p"; ++ ++ memory { ++ reg = <0x61000000 0x3f000000>; ++ }; ++ ++ aliases { ++ serial0 = &uart0; ++ i2c-controller0 = &i2c0; ++ i2c-controller1 = &i2c1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x00>; ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a9"; ++ next-level-cache = <&L2>; ++ reg = <0x01>; ++ }; ++ }; ++ ++ localbus@1c000000 { ++ #address-cells = <0x2>; ++ #size-cells = <0x1>; ++ /* NAND Flash */ ++ ranges = < ++ 0x0 0x0 0x0 0x1c000000 0x00120000 ++ 0x1 0x0 0x0 0x1c120000 0x00040000 ++ >; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x02000000>; ++ byteswap; ++ ++ partition@0 { ++ /* uboot */ ++ reg = <0x00000000 0x00100000>; ++ label = "uboot"; ++ }; ++ partition@1 { ++ /* uboot-env */ ++ reg = <0x00100000 0x00400000>; ++ label = "uboot-env"; ++ env_size = <0x10000>; ++ }; ++ partition@2 { ++ /* vpd */ ++ reg = <0x00500000 0x00200000>; ++ label = "vpd"; ++ }; ++ partition@3 { ++ /* shmoo */ ++ reg = <0x00700000 0x00200000>; ++ label = "shmoo"; ++ }; ++ partition@4 { ++ /* open */ ++ reg = <0x00900000 0xf9500000>; ++ label = "open"; ++ }; ++ partition@5 { ++ /* onie */ ++ reg = <0xf9e00000 0x00c00000>; ++ label = "onie"; ++ }; ++ partition@6 { ++ /* onie2 */ ++ reg = <0xfaa00000 0x00c00000>; ++ label = "onie2"; ++ }; ++ partition@7 { ++ /* board_eeprom */ ++ reg = <0xfb600000 0x00600000>; ++ label = "board_eeprom"; ++ }; ++ partition@8 { ++ /* diags */ ++ reg = <0xfbc00000 0x02000000>; ++ label = "diag"; ++ }; ++ partition@9 { ++ /* diags2 */ ++ reg = <0xfdc00000 0x02000000>; ++ label = "diag2"; ++ }; ++ }; ++ cpld@1,0 { ++ compatible = "dni,3448p-cpld"; ++ reg = <0x1 0x0 0x00040000>; ++ }; ++ }; ++ ++ i2c0: i2c@18038000 { ++ compatible = "iproc-smb"; ++ reg = <0x18038000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <0x0 127 0x0>; ++ clock-frequency = <100000>; ++ rtc@68 { ++ compatible = "stm,m41st85"; ++ reg = <0x68>; ++ }; ++ tmon@49 { ++ compatible = "ti,tmp75"; ++ reg = <0x49>; ++ }; ++ tmon@4a { ++ compatible = "ti,tmp75"; ++ reg = <0x4a>; ++ }; ++ CPLD1@1,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "dni,3448p-cpld"; ++ label = "cpld"; ++ reg = <0x28>; ++ }; ++ }; ++ ++ i2c1: i2c@1803b000 { ++ compatible = "iproc-smb"; ++ reg = <0x1803b000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = <0x0 128 0x0>; ++ clock-frequency = <100000>; ++ ++ fan@2c { ++ compatible = "maxim,max6639"; ++ reg = <0x2c>; ++ }; ++ psumux@01 { ++ compatible = "3448p-psu-mux"; ++ reg = <0x01>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/helix4.dtsi b/arch/arm/boot/dts/helix4.dtsi +new file mode 100644 +index 0000000..1a7ce9e diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch new file mode 100644 index 00000000..0d5d3e20 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_boot_dts_helix4.dtsi.patch @@ -0,0 +1,65 @@ +--- /dev/null ++++ b/arch/arm/boot/dts/helix4.dtsi +@@ -0,0 +1,59 @@ ++/include/ "skeleton.dtsi" ++ ++/ { ++ interrupt-parent = <&gic>; ++ ++ chipcommonA { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x18000000 0x00001000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ uart0: serial@0300 { ++ compatible = "ns16550"; ++ reg = <0x0300 0x100>; ++ interrupts = <123>; ++ clock-frequency = <100000000>; ++ status = "enabled"; ++ }; ++ }; ++ ++ mpcore { ++ compatible = "simple-bus"; ++ ranges = <0x00000000 0x19020000 0x00003000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ scu@0000 { ++ compatible = "arm,cortex-a9-scu"; ++ reg = <0x0000 0x100>; ++ }; ++ ++ gic: interrupt-controller@1000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x1000 0x1000>, ++ <0x0100 0x100>; ++ }; ++ ++ L2: cache-controller@2000 { ++ compatible = "arm,pl310-cache"; ++ reg = <0x2000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ clk_periph: periph { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <400000000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/kirkwood-dreamplug.dts b/arch/arm/boot/dts/kirkwood-dreamplug.dts +new file mode 100644 +index 0000000..a5376b8 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch new file mode 100644 index 00000000..5e544e90 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_common_gic.c.patch @@ -0,0 +1,44 @@ +--- a/arch/arm/common/gic.c ++++ b/arch/arm/common/gic.c +@@ -40,6 +40,8 @@ + #include + + #include ++#include ++#include + #include + #include + +@@ -215,6 +217,29 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) + #define gic_set_wake NULL + #endif + ++asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ++{ ++ u32 irqstat, irqnr; ++ ++ do { ++ irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK); ++ irqnr = irqstat & ~0x1c00; ++ ++ if (likely(irqnr > 15 && irqnr < 1021)) { ++ handle_IRQ(irqnr, regs); ++ continue; ++ } ++ if (irqnr < 16) { ++ writel_relaxed(irqstat, gic_cpu_base_addr + GIC_CPU_EOI); ++#ifdef CONFIG_SMP ++ do_IPI(irqnr, regs); ++#endif ++ continue; ++ } ++ break; ++ } while (1); ++} ++ + static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) + { + struct gic_chip_data *chip_data = irq_get_handler_data(irq); +diff --git a/arch/arm/configs/iproc_defconfig b/arch/arm/configs/iproc_defconfig +new file mode 100644 +index 0000000..c401047 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch new file mode 100644 index 00000000..7757265a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_configs_iproc_defconfig.patch @@ -0,0 +1,2430 @@ +--- /dev/null ++++ b/arch/arm/configs/iproc_defconfig +@@ -0,0 +1,2425 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.6.5 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_ARM_PATCH_PHYS_VIRT=y ++CONFIG_GENERIC_BUG=y ++CONFIG_HAVE_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_XZ=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_FHANDLE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_KTIME_SCALAR=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++# CONFIG_HIGH_RES_TIMERS is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_ROOT_UID=0 ++CONFIG_INITRAMFS_ROOT_GID=0 ++# CONFIG_RD_GZIP is not set ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_INITRAMFS_COMPRESSION_NONE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++# CONFIG_ELF_CORE is not set ++# CONFIG_BASE_FULL is not set ++CONFIG_FUTEX=y ++# CONFIG_EPOLL is not set ++# CONFIG_SIGNALFD is not set ++# CONFIG_TIMERFD is not set ++# CONFIG_EVENTFD is not set ++# CONFIG_SHMEM is not set ++# CONFIG_AIO is not set ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++# CONFIG_PERF_EVENTS is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_PCI_QUIRKS=y ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=y ++CONFIG_HAVE_DMA_CONTIGUOUS=y ++CONFIG_USE_GENERIC_SMP_HELPERS=y ++CONFIG_GENERIC_SMP_IDLE_THREAD=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=1 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++# CONFIG_SYSV68_PARTITION is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_PRIMA2 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LPC32XX is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_W90X900 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_PICOXCELL is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARCH_IPROC=y ++CONFIG_BCM_ZRELADDR=0x61008000 ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++ ++# ++# Broadcom IPROC architecture based implementations ++# ++# CONFIG_ARCH_NORTHSTAR is not set ++CONFIG_MACH_IPROC=y ++CONFIG_GP_TIMER_COMPARATOR_LOAD_DELAY=y ++CONFIG_IPROC_DCACHE_INVALIDATION=y ++# CONFIG_IPROC_TIMER_UNIT_TESTS is not set ++# CONFIG_IPROC_SW_RESET_RECORD is not set ++# CONFIG_BRCM_PROP_MODULES is not set ++# CONFIG_BCM_STM is not set ++CONFIG_BCM_PARAMS_PHYS=0x61000000 ++CONFIG_BCM_RAM_BASE=0x60000000 ++CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000 ++ ++# ++# Broadcom iProc Drivers ++# ++# CONFIG_IPROC_CCB_TIMER is not set ++# CONFIG_IPROC_RNG is not set ++CONFIG_IPROC_MDIO=y ++# CONFIG_IPROC_GSIO_SPI is not set ++# CONFIG_IPROC_SD is not set ++# CONFIG_IPROC_DMA is not set ++CONFIG_IPROC_GPIO=y ++CONFIG_IPROC_QSPI=y ++CONFIG_IPROC_QSPI_SINGLE_MODE=y ++# CONFIG_IPROC_QSPI_DUAL_MODE is not set ++# CONFIG_IPROC_QSPI_QUAD_MODE is not set ++CONFIG_IPROC_QSPI_MAX_HZ=62500000 ++CONFIG_IPROC_MTD_NAND=y ++# CONFIG_IPROC_MTD_NAND_USE_JFFS2 is not set ++# CONFIG_IPROC_MTD_NOR is not set ++# CONFIG_IPROC_PMU is not set ++# CONFIG_IPROC_PWM is not set ++CONFIG_IPROC_USB2H=y ++CONFIG_USB_EHCI_BCM=y ++CONFIG_USB_OHCI_BCM=y ++# CONFIG_IPROC_USB3H is not set ++CONFIG_IPROC_USB2D=m ++CONFIG_IPROC_PCIE=y ++# CONFIG_IPROC_PCIE_AER is not set ++CONFIG_IPROC_GMAC=y ++ ++# ++# Broadcom HND network devices ++# ++CONFIG_HND=y ++CONFIG_ET=y ++CONFIG_ET_47XX=y ++CONFIG_ET_ALL_PASSIVE_ON=y ++# CONFIG_ET_ALL_PASSIVE_RUNTIME is not set ++# CONFIG_BCM_CTF is not set ++# CONFIG_BCM_IPROC_GMAC_ACP is not set ++# CONFIG_WL_EMULATOR is not set ++# CONFIG_BCM57XX is not set ++# CONFIG_WL is not set ++# CONFIG_WL_USBAP is not set ++CONFIG_WL_AP="wlconfig_lx_router_ap" ++CONFIG_WL_AP_SDSTD="wlconfig_lx_router_ap_sdstd" ++CONFIG_WL_STA="wlconfig_lx_router_sta" ++CONFIG_WL_APSTA="wlconfig_lx_router_apsta" ++CONFIG_WL_AP_ONCHIP_G="wlconfig_lx_router_ap_1chipG" ++CONFIG_WL_STA_ONCHIP_G="wlconfig_lx_router_sta_1chipG" ++CONFIG_WL_HIGH="wlconfig_lx_router_high" ++# CONFIG_EMF is not set ++# CONFIG_IPROC_SND is not set ++CONFIG_IPROC_I2C=y ++# CONFIG_IPROC_SRA is not set ++# CONFIG_IPROC_TDM is not set ++ ++# ++# Broadcom iProc GPL Drivers ++# ++# CONFIG_IPROC_SND_CODEC_WM8955 is not set ++# CONFIG_IPROC_SND_CODEC_WM8750 is not set ++CONFIG_IPROC_CCB_WDT=y ++ ++# ++# iProc SoC based Machine types ++# ++# CONFIG_MACH_NS is not set ++# CONFIG_MACH_HX4 is not set ++# CONFIG_MACH_HR2 is not set ++# CONFIG_MACH_NSP is not set ++# CONFIG_MACH_KT2 is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++# CONFIG_SWP_EMULATE is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_NR_BANKS=8 ++CONFIG_CPU_HAS_PMU=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_458693 is not set ++# CONFIG_ARM_ERRATA_460075 is not set ++# CONFIG_ARM_ERRATA_742230 is not set ++# CONFIG_ARM_ERRATA_742231 is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_ARM_ERRATA_743622 is not set ++# CONFIG_ARM_ERRATA_751472 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++CONFIG_ARM_GIC=y ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_ARCH_SUPPORTS_MSI=y ++CONFIG_PCI_MSI=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++CONFIG_HAVE_ARM_SCU=y ++# CONFIG_ARM_ARCH_TIMER is not set ++CONFIG_HAVE_ARM_TWD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++CONFIG_LOCAL_TIMERS=y ++CONFIG_ARCH_NR_GPIO=0 ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++# CONFIG_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++# CONFIG_HIGHMEM is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_ALIGNMENT_TRAP=y ++# CONFIG_UACCESS_WITH_MEMCPY is not set ++# CONFIG_SECCOMP is not set ++# CONFIG_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++# CONFIG_USE_OF is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyS0,115200n8 maxcpus=2 mem=512M" ++CONFIG_CMDLINE_FROM_BOOTLOADER=y ++# CONFIG_CMDLINE_EXTEND is not set ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++# CONFIG_VFP is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_HAVE_AOUT=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++# CONFIG_UNIX_DIAG is not set ++# CONFIG_XFRM_USER is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++# CONFIG_IP_ROUTE_MULTIPATH is not set ++# CONFIG_IP_ROUTE_VERBOSE is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_ARPD=y ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++# CONFIG_INET_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++CONFIG_NETFILTER_DEBUG=y ++CONFIG_NETFILTER_ADVANCED=y ++CONFIG_BRIDGE_NETFILTER=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_NETLINK=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++CONFIG_NETFILTER_NETLINK_QUEUE=y ++CONFIG_NETFILTER_NETLINK_LOG=y ++CONFIG_NF_CONNTRACK=y ++CONFIG_NF_CONNTRACK_MARK=y ++CONFIG_NF_CONNTRACK_PROCFS=y ++# CONFIG_NF_CONNTRACK_EVENTS is not set ++# CONFIG_NF_CONNTRACK_TIMEOUT is not set ++# CONFIG_NF_CONNTRACK_TIMESTAMP is not set ++# CONFIG_NF_CT_PROTO_DCCP is not set ++# CONFIG_NF_CT_PROTO_SCTP is not set ++# CONFIG_NF_CT_PROTO_UDPLITE is not set ++# CONFIG_NF_CONNTRACK_AMANDA is not set ++CONFIG_NF_CONNTRACK_FTP=y ++# CONFIG_NF_CONNTRACK_H323 is not set ++# CONFIG_NF_CONNTRACK_IRC is not set ++# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set ++# CONFIG_NF_CONNTRACK_SNMP is not set ++# CONFIG_NF_CONNTRACK_PPTP is not set ++# CONFIG_NF_CONNTRACK_SANE is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++CONFIG_NF_CONNTRACK_TFTP=y ++# CONFIG_NF_CT_NETLINK is not set ++# CONFIG_NF_CT_NETLINK_TIMEOUT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set ++CONFIG_NETFILTER_TPROXY=y ++CONFIG_NETFILTER_XTABLES=y ++ ++# ++# Xtables combined modules ++# ++CONFIG_NETFILTER_XT_MARK=y ++CONFIG_NETFILTER_XT_CONNMARK=y ++ ++# ++# Xtables targets ++# ++# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set ++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set ++# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set ++# CONFIG_NETFILTER_XT_TARGET_CT is not set ++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set ++CONFIG_NETFILTER_XT_TARGET_HL=y ++# CONFIG_NETFILTER_XT_TARGET_HMARK is not set ++# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set ++# CONFIG_NETFILTER_XT_TARGET_LOG is not set ++# CONFIG_NETFILTER_XT_TARGET_MARK is not set ++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set ++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set ++# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set ++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set ++# CONFIG_NETFILTER_XT_TARGET_TEE is not set ++# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set ++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set ++ ++# ++# Xtables matches ++# ++# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set ++# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set ++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set ++# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++# CONFIG_NETFILTER_XT_MATCH_CPU is not set ++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set ++# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set ++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set ++CONFIG_NETFILTER_XT_MATCH_ECN=y ++# CONFIG_NETFILTER_XT_MATCH_ESP is not set ++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_HELPER is not set ++CONFIG_NETFILTER_XT_MATCH_HL=y ++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set ++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set ++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set ++# CONFIG_NETFILTER_XT_MATCH_MAC is not set ++# CONFIG_NETFILTER_XT_MATCH_MARK is not set ++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set ++# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set ++# CONFIG_NETFILTER_XT_MATCH_OSF is not set ++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set ++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set ++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set ++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set ++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set ++# CONFIG_NETFILTER_XT_MATCH_REALM is not set ++# CONFIG_NETFILTER_XT_MATCH_RECENT is not set ++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set ++# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set ++# CONFIG_NETFILTER_XT_MATCH_STRING is not set ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=y ++# CONFIG_NETFILTER_XT_MATCH_TIME is not set ++# CONFIG_NETFILTER_XT_MATCH_U32 is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++CONFIG_NF_DEFRAG_IPV4=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_NF_CONNTRACK_PROC_COMPAT=y ++CONFIG_IP_NF_QUEUE=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++# CONFIG_IP_NF_MATCH_RPFILTER is not set ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_TARGET_ULOG=y ++CONFIG_NF_NAT=y ++CONFIG_NF_NAT_NEEDED=y ++CONFIG_IP_NF_TARGET_MASQUERADE=y ++CONFIG_IP_NF_TARGET_NETMAP=y ++CONFIG_IP_NF_TARGET_REDIRECT=y ++CONFIG_NF_NAT_FTP=y ++# CONFIG_NF_NAT_IRC is not set ++CONFIG_NF_NAT_TFTP=y ++# CONFIG_NF_NAT_AMANDA is not set ++# CONFIG_NF_NAT_PPTP is not set ++# CONFIG_NF_NAT_H323 is not set ++# CONFIG_NF_NAT_SIP is not set ++CONFIG_IP_NF_MANGLE=y ++# CONFIG_IP_NF_TARGET_CLUSTERIP is not set ++CONFIG_IP_NF_TARGET_ECN=y ++CONFIG_IP_NF_TARGET_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARP_MANGLE=y ++# CONFIG_BRIDGE_NF_EBTABLES is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++CONFIG_STP=y ++CONFIG_GARP=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=y ++CONFIG_VLAN_8021Q_GVRP=y ++# CONFIG_DECNET is not set ++CONFIG_LLC=y ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++CONFIG_FIB_RULES=y ++CONFIG_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++# CONFIG_CAIF is not set ++# CONFIG_CEPH_LIB is not set ++# CONFIG_NFC is not set ++CONFIG_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_DMA_SHARED_BUFFER is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++CONFIG_CMA_AREAS=7 ++# CONFIG_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_SM_FTL is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++CONFIG_M25PXX_STAY_IN_3BYTE_MODE=y ++# CONFIG_MTD_SST25L is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_MUSEUM_IDS is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_ALAUDA is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_RESERVE=2 ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_DA is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_BLK_DEV_SX8 is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++CONFIG_BLK_DEV_XIP=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_ATMEL_PWM is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_APDS9802ALS is not set ++# CONFIG_ISL29003 is not set ++# CONFIG_ISL29020 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_SENSORS_BH1780 is not set ++# CONFIG_SENSORS_BH1770 is not set ++# CONFIG_SENSORS_APDS990X is not set ++# CONFIG_HMC6352 is not set ++# CONFIG_DS1682 is not set ++# CONFIG_TI_DAC7512 is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI is not set ++# CONFIG_PCH_PHUB is not set ++# CONFIG_USB_SWITCH_FSA9480 is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++# CONFIG_EEPROM_AT24 is not set ++# CONFIG_EEPROM_AT25 is not set ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_EEPROM_93XX46 is not set ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# CONFIG_TI_ST is not set ++# CONFIG_SENSORS_LIS3_SPI is not set ++# CONFIG_SENSORS_LIS3_I2C is not set ++ ++# ++# Altera FPGA firmware download module ++# ++# CONFIG_ALTERA_STAPL is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_TGT=y ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=y ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++CONFIG_SCSI_MULTI_LUN=y ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_SCSI_BNX2X_FCOE is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC7XXX_OLD is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_DPT_I2O is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_LIBFC is not set ++# CONFIG_LIBFCOE is not set ++# CONFIG_FCOE is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_FC is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_LPFC is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_DC390T is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_SRP is not set ++# CONFIG_SCSI_BFA_FC is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++# CONFIG_I2O is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++# CONFIG_MII is not set ++# CONFIG_NET_TEAM is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++CONFIG_NET_VENDOR_AMD=y ++# CONFIG_AMD8111_ETH is not set ++# CONFIG_PCNET32 is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++CONFIG_NET_VENDOR_BROADCOM=y ++# CONFIG_B44 is not set ++# CONFIG_BNX2 is not set ++# CONFIG_CNIC is not set ++CONFIG_TIGON3=y ++# CONFIG_BNX2X is not set ++CONFIG_NET_VENDOR_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CIRRUS=y ++# CONFIG_CS89x0 is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_FARADAY=y ++# CONFIG_FTMAC100 is not set ++# CONFIG_FTGMAC100 is not set ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++CONFIG_NET_VENDOR_INTEL=y ++# CONFIG_E100 is not set ++# CONFIG_E1000 is not set ++CONFIG_E1000E=y ++# CONFIG_IGB is not set ++# CONFIG_IGBVF is not set ++# CONFIG_IXGB is not set ++# CONFIG_IXGBE is not set ++CONFIG_NET_VENDOR_I825XX=y ++# CONFIG_IP1000 is not set ++# CONFIG_JME is not set ++CONFIG_NET_VENDOR_MARVELL=y ++# CONFIG_SKGE is not set ++# CONFIG_SKY2 is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++CONFIG_NET_VENDOR_MICREL=y ++# CONFIG_KS8851 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_KSZ884X_PCI is not set ++CONFIG_NET_VENDOR_MICROCHIP=y ++# CONFIG_ENC28J60 is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++CONFIG_NET_VENDOR_NATSEMI=y ++# CONFIG_NATSEMI is not set ++# CONFIG_NS83820 is not set ++CONFIG_NET_VENDOR_8390=y ++# CONFIG_AX88796 is not set ++# CONFIG_NE2K_PCI is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 is not set ++CONFIG_NET_VENDOR_SEEQ=y ++# CONFIG_SEEQ8005 is not set ++CONFIG_NET_VENDOR_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++CONFIG_NET_VENDOR_SMSC=y ++# CONFIG_SMC91X is not set ++# CONFIG_EPIC100 is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_SMSC9420 is not set ++CONFIG_NET_VENDOR_STMICRO=y ++# CONFIG_STMMAC_ETH is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TLAN is not set ++CONFIG_NET_VENDOR_VIA=y ++# CONFIG_VIA_RHINE is not set ++# CONFIG_VIA_VELOCITY is not set ++CONFIG_NET_VENDOR_WIZNET=y ++# CONFIG_WIZNET_W5100 is not set ++# CONFIG_WIZNET_W5300 is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AMD_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_ATMEL is not set ++# CONFIG_PRISM54 is not set ++# CONFIG_USB_ZD1201 is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++# CONFIG_VT is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_PCI=y ++CONFIG_SERIAL_8250_NR_UARTS=2 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SERIAL_8250_EXTENDED=y ++# CONFIG_SERIAL_8250_MANY_PORTS is not set ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DETECT_IRQ=y ++CONFIG_SERIAL_8250_RSA=y ++# CONFIG_SERIAL_8250_EM is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 is not set ++# CONFIG_SERIAL_MFD_HSU is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_HW_RANDOM_ATMEL is not set ++# CONFIG_HW_RANDOM_EXYNOS is not set ++# CONFIG_R3964 is not set ++# CONFIG_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++# CONFIG_I2C_COMPAT is not set ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++# CONFIG_I2C_HELPER_AUTO is not set ++# CONFIG_I2C_SMBUS is not set ++ ++# ++# I2C Algorithms ++# ++# CONFIG_I2C_ALGOBIT is not set ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_INTEL_MID is not set ++# CONFIG_I2C_NOMADIK is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PL022 is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_TLE62X0 is not set ++# CONFIG_HSI is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_PL061 is not set ++# CONFIG_GPIO_VX855 is not set ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_RDC321X is not set ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_CORE=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_ARM_SP805_WATCHDOG is not set ++# CONFIG_DW_WATCHDOG is not set ++# CONFIG_MPCORE_WATCHDOG is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++# CONFIG_ALIM7101_WDT is not set ++# CONFIG_I6300ESB_WDT is not set ++ ++# ++# PCI-based Watchdog Cards ++# ++# CONFIG_PCIPCWATCHDOG is not set ++# CONFIG_WDTPCI is not set ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++CONFIG_BCMA_POSSIBLE=y ++ ++# ++# Broadcom specific AMBA ++# ++# CONFIG_BCMA is not set ++ ++# ++# Multifunction device drivers ++# ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_88PM860X is not set ++# CONFIG_MFD_88PM800 is not set ++# CONFIG_MFD_88PM805 is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_MFD_LM3533 is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912_I2C is not set ++# CONFIG_MFD_TPS65912_SPI is not set ++# CONFIG_TWL4030_CORE is not set ++# CONFIG_TWL6040_CORE is not set ++# CONFIG_MFD_STMPE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_T7L66XB is not set ++# CONFIG_MFD_TC6387XB is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_MFD_DA9052_SPI is not set ++# CONFIG_MFD_DA9052_I2C is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_MAX77686 is not set ++# CONFIG_MFD_MAX77693 is not set ++# CONFIG_MFD_MAX8925 is not set ++# CONFIG_MFD_MAX8997 is not set ++# CONFIG_MFD_MAX8998 is not set ++# CONFIG_MFD_SEC_CORE is not set ++# CONFIG_MFD_ARIZONA_I2C is not set ++# CONFIG_MFD_ARIZONA_SPI is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM831X_I2C is not set ++# CONFIG_MFD_WM831X_SPI is not set ++# CONFIG_MFD_WM8350_I2C is not set ++# CONFIG_MFD_WM8994 is not set ++# CONFIG_MFD_PCF50633 is not set ++# CONFIG_MFD_MC13XXX_SPI is not set ++# CONFIG_MFD_MC13XXX_I2C is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_MFD_TIMBERDALE is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_MFD_RDC321X is not set ++# CONFIG_MFD_JANZ_CMODIO is not set ++# CONFIG_MFD_VX855 is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_AAT2870_CORE is not set ++# CONFIG_MFD_RC5T583 is not set ++# CONFIG_MFD_PALMAS is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGA_ARB is not set ++# CONFIG_DRM is not set ++# CONFIG_STUB_POULSBO is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_EXYNOS_VIDEO is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++CONFIG_HIDRAW=y ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO_TPKBD is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MICROSOFT is not set ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SONY is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV is not set ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB_ARCH_HAS_XHCI=y ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB=y ++CONFIG_USB_DEBUG=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DYNAMIC_MINORS=y ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_XHCI_HCD is not set ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++# CONFIG_USB_EHCI_TT_NEWSCHED is not set ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_OHCI_HCD is not set ++# CONFIG_USB_EHCI_HCD_PLATFORM is not set ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_CHIPIDEA is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may ++# ++ ++# ++# also be needed; see USB_STORAGE Help for more info ++# ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_DEBUG=y ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++CONFIG_USB_UAS=y ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_SISUSBVGA is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_ISP1301 is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_DUMMY_HCD is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++# CONFIG_USB_FILE_STORAGE is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++CONFIG_DMADEVICES=y ++CONFIG_DMADEVICES_DEBUG=y ++CONFIG_DMADEVICES_VDEBUG=y ++ ++# ++# DMA Devices ++# ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTIO_BALLOON is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_HAVE_MACH_CLKDEV=y ++ ++# ++# Hardware Spinlock drivers ++# ++CONFIG_IOMMU_SUPPORT=y ++ ++# ++# Remoteproc drivers (EXPERIMENTAL) ++# ++ ++# ++# Rpmsg drivers (EXPERIMENTAL) ++# ++# CONFIG_VIRT_DRIVERS is not set ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_XATTR=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++CONFIG_NILFS2_FS=y ++# CONFIG_FS_POSIX_ACL is not set ++CONFIG_FILE_LOCKING=y ++# CONFIG_FSNOTIFY is not set ++# CONFIG_DNOTIFY is not set ++# CONFIG_INOTIFY_USER is not set ++# CONFIG_FANOTIFY is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++CONFIG_AUTOFS4_FS=y ++# CONFIG_FUSE_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++# CONFIG_NTFS_RW is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_SYSFS=y ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++CONFIG_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_SQUASHFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_QNX6FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# CONFIG_SUNRPC_DEBUG is not set ++# CONFIG_CEPH_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++# CONFIG_NLS_MAC_ROMAN is not set ++# CONFIG_NLS_MAC_CELTIC is not set ++# CONFIG_NLS_MAC_CENTEURO is not set ++# CONFIG_NLS_MAC_CROATIAN is not set ++# CONFIG_NLS_MAC_CYRILLIC is not set ++# CONFIG_NLS_MAC_GAELIC is not set ++# CONFIG_NLS_MAC_GREEK is not set ++# CONFIG_NLS_MAC_ICELAND is not set ++# CONFIG_NLS_MAC_INUIT is not set ++# CONFIG_NLS_MAC_ROMANIAN is not set ++# CONFIG_NLS_MAC_TURKISH is not set ++# CONFIG_NLS_UTF8 is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_INFO_REDUCED is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_LKDTM is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_ARM_UNWIND is not set ++CONFIG_DEBUG_USER=y ++CONFIG_DEBUG_LL=y ++CONFIG_DEBUG_LL_UART_NONE=y ++# CONFIG_DEBUG_ICEDCC is not set ++# CONFIG_DEBUG_SEMIHOSTING is not set ++# CONFIG_EARLY_PRINTK is not set ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_ENCRYPTED_KEYS is not set ++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++# CONFIG_CRYPTO_AUTHENC is not set ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=m ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++ ++# ++# Random Number Generation ++# ++CONFIG_CRYPTO_ANSI_CPRNG=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_GENERIC_STRNCPY_FROM_USER=y ++CONFIG_GENERIC_STRNLEN_USER=y ++CONFIG_GENERIC_PCI_IOMAP=y ++CONFIG_GENERIC_IO=y ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC32_SELFTEST is not set ++CONFIG_CRC32_SLICEBY8=y ++# CONFIG_CRC32_SLICEBY4 is not set ++# CONFIG_CRC32_SARWATE is not set ++# CONFIG_CRC32_BIT is not set ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++# CONFIG_CRC8 is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++# CONFIG_XZ_DEC is not set ++# CONFIG_XZ_DEC_BCJ is not set ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set +diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h +index 9abe7a0..fac79dc 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch new file mode 100644 index 00000000..b4db0dac --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_bug.h.patch @@ -0,0 +1,12 @@ +--- a/arch/arm/include/asm/bug.h ++++ b/arch/arm/include/asm/bug.h +@@ -32,7 +32,6 @@ + + #define __BUG(__file, __line, __value) \ + do { \ +- BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ + asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ + ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ + "2:\t.asciz " #__file "\n" \ +diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h +index 3e91f22..b7641d6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch new file mode 100644 index 00000000..bc5fd627 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_hardware_gic.h.patch @@ -0,0 +1,12 @@ +--- a/arch/arm/include/asm/hardware/gic.h ++++ b/arch/arm/include/asm/hardware/gic.h +@@ -42,6 +42,7 @@ extern struct irq_chip gic_arch_extn; + void gic_init(unsigned int, int, void __iomem *, void __iomem *); + int gic_of_init(struct device_node *node, struct device_node *parent); + void gic_secondary_init(unsigned int); ++void gic_handle_irq(struct pt_regs *regs); + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); + void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); + +diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h +index fcbac3c..f2a1a30 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch new file mode 100644 index 00000000..e308b092 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_pgtable.h.patch @@ -0,0 +1,39 @@ +--- a/arch/arm/include/asm/pgtable.h ++++ b/arch/arm/include/asm/pgtable.h +@@ -21,7 +21,6 @@ + #else + + #include +-#include + #include + + #include +@@ -33,14 +32,13 @@ + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) +- * +- * Note that platforms may override VMALLOC_START, but they must provide +- * VMALLOC_END. VMALLOC_END defines the (exclusive) limit of this space, +- * which may not overlap IO space. + */ +-#ifndef VMALLOC_START + #define VMALLOC_OFFSET (8*1024*1024) + #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) ++#ifdef __ASSEMBLY__ ++#define VMALLOC_END 0xff000000 ++#else ++#define VMALLOC_END 0xff000000UL + #endif + + #define LIBRARY_TEXT_START 0x0c000000 +@@ -338,6 +336,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) + * We provide our own arch_get_unmapped_area to cope with VIPT caches. + */ + #define HAVE_ARCH_UNMAPPED_AREA ++#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN + + /* + * remap a physical page `pfn' of size `size' with page protection `prot' +diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h +index 3352451..da9f0d9 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch new file mode 100644 index 00000000..ecf5bf4c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_include_asm_processor.h.patch @@ -0,0 +1,13 @@ +--- a/arch/arm/include/asm/processor.h ++++ b/arch/arm/include/asm/processor.h +@@ -119,6 +119,8 @@ static inline void prefetch(const void *ptr) + + #endif + ++#define HAVE_ARCH_PICK_MMAP_LAYOUT ++ + #endif + + #endif /* __ASM_ARM_PROCESSOR_H */ +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index ece0996..5ad6b59 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch new file mode 100644 index 00000000..6d188842 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-armv.S.patch @@ -0,0 +1,39 @@ +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -27,25 +27,28 @@ + #include + + #include "entry-header.S" ++ + #include + ++ + /* + * Interrupt handling. + */ + .macro irq_handler ++ + #ifdef CONFIG_MULTI_IRQ_HANDLER +- ldr r1, =handle_arch_irq ++ ++ ldr r1, =handle_arch_irq + mov r0, sp +- ldr r1, [r1] + adr lr, BSYM(9997f) +- teq r1, #0 +- movne pc, r1 +-#endif ++ ldr pc, [r1] ++#else + arch_irq_handler_default ++#endif + 9997: + .endm + +- .macro pabt_helper ++ .macro pabt_helper + @ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5 + #ifdef MULTI_PABORT + ldr ip, .LCprocfns +diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S +index 9d95a46..9dd0881 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch new file mode 100644 index 00000000..b7f2c53d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_entry-header.S.patch @@ -0,0 +1,15 @@ +--- a/arch/arm/kernel/entry-header.S ++++ b/arch/arm/kernel/entry-header.S +@@ -13,8 +13,10 @@ + #define BAD_DATA 1 + #define BAD_ADDREXCPTN 2 + #define BAD_IRQ 3 ++ + #define BAD_UNDEFINSTR 4 + ++ + @ + @ Most of the stack format comes from struct pt_regs, but with + @ the addition of 8 bytes for storing syscall args 5 and 6. +diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S +index 3606e85..f364802 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch new file mode 100644 index 00000000..d9d3312b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_head.S.patch @@ -0,0 +1,32 @@ +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -87,7 +87,26 @@ ENTRY(stext) + + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode + @ and irqs disabled +- mrc p15, 0, r9, c0, c0 @ get processor id ++#ifdef CONFIG_ARCH_IPROC ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++#ifndef CONFIG_MACH_CYGNUS ++ /* ++ * fixup the vector table so that the secondary CPU does ++ * not start executing kernel instructions until we've ++ * patched its jump address during wakeup_secondary() ++ */ ++ ldr r3,=0xffff002c ++ ldr r4,=0xffff0000 ++ str r3, [r4, #0x400] ++#endif ++#endif ++ ++ /* Make sure the cache is invalidated and MMU is disabled */ ++ bl __iproc_head_fixup ++#endif /* CONFIG_ARCH_IPROC */ ++ ++ mrc p15, 0, r9, c0, c0 @ get processor id + bl __lookup_processor_type @ r5=procinfo r9=cpuid + movs r10, r5 @ invalid processor (r5=0)? + THUMB( it eq ) @ force fixup-able long branch encoding +diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c +index 1e9be5d..7ab2fa7 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch new file mode 100644 index 00000000..4c6c765c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_module.c.patch @@ -0,0 +1,74 @@ +--- a/arch/arm/kernel/module.c ++++ b/arch/arm/kernel/module.c +@@ -111,19 +111,20 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + } + + offset >>= 2; ++ offset &= 0x00ffffff; + + *(u32 *)loc &= 0xff000000; + *(u32 *)loc |= offset & 0x00ffffff; + break; + +- case R_ARM_V4BX: +- /* Preserve Rm and the condition code. Alter ++ case R_ARM_V4BX: ++ /* Preserve Rm and the condition code. Alter + * other bits to re-code instruction as + * MOV PC,Rm. + */ +- *(u32 *)loc &= 0xf000000f; +- *(u32 *)loc |= 0x01a0f000; +- break; ++ *(u32 *)loc &= 0xf000000f; ++ *(u32 *)loc |= 0x01a0f000; ++ break; + + case R_ARM_PREL31: + offset = *(u32 *)loc + sym->st_value - loc; +@@ -142,7 +143,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + + *(u32 *)loc &= 0xfff0f000; + *(u32 *)loc |= ((offset & 0xf000) << 4) | +- (offset & 0x0fff); ++ (offset & 0x0fff); ++ + break; + + #ifdef CONFIG_THUMB2_KERNEL +@@ -203,12 +205,13 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + *(u16 *)(loc + 2) = (u16)((lower & 0xd000) | + (j1 << 13) | (j2 << 11) | + ((offset >> 1) & 0x07ff)); ++ + break; + + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: +- upper = *(u16 *)loc; +- lower = *(u16 *)(loc + 2); ++ upper = __mem_to_opcode_thumb16(*(u16 *)loc); ++ lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2)); + + /* + * MOVT/MOVW instructions encoding in Thumb-2: +@@ -229,12 +232,15 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, + if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS) + offset >>= 16; + +- *(u16 *)loc = (u16)((upper & 0xfbf0) | ++ upper = (u16)((upper & 0xfbf0) | + ((offset & 0xf000) >> 12) | + ((offset & 0x0800) >> 1)); +- *(u16 *)(loc + 2) = (u16)((lower & 0x8f00) | ++ lower = (u16)((lower & 0x8f00) | + ((offset & 0x0700) << 4) | + (offset & 0x00ff)); ++ ++ *(u16 *)loc = __opcode_to_mem_thumb16(upper); ++ *(u16 *)(loc + 2) = __opcode_to_mem_thumb16(lower); + break; + #endif + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index d9e3c61..2dc26fd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch new file mode 100644 index 00000000..48c61653 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_process.c.patch @@ -0,0 +1,27 @@ +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -263,11 +264,12 @@ void __show_regs(struct pt_regs *regs) + unsigned long flags; + char buf[64]; + +- printk("CPU: %d %s (%s %.*s)\n", ++ printk("CPU: %d %s (%s %.*s%s)\n", + raw_smp_processor_id(), print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), +- init_utsname()->version); ++ init_utsname()->version, ++ LINUX_PACKAGE_ID); + print_symbol("PC is at %s\n", instruction_pointer(regs)); + print_symbol("LR is at %s\n", regs->ARM_lr); + printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" +diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c +index 8f5dd79..1edbb3d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch new file mode 100644 index 00000000..1a88d2a2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_scu.c.patch @@ -0,0 +1,49 @@ +--- a/arch/arm/kernel/smp_scu.c ++++ b/arch/arm/kernel/smp_scu.c +@@ -27,7 +27,7 @@ + */ + unsigned int __init scu_get_core_count(void __iomem *scu_base) + { +- unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG); ++ unsigned int ncores = readl_relaxed(scu_base + SCU_CONFIG); + return (ncores & 0x03) + 1; + } + +@@ -41,19 +41,19 @@ void scu_enable(void __iomem *scu_base) + #ifdef CONFIG_ARM_ERRATA_764369 + /* Cortex-A9 only */ + if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) { +- scu_ctrl = __raw_readl(scu_base + 0x30); ++ scu_ctrl = readl_relaxed(scu_base + 0x30); + if (!(scu_ctrl & 1)) +- __raw_writel(scu_ctrl | 0x1, scu_base + 0x30); ++ writel_relaxed(scu_ctrl | 0x1, scu_base + 0x30); + } + #endif + +- scu_ctrl = __raw_readl(scu_base + SCU_CTRL); ++ scu_ctrl = readl_relaxed(scu_base + SCU_CTRL); + /* already enabled? */ + if (scu_ctrl & 1) + return; + + scu_ctrl |= 1; +- __raw_writel(scu_ctrl, scu_base + SCU_CTRL); ++ writel_relaxed(scu_ctrl, scu_base + SCU_CTRL); + + /* + * Ensure that the data accessed by CPU0 before the SCU was +@@ -79,9 +79,9 @@ int scu_power_mode(void __iomem *scu_base, unsigned int mode) + if (mode > 3 || mode == 1 || cpu > 3) + return -EINVAL; + +- val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; ++ val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; + val |= mode; +- __raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu); ++ writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu); + + return 0; + } +diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c +index a8a6682..0647dfa 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch new file mode 100644 index 00000000..1634a4d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_kernel_smp_twd.c.patch @@ -0,0 +1,70 @@ +--- a/arch/arm/kernel/smp_twd.c ++++ b/arch/arm/kernel/smp_twd.c +@@ -39,7 +39,7 @@ static void twd_set_mode(enum clock_event_mode mode, + /* timer load already set up */ + ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE + | TWD_TIMER_CONTROL_PERIODIC; +- __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); ++ writel_relaxed(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ +@@ -51,18 +51,18 @@ static void twd_set_mode(enum clock_event_mode mode, + ctrl = 0; + } + +- __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); ++ writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + } + + static int twd_set_next_event(unsigned long evt, + struct clock_event_device *unused) + { +- unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL); ++ unsigned long ctrl = readl_relaxed(twd_base + TWD_TIMER_CONTROL); + + ctrl |= TWD_TIMER_CONTROL_ENABLE; + +- __raw_writel(evt, twd_base + TWD_TIMER_COUNTER); +- __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); ++ writel_relaxed(evt, twd_base + TWD_TIMER_COUNTER); ++ writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + + return 0; + } +@@ -75,8 +75,8 @@ static int twd_set_next_event(unsigned long evt, + */ + int twd_timer_ack(void) + { +- if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { +- __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); ++ if (readl_relaxed(twd_base + TWD_TIMER_INTSTAT)) { ++ writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT); + return 1; + } + +@@ -110,16 +110,16 @@ static void __cpuinit twd_calibrate_rate(void) + /* OK, now the tick has started, let's get the timer going */ + waitjiffies += 5; + +- /* enable, no interrupt or reload */ +- __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL); ++ /* enable, no interrupt or reload */ ++ writel_relaxed(0x1, twd_base + TWD_TIMER_CONTROL); + +- /* maximum value */ +- __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); ++ /* maximum value */ ++ writel_relaxed(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); + + while (get_jiffies_64() < waitjiffies) + udelay(10); + +- count = __raw_readl(twd_base + TWD_TIMER_COUNTER); ++ count = readl_relaxed(twd_base + TWD_TIMER_COUNTER); + + twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); + +diff --git a/arch/arm/mach-iproc/Kconfig b/arch/arm/mach-iproc/Kconfig +new file mode 100644 +index 0000000..c77208d diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch new file mode 100644 index 00000000..d7548b4c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Kconfig.patch @@ -0,0 +1,113 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/Kconfig +@@ -0,0 +1,107 @@ ++menu "iProc SoC based Machine types" ++ depends on MACH_IPROC ++ ++config MACH_CYGNUS ++ bool "Cygnus bring-up board" ++ help ++ Support for the Broadcom Cygnus bring-up board. ++ ++config MACH_NS ++ bool "Support Broadcom Northstar bring-up board" ++ help ++ Support for the Broadcom Northstar bring-up board. ++ ++config MACH_HX4 ++ bool "Support Broadcom Helix4 bring-up board" ++ help ++ Support for the Broadcom Helix4 bring-up board. ++ ++config MACH_HR2 ++ bool "Support Broadcom Hurricane2 bring-up board" ++ help ++ Support for the Broadcom Hurricane2 bring-up board. ++ ++config MACH_NSP ++ bool "Support Broadcom Northstar Plus bring-up board" ++ help ++ Support for the Broadcom Northstar Plus bring-up board. ++ ++config MACH_KT2 ++ bool "Support Broadcom Katana2 bring-up board" ++ help ++ Support for the Broadcom Katana2 bring-up board. ++ ++config MACH_GH ++ bool "Support Broadcom Greyhound bring-up board" ++ select MACH_IPROC_P7 ++ help ++ Support for the Broadcom Greyhound bring-up board. ++ ++config MACH_DNI_3448P ++ select ARM_L1_CACHE_SHIFT_6 ++ bool "Support Delta Networks Inc. 3448P board" ++ help ++ Support for the Broadcom Greyhound bring-up board. ++ ++config MACH_ACCTON_AS4610_54 ++ select ARM_L1_CACHE_SHIFT_6 ++ bool "Support Accton AS4610 54 POE and non-POE board" ++ help ++ Support for Accton AS4610-54 POE and non -POE board. ++ ++config MACH_IPROC_P7 ++ bool "Support iProc Profile 7 architecture" ++ depends on MACH_GH ++ help ++ Support for iProc Profile 7 architecture. ++ ++config MACH_IPROC_EMULATION ++ bool "Support iProc emulation" ++ help ++ Support for the iProc emulation. ++ ++if MACH_CYGNUS ++ ++config MACH_CYGNUS_EMULATION ++ bool "Is it Cygnus emulation ?" ++ default y ++ help ++ Support for the Broadcom Cygnus emulation ++ ++if MACH_CYGNUS_EMULATION ++ ++config CYGNUS_EMULATION_RTL_VER ++ string "specify RTL version" ++ default "Cygnus RTL-5.1" ++ help ++ running rtl version used for emulation build ++ ++config CYGNUS_EMULATION_ARM_CLK ++ int "Hz - iHost clk don't change" ++ default 250000000 ++ help ++ iHost clock in emulator ++ ++config CYGNUS_EMULATION_PCLK ++ int "Hz - axi81 (pclk) in xls" ++ default 62500000 ++ help ++ pheripheral clock in emulator ++ ++config CYGNUS_EMULATION_SCLK ++ int "Hz - sclk in xls" ++ default 154380 ++ help ++ uart clock in emulator ++ ++config CYGNUS_EMULATION_CLK_125 ++ int "Hz - axi41 clock in xls" ++ default 154380 ++ help ++ 125Mhz equialent clock in emulator ++ ++endif #MACH_CYGNUS_EMULATION ++ ++endif #MACH_CYGNUS ++ ++endmenu +diff --git a/arch/arm/mach-iproc/Makefile b/arch/arm/mach-iproc/Makefile +new file mode 100644 +index 0000000..b4a7ff3 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch new file mode 100644 index 00000000..21af44ed --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.boot.patch @@ -0,0 +1,8 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/Makefile.boot +@@ -0,0 +1,2 @@ ++zreladdr-y := $(CONFIG_BCM_ZRELADDR) ++params_phys-y := $(CONFIG_BCM_PARAMS_PHYS) +diff --git a/arch/arm/mach-iproc/board_bu.c b/arch/arm/mach-iproc/board_bu.c +new file mode 100644 +index 0000000..7e07ed1 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch new file mode 100644 index 00000000..60f3a4a0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_Makefile.patch @@ -0,0 +1,21 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/Makefile +@@ -0,0 +1,15 @@ ++ifdef CONFIG_MACH_CYGNUS ++obj-y := io_map.o northstar.o common.o northstar_dmu.o board_bu.o localtimer.o ++else ++obj-y := io_map.o northstar.o common.o northstar_dmu.o board_bu.o idm.o localtimer.o ++endif ++ ++ifdef CONFIG_BCM_CTF2 ++EXTRA_CFLAGS += -I$(srctree)/../../bcmdrivers/gmac/src/include/ ++endif ++ ++obj-$(CONFIG_PM) += pm.o ++ ++#obj-$(CONFIG_MACH_NS) += board_bu.o ++ ++obj-$(CONFIG_MTD) += flash.o +diff --git a/arch/arm/mach-iproc/Makefile.boot b/arch/arm/mach-iproc/Makefile.boot +new file mode 100644 +index 0000000..2de985c diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch new file mode 100644 index 00000000..126a2d42 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_board_bu.c.patch @@ -0,0 +1,1103 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/board_bu.c +@@ -0,0 +1,1097 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_EARLY_DMA_ALLOC ++#include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "northstar.h" ++#include "common.h" ++#ifdef HNDCTF ++#include ++#include ++#endif /* HNDCTF */ ++ ++#include ++#include ++#include ++ ++#include ++ ++/* Fast device at 0x6000 offset */ ++static AMBA_APB_DEVICE(pl020, "pl020", 0, 0x18028000, ++ { 111 }, NULL); ++static AMBA_APB_DEVICE(pl021, "pl021", 0, 0x18029000, ++ { 111 }, NULL); ++ ++struct pl022_config_chip spi_chip_info = { ++ /* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */ ++ .com_mode = DMA_TRANSFER, ++ .iface = SSP_INTERFACE_MOTOROLA_SPI, ++ /* We can only act as master but SSP_SLAVE is possible in theory */ ++ .hierarchy = SSP_MASTER, ++ /* 0 = drive TX even as slave, 1 = do not drive TX as slave */ ++ .slave_tx_disable = 0, ++ .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM, ++ .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC, ++ .ctrl_len = SSP_BITS_12, ++ .wait_state = SSP_MWIRE_WAIT_ZERO, ++ .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, ++}; ++ ++static struct pl022_ssp_controller ssp_platform_data[] = { ++ { ++ /* If you have several SPI buses this varies, we have only bus 0 */ ++ .bus_id = 0, ++ /* ++ * On the APP CPU GPIO 4, 5 and 6 are connected as generic ++ * chip selects for SPI. (Same on U330, U335 and U365.) ++ * TODO: make sure the GPIO driver can select these properly ++ * and do padmuxing accordingly too. ++ */ ++ .num_chipselect = 1, ++ .enable_dma = 1, ++ }, ++ { ++ /* If you have several SPI buses this varies, we have only bus 0 */ ++ .bus_id = 1, ++ /* ++ * On the APP CPU GPIO 4, 5 and 6 are connected as generic ++ * chip selects for SPI. (Same on U330, U335 and U365.) ++ * TODO: make sure the GPIO driver can select these properly ++ * and do padmuxing accordingly too. ++ */ ++ .num_chipselect = 1, ++ .enable_dma = 1, ++ }, ++}; ++ ++static struct spi_board_info iproc_spi_devices[] = { ++ { ++ /* A dummy chip used for loopback tests */ ++ .modalias = "spidev0", ++ /* Really dummy, pass in additional chip config here */ ++ .platform_data = NULL, ++ /* This defines how the controller shall handle the device */ ++ .controller_data = &spi_chip_info, ++ /* .irq - no external IRQ routed from this device */ ++ .max_speed_hz = 1000000, ++ .bus_num = 0, /* Only one bus on this chip */ ++ .chip_select = 0, ++ /* Means SPI_CS_HIGH, change if e.g low CS */ ++ .mode = SPI_MODE_2 | SPI_NO_CS, ++ }, ++ { ++ /* A dummy chip used for loopback tests */ ++ .modalias = "spidev1", ++ /* Really dummy, pass in additional chip config here */ ++ .platform_data = NULL, ++ /* This defines how the controller shall handle the device */ ++ .controller_data = &spi_chip_info, ++ /* .irq - no external IRQ routed from this device */ ++ .max_speed_hz = 1000000, ++ .bus_num = 1, /* Only one bus on this chip */ ++ .chip_select = 0, ++ /* Means SPI_CS_HIGH, change if e.g low CS */ ++ .mode = SPI_MODE_2 | SPI_NO_CS, ++ }, ++}; ++ ++/* ++ * The order of device declaration may be important, since some devices ++ * have dependencies on other devices being initialized first. ++ */ ++static struct amba_device *amba_pl_devs[] __initdata = { ++ &pl020_device, ++ &pl021_device, ++ ++}; ++ ++void __init iproc_spi_init(struct amba_device *adev, int i) ++{ ++ adev->dev.platform_data = &ssp_platform_data[i]; ++} ++ ++void __init iproc_spi_register_board_devices(void) ++{ ++ /* Register any SPI devices */ ++ spi_register_board_info(iproc_spi_devices, ARRAY_SIZE(iproc_spi_devices)); ++} ++ ++void __init iproc_init_devics(void) ++{ ++ int i; ++ ++ /* Register the AMBA devices in the AMBA bus abstraction layer */ ++ for (i = 0; i < ARRAY_SIZE(amba_pl_devs); i++) { ++ struct amba_device *d = amba_pl_devs[i]; ++ iproc_spi_init(d, i); ++ amba_device_register(d, &iomem_resource); ++ } ++ ++ /* Register SPI bus */ ++ iproc_spi_register_board_devices(); ++} ++ ++ ++#if defined(CONFIG_IPROC_SD) || defined(CONFIG_IPROC_SD_MODULE) ++#define IPROC_SDIO_PA IPROC_SDIO3_REG_BASE ++#define SDIO_CORE_REG_SIZE 0x10000 ++#define BSC_CORE_REG_SIZE 0x1000 ++#define SDIO_IDM_IDM_RESET_CONTROL (0x16800) ++#define IPROC_SDIO_IRQ (177) ++#endif ++ ++#if defined(CONFIG_MACH_NSP) ++#define SATA_M0_IDM_IO_CONTROL_DIRECT_VA HW_IO_PHYS_TO_VIRT(SATA_M0_IDM_IO_CONTROL_DIRECT) ++#define SATA_M0_IDM_IDM_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(SATA_M0_IDM_IDM_RESET_CONTROL) ++#define SATA_TOP_CTRL_BUS_CTRL_VA HW_IO_PHYS_TO_VIRT(SATA_TOP_CTRL_BUS_CTRL) ++#define SATA3_PCB_UPPER_REG15_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG15) ++#define SATA3_PCB_UPPER_REG0_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG0) ++#define SATA3_PCB_UPPER_REG1_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG1) ++#define SATA3_PCB_UPPER_REG11_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG11) ++#define SATA3_PCB_UPPER_REG5_VA HW_IO_PHYS_TO_VIRT(SATA3_PCB_UPPER_REG5) ++#define AXIIC_sata_m0_fn_mod_VA HW_IO_PHYS_TO_VIRT(AXIIC_sata_m0_fn_mod) ++#define BCM_INT_SATA 190 ++#define NSP_CHIPID 0x3F00CF1E ++#endif ++ ++#ifndef CONFIG_MACH_CYGNUS ++extern void request_idm_timeout_interrupts(void); ++#endif ++ ++extern irqreturn_t idm_timeout_handler(int val, void *ptr); ++#if (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) ++extern void* bcm5301x_otp_init(void); ++extern int bcm5301x_otp_exit(void); ++extern int bcm5301x_otp_read_dword(void *oh, uint wn, u32 *data); ++#endif /* (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) */ ++ ++#ifdef CONFIG_MACH_CYGNUS_EMULATION //cygnus:emulator: ++ /* This is the main reference clock 25MHz from external crystal */ ++ static struct clk clk_ref = { ++ .name = "Refclk", ++ .rate = CONFIG_CYGNUS_EMULATION_SCLK, /* run-time override */ ++ .fixed = 1, ++ .type = 0, ++ }; ++#else ++/* This is the main reference clock 25MHz from external crystal */ ++static struct clk clk_ref = { ++ .name = "Refclk", ++ .rate = 25 * 1000000, /* run-time override */ ++ .fixed = 1, ++ .type = 0, ++}; ++#endif /* END of CYGNUS */ ++ ++#ifdef HNDCTF ++ctf_t *kcih = NULL; ++EXPORT_SYMBOL(kcih); ++ctf_attach_t ctf_attach_fn = NULL; ++EXPORT_SYMBOL(ctf_attach_fn); ++#endif /* HNDCTF */ ++ ++static struct clk_lookup board_clk_lookups[] = { ++ { ++ .con_id = "refclk", ++ .clk = &clk_ref, ++ } ++}; ++ ++extern void __init northstar_timer_init(struct clk *clk_ref); ++ ++#if defined(CONFIG_IPROC_SD) || defined(CONFIG_IPROC_SD_MODULE) ++/* sdio */ ++static struct sdio_platform_cfg sdio_platform_data = { ++ .devtype = SDIO_DEV_TYPE_SDMMC, ++}; ++static struct resource sdio_resources[] = { ++ [0] = { ++ .start = IPROC_SDIO_PA, ++ .end = IPROC_SDIO_PA + BSC_CORE_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_SDIO_IRQ, ++ .end = IPROC_SDIO_IRQ, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device board_sdio_device = { ++ .name = "iproc-sdio", ++ .id = 0, ++ .dev = { ++ .platform_data = &sdio_platform_data, ++ }, ++ .num_resources = ARRAY_SIZE(sdio_resources), ++ .resource = sdio_resources, ++}; ++ ++static void setup_sdio(void) ++{ ++ void __iomem *idm_base; ++ struct platform_device *sdio_plat_dev[1]; ++ idm_base = (void __iomem *)IPROC_IDM_REGISTER_VA; ++ printk("%s: %d %p\n", __FUNCTION__, __LINE__, idm_base + SDIO_IDM_IDM_RESET_CONTROL); ++ writel_relaxed(0, idm_base + SDIO_IDM_IDM_RESET_CONTROL); ++ sdio_plat_dev[0] = &board_sdio_device; ++ platform_add_devices(sdio_plat_dev, 1); ++ ++} ++#endif /* CONFIG_IPROC_SD || CONFIG_IPROC_SD_MODULE */ ++ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++static struct resource iproc_pwm_resources = { ++ .start = IPROC_CCB_PWM_CTL, ++ .end = IPROC_CCB_PWM_CTL + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device board_pwm_device = { ++ .name = "iproc_pwmc", ++ .id = -1, ++ .resource = &iproc_pwm_resources, ++ .num_resources = 1, ++}; ++static struct pwm_lookup board_pwm_lookup[] = { ++ PWM_LOOKUP("iproc_pwmc", 0,"iproc_pwmc","pwm-0"), ++ PWM_LOOKUP("iproc_pwmc", 1,"iproc_pwmc","pwm-1"), ++ PWM_LOOKUP("iproc_pwmc", 2,"iproc_pwmc","pwm-2"), ++ PWM_LOOKUP("iproc_pwmc", 3,"iproc_pwmc","pwm-3"), ++ ++}; ++ ++#endif /* CONFIG_IPROC_PWM || CONFIG_IPROC_PWM_MODULE */ ++ ++#if defined(CONFIG_IPROC_WDT) || defined(CONFIG_IPROC_WDT_MODULE) ++/* watchdog */ ++static struct resource wdt_resources[] = { ++ [0] = { ++ .start = IPROC_CCA_REG_BASE, ++ .end = IPROC_CCA_REG_BASE + 0x1000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device board_wdt_device = { ++ .name = "iproc_wdt", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(wdt_resources), ++ .resource = wdt_resources, ++}; ++#endif /* CONFIG_IPROC_WDT || CONFIG_IPROC_WDT_MODULE */ ++ ++#if defined(CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++static AMBA_APB_DEVICE(sp805_wdt, "sp805-wdt", 0x00141805, ++ IPROC_SP805_WDT_REG_BASE, { }, NULL); ++#endif ++ ++#if defined(CONFIG_IPROC_CCB_TIMER) || defined(CONFIG_IPROC_CCB_TIMER_MODULE) ++static struct resource ccb_timer_resources[] = { ++ [0] = { ++ .start = IPROC_CCB_TIMER_INT_START, ++ .end = IPROC_CCB_TIMER_INT_START + IPROC_CCB_TIMER_INT_COUNT - 1, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [1] = { ++ .start = IPROC_CCB_TIMER0_REGS_VA, ++ .end = IPROC_CCB_TIMER0_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = IPROC_CCB_TIMER1_REGS_VA, ++ .end = IPROC_CCB_TIMER1_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [3] = { ++ .start = IPROC_CCB_TIMER2_REGS_VA, ++ .end = IPROC_CCB_TIMER2_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [4] = { ++ .start = IPROC_CCB_TIMER3_REGS_VA, ++ .end = IPROC_CCB_TIMER3_REGS_VA + 0x20 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device board_timer_device = { ++ .name = "iproc_ccb_timer", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(ccb_timer_resources), ++ .resource = ccb_timer_resources, ++}; ++#endif /* CONFIG_IPROC_CCB_TIMER || CONFIG_IPROC_CCB_TIMER_MODULE */ ++ ++#if defined(CONFIG_IPROC_FA2) ++#if defined(CONFIG_MACH_NSP) ++static struct resource fa2_resources[] = { ++ [0] = { ++ .start = CTF_CONTROL_REG, /* Macro is in socregs_nsp.h */ ++ .end = CTF_CONTROL_REG + SZ_1K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 178, ++ .end = 178, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#endif ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#if !(defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) ++/* Helix4 */ ++static struct resource smbus_resources[] = { ++ [0] = { ++ .start = ChipcommonB_SMBus_Config, /* Macro is in socregs_hx4.h */ ++ .end = ChipcommonB_SMBus_Config + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 127, ++ .end = 127, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct resource smbus_resources1[] = { ++ [0] = { ++ .start = ChipcommonB_SMBus1_SMBus_Config, /* Macro is in socregs_hx4.h */ ++ .end = ChipcommonB_SMBus1_SMBus_Config + SZ_4K - 1, ++ .flags = IORESOURCE_MEM ++ }, ++ [1] = { ++ .start = 128, /* macro in irqs.h (plat-iproc) */ ++ .end = 128, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#elif defined(CONFIG_MACH_NSP) ++/* Northstar plus */ ++static struct resource smbus_resources[] = { ++ [0] = { ++ .start = ChipcommonB_SMBus_Config, /* Macro is in socregs_hx4.h */ ++ .end = ChipcommonB_SMBus_Config + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 121, ++ .end = 121, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#else ++/* Northstar */ ++static struct resource smbus_resources[] = { ++ [0] = { ++ .start = CCB_SMBUS_START, /* Define this macro is socregs.h, or ++ in iproc_regs.h */ ++ .end = CCB_SMBUS_START + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_ID_CCB_SMBUS, /* macro in irqs.h (plat-iproc) */ ++ .end = BCM_INT_ID_CCB_SMBUS, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++#endif ++ ++/* Common to Northstar, Helix4 */ ++static struct platform_device board_smbus_device = { ++ .name= "iproc-smb", ++ .id = 0, ++ .dev= { ++ .platform_data = NULL, /* Can be defined, if reqd */ ++ }, ++ .num_resources = ARRAY_SIZE(smbus_resources), ++ .resource = smbus_resources, ++}; ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) ++static struct platform_device board_smbus_device1 = { ++ .name= "iproc-smb", ++ .id = 1, ++ .dev= { ++ .platform_data = NULL, /* Can be defined, if reqd */ ++ }, ++ .num_resources = ARRAY_SIZE(smbus_resources1), ++ .resource = smbus_resources1, ++}; ++ ++#endif /* CONFIG_MACH_HX4 */ ++#endif /* Not ACCTON-AS4610-54, dni-3448p */ ++ ++#if defined(CONFIG_IPROC_FA2) ++#if defined(CONFIG_MACH_NSP) ++static struct platform_device board_fa2_device = { ++ .name= "fa2", ++ .id = 0, ++ .dev= { ++ .platform_data = NULL, /* Can be defined, if reqd */ ++ }, ++ .num_resources = ARRAY_SIZE(fa2_resources), ++ .resource = fa2_resources, ++}; ++#endif ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#ifdef CONFIG_IPROC_USB3H ++static struct resource bcm_xhci_resources[] = { ++ [0] = { ++ .start = USB30_BASE, ++ .end = USB30_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_ID_USB3H2CORE_USB2_INT0, ++ .end = BCM_INT_ID_USB3H2CORE_USB2_INT0, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 xhci_dmamask = DMA_BIT_MASK(32); ++ ++static struct platform_device bcm_xhci_device = { ++ .name = "bcm-xhci", ++ .id = 0, ++ .dev = { ++// .platform_data = &xhci_platform_data, ++ .dma_mask = &xhci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm_xhci_resources, ++ .num_resources = ARRAY_SIZE(bcm_xhci_resources), ++}; ++#endif /* CONFIG_IPROC_USB3 */ ++ ++#ifdef CONFIG_USB_EHCI_BCM ++ ++static u64 ehci_dmamask = DMA_BIT_MASK(32); ++ ++static struct resource usbh_ehci_resource[] = { ++ [0] = { ++ .start = IPROC_USB20_REG_BASE, ++ .end = IPROC_USB20_REG_BASE + 0x0FFF, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ // FIXME Cumulus: Helix4 IRQ value should be 117, ++ // some #define in plat-iproc irqgs.h is messed up ++ .start = 117, ++ .end = 117, ++ //.start = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ //.end = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device usbh_ehci_device = ++{ ++ .name = "bcm-ehci", ++ .id = 0, ++ .resource = usbh_ehci_resource, ++ .num_resources = ARRAY_SIZE(usbh_ehci_resource), ++ .dev = { ++ .dma_mask = &ehci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++}; ++#endif ++ ++#ifdef CONFIG_USB_OHCI_BCM ++ ++static u64 ohci_dmamask = DMA_BIT_MASK(32); ++ ++static struct resource usbh_ohci_resource[] = { ++ [0] = { ++ .start = IPROC_USB20_REG_BASE + 0x1000, ++ .end = IPROC_USB20_REG_BASE + 0x1000 + 0x0FFF, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ // FIXME Cumulus: Helix4 IRQ value should be 117, ++ // some #define in plat-iproc irqgs.h is messed up ++ .start = 117, ++ .end = 117, ++ //.start = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ //.end = BCM_INT_ID_USB2H2CORE_USB2_INT, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device usbh_ohci_device = ++{ ++ .name = "bcm-ohci", ++ .id = 0, ++ .resource = usbh_ohci_resource, ++ .num_resources = ARRAY_SIZE(usbh_ohci_resource), ++ .dev = { ++ .dma_mask = &ohci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++}; ++#endif ++ ++#ifdef CONFIG_SATA_AHCI_PLATFORM ++static struct resource bcm_sata_resources[] = { ++ [0] = { ++ .start = SATA_AHCI_GHC_HBA_CAP, ++ .end = SATA_AHCI_GHC_HBA_CAP + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_SATA, ++ .end = BCM_INT_SATA, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static u64 sata_dmamask = DMA_BIT_MASK(32); ++ ++static struct platform_device bcm_sata_device = { ++ .name = "strict-ahci", ++ .id = 0, ++ .dev = { ++ .dma_mask = &sata_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm_sata_resources, ++ .num_resources = ARRAY_SIZE(bcm_sata_resources), ++}; ++#endif ++ ++#ifdef CONFIG_DMAC_PL330 ++#include "../../../../bcmdrivers/dma/pl330-pdata.h" ++static struct iproc_pl330_data iproc_pl330_pdata = { ++ /* Non Secure DMAC virtual base address */ ++ .dmac_ns_base = IPROC_DMAC_REG_VA, ++ /* Secure DMAC virtual base address */ ++ .dmac_s_base = IPROC_DMAC_REG_VA, ++ /* # of PL330 dmac channels 'configurable' */ ++ .num_pl330_chans = 8, ++ /* irq number to use */ ++ .irq_base = BCM_INT_ID_DMAC, ++ /* # of PL330 Interrupt lines connected to GIC */ ++ .irq_line_count = 16, ++}; ++ ++static struct platform_device pl330_dmac_device = { ++ .name = "iproc-dmac-pl330", ++ .id = 0, ++ .dev = { ++ .platform_data = &iproc_pl330_pdata, ++ .coherent_dma_mask = DMA_BIT_MASK(64), ++ }, ++}; ++#endif ++ ++ ++#if defined(CONFIG_MACH_NSP) ++void config_AHCI( void ) ++{ ++ volatile unsigned int sata_clk_enable; ++ volatile unsigned int bustopcfg; ++ ++ printk("\nConfigure AHCI ...\n"); ++ sata_clk_enable = readl_relaxed(SATA_M0_IDM_IO_CONTROL_DIRECT_VA); ++ sata_clk_enable |= 0x1; ++ writel_relaxed( sata_clk_enable, SATA_M0_IDM_IO_CONTROL_DIRECT_VA); ++ sata_clk_enable = readl_relaxed(SATA_M0_IDM_IO_CONTROL_DIRECT_VA); ++ udelay(1000); ++ ++ ++ /* Reset core */ ++ writel_relaxed(0x0, SATA_M0_IDM_IDM_RESET_CONTROL_VA); ++ udelay(1000); ++ sata_clk_enable = readl_relaxed(SATA_M0_IDM_IDM_RESET_CONTROL_VA); ++ bustopcfg = __raw_readl(SATA_TOP_CTRL_BUS_CTRL_VA); // JIRA:LINUXDEV-39 ++ bustopcfg &= ~ (( 3 << 2) | ( 3 << 4 )); ++ bustopcfg |= (( 2 << 2) | ( 2 << 4 ));//| ( 2<< 6 )); ++ //bustopcfg |= ( ( 0x2 << 8 ) | ( 0x2 << 17 ) ); ++ writel_relaxed(bustopcfg, SATA_TOP_CTRL_BUS_CTRL_VA); ++} ++void configure_SATA_PHY ( void ) ++{ ++ unsigned int i, tmp; ++ void __iomem *bs = ioremap(AXIIC_sata_m0_fn_mod, 4); ++ ++ void __iomem *id = IOMEM(IPROC_CCA_CORE_REG_VA); ++ ++ printk("\nConfigure PHY ...\n"); ++ ++ writel_relaxed(0x0150,SATA3_PCB_UPPER_REG15_VA); ++ writel_relaxed( 0xF6F6, SATA3_PCB_UPPER_REG0_VA); ++ writel_relaxed( 0x2e96, SATA3_PCB_UPPER_REG1_VA); ++ ++ writel_relaxed(0x0160,SATA3_PCB_UPPER_REG15_VA); ++ writel_relaxed( 0xF6F6, SATA3_PCB_UPPER_REG0_VA); ++ writel_relaxed( 0x2e96, SATA3_PCB_UPPER_REG1_VA); ++ ++ //access SATA PLL ++ writel_relaxed(0x0050,SATA3_PCB_UPPER_REG15_VA); ++ //Audio PLL 0x8B ++ i = readl_relaxed(SATA3_PCB_UPPER_REG11_VA); ++ i &= ~ (( 0x1f) << 9 ); ++ i |= ( 0xC << 9); ++ writel_relaxed( i, SATA3_PCB_UPPER_REG11_VA); ++ ++ //Sequence for restarting PLL. Please try after changing the divider. ++ //'PLL_CapCtrl[10] = 1, PLL_CapCtrl[7:0] = F0h ++ //SATA3_PLL: PLL Register Bank address 0x50 ++ ++ //set register SATA3_PLL_capControl ( 0x85 ) ++ i = readl_relaxed(SATA3_PCB_UPPER_REG5_VA); ++ i = ( i | 0x4f0 ) & 0xFF0; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG5_VA); ++ ++ //'PLL_Ctrl[13:12] = 11 ++ //Set register SATA3_PLL_CONTROL ( 0x81 ) ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ i |= 0x3000; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG1_VA); ++ ++ //'PLL_ReStart ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ i &= 0x7FFF; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG1_VA); ++ mdelay(100); ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ i |= 0x8000; ++ writel_relaxed( i, SATA3_PCB_UPPER_REG1_VA); ++ mdelay(1000); ++ writel_relaxed(0x0000,SATA3_PCB_UPPER_REG15_VA); ++ i = readl_relaxed(SATA3_PCB_UPPER_REG1_VA); ++ tmp = readl(id); ++ if (tmp == NSP_CHIPID) ++ { ++ tmp = readl(bs); ++ tmp |= 0x3; ++ writel(tmp, bs); ++ tmp = readl(bs); ++ } ++} ++#endif ++ ++#ifdef CONFIG_MACH_CYGNUS ++#include "include/mach/iproc_regs.h" ++#ifdef CONFIG_IPROC_DS1WM ++#include "../../../../../bcmgpldrivers/d1w/ds1wm.h" ++ ++ ++static struct ds1wm_driver_data ds1wm_platform_data = { ++ .clock_rate = 80000000, ++ .reset_recover_delay = 1, /*ms*/ ++}; ++ ++static struct resource ds1wm_resources[] = { ++ [0] = { ++ .start = IPROC_D1W_REG_BASE, ++ .end = IPROC_D1W_REG_BASE+0x0F, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_D1W_CLK_GATE_CTRL, ++ .end = IPROC_D1W_CLK_GATE_CTRL+0x03 ++ }, ++ [2] = { ++ .start = IPROC_D1W_IO_MUX_REG, ++ .end = IPROC_D1W_IO_MUX_REG+0x03 ++ }, ++ [3] = { ++ .start = IPROC_D1W_INTR, ++ .end = IPROC_D1W_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device ds1wm_device = { ++ .name = "ds1wm", ++ .id = -1, ++ .dev = { ++ .platform_data = &ds1wm_platform_data, ++ }, ++ .num_resources = ARRAY_SIZE(ds1wm_resources), ++ .resource = ds1wm_resources, ++}; ++#endif ++ ++#ifdef CONFIG_IPROC_KEYPAD ++#include "../../../../../bcmdrivers/keypad/keypad.h" ++static iproc_keypad_t keypad_info = { ++ .max_rows = 4, ++ .max_cols = 4, ++ .StatFilEn = 1, ++ .StatFilType = 0x5, ++ .ColFilEn = 1, ++ .ColFilType = 0x05, ++ .IoMode = 0, ++ .SwapRc = 0, ++ .ScanMode = 0 ++}; ++ ++static struct resource keypad_resources[] = { ++ [0] = { ++ .start = IPROC_KEYPAD_REG_BASE, ++ .end = IPROC_KEYPAD_REG_BASE+0x4B, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_CRMU_ASIU_KEYPAD_CLK_DIV, ++ .end = IPROC_CRMU_ASIU_KEYPAD_CLK_DIV+0x03, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = IPROC_IO_MUX_REG_BASE, ++ .end = IPROC_IO_MUX_REG_BASE+0x07, ++ .flags = IORESOURCE_MEM, ++ }, ++ [3] = { ++ .start = IPROC_CLK_GATING_CTRL, ++ .end = IPROC_CLK_GATING_CTRL + 0x03, ++ .flags = IORESOURCE_MEM, ++ }, ++ [4] = { ++ .start = IPROC_KEYPAD_INTR, ++ .end = IPROC_KEYPAD_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device keypad_device = { ++ .name = "iproc-keypad", ++ .id = -1, ++ .dev = { ++ .platform_data = &keypad_info, ++ }, ++ .num_resources = ARRAY_SIZE(keypad_resources), ++ .resource = keypad_resources, ++}; ++#endif ++#ifdef CONFIG_IPROC_TOUCHSCREEN ++static struct resource tsc_resources[] = { ++ [0] = { ++ .start = IPROC_TSC_REG_BASE, ++ .end = IPROC_TSC_REG_BASE+0x3F, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_TSC_INTR, ++ .end = IPROC_TSC_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device tsc_device = { ++ .name = "iproc-tsc", ++ .id = -1, ++ .dev = { ++ .platform_data = NULL, ++ }, ++ .num_resources = ARRAY_SIZE(tsc_resources), ++ .resource = tsc_resources, ++}; ++#endif ++ ++#ifdef CONFIG_IPROC_ADC ++static struct resource adc_resources[] = { ++ [0] = { ++ .start = IPROC_ADC_REG_BASE, ++ .end = IPROC_ADC_REG_BASE+0x3F, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IPROC_ADC_INTR, ++ .end = IPROC_ADC_INTR, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device adc_device = { ++ .name = "iproc-adc", ++ .id = -1, ++ .dev = { ++ .platform_data = NULL, ++ }, ++ .num_resources = ARRAY_SIZE(adc_resources), ++ .resource = adc_resources, ++}; ++#endif ++ ++#endif ++ ++void __init board_map_io(void) ++{ ++ ++ /* ++ * Install clock sources in the lookup table. ++ */ ++ clkdev_add_table(board_clk_lookups, ++ ARRAY_SIZE(board_clk_lookups)); ++ ++ /* Map machine specific iodesc here */ ++ northstar_map_io(); ++} ++ ++void __init iproc_init_early(void) ++{ ++ ++ /* ++ * SDK allocates coherent buffers from atomic ++ * context. Increase size of atomic coherent pool to make sure such ++ * the allocations won't fail. ++ */ ++#ifdef CONFIG_CMA ++ init_dma_coherent_pool_size(SZ_1M * 16); ++#endif ++ /* ++ * Allocate contiguous himem block for SDK usage ++ */ ++#ifdef CONFIG_EARLY_DMA_ALLOC ++ eda_init(); ++#endif ++} ++ ++static struct platform_device *board_sata_device[] __initdata = { ++#ifdef CONFIG_SATA_AHCI_PLATFORM ++ &bcm_sata_device, ++#endif ++}; ++ ++static struct of_dev_auxdata iproc_auxdata_lookup[] __initdata = ++{ ++ { /* sentinel */ }, ++}; ++static struct platform_device *board_devices[] __initdata = { ++#if !(defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ &board_smbus_device, ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) ++ &board_smbus_device1, ++#endif ++#endif /*Don't use for Accton */ ++ ++#if defined(CONFIG_IPROC_FA2) ++#if defined(CONFIG_MACH_NSP) ++ &board_fa2_device, ++#endif ++#endif /* FA+ */ ++ ++#if defined(CONFIG_IPROC_CCB_TIMER) || defined(CONFIG_IPROC_CCB_TIMER_MODULE) ++ &board_timer_device, ++#endif /* CONFIG_IPROC_CCB_TIMER || CONFIG_IPROC_CCB_TIMER_MODULE */ ++#if defined(CONFIG_IPROC_WDT) || defined(CONFIG_IPROC_WDT_MODULE) ++ &board_wdt_device, ++#endif /* CONFIG_IPROC_WDT || CONFIG_IPROC_WDT_MODULE */ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++ &board_pwm_device, ++#endif /* CONFIG_IPROC_PWM || CONFIG_IPROC_PWM_MODULE */ ++#ifdef CONFIG_IPROC_USB3H ++ &bcm_xhci_device, ++#endif ++#ifdef CONFIG_USB_EHCI_BCM ++ &usbh_ehci_device, ++#endif ++#ifdef CONFIG_USB_OHCI_BCM ++ &usbh_ohci_device, ++#endif ++#ifdef CONFIG_DMAC_PL330 ++ &pl330_dmac_device, ++#endif ++#ifdef CONFIG_MACH_CYGNUS ++#ifdef CONFIG_IPROC_DS1WM ++ &ds1wm_device, ++#endif ++#ifdef CONFIG_IPROC_KEYPAD ++ &keypad_device, ++#endif ++#endif ++}; ++ ++static struct amba_device *amba_devs[] __initdata = { ++#if defined(CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++ &sp805_wdt_device, ++#endif ++}; ++ ++static void __init board_add_devices(void) ++{ ++ int i; ++ ++ platform_add_devices(board_devices, ARRAY_SIZE(board_devices)); ++// if (iproc_get_chipid() == 53010) { ++// } ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ amba_device_register(amba_devs[i], &iomem_resource); ++ } ++} ++ ++static void __init board_add_sata_device(void) ++{ ++ platform_add_devices(board_sata_device, sizeof(board_sata_device)/sizeof((board_sata_device)[0])); ++} ++ ++ ++/* SPI device info of GSIO(SPI) interface */ ++static struct spi_board_info bcm5301x_spi_device[] = { ++ { ++ .modalias = "spidev", ++ .platform_data = NULL, ++ .controller_data = NULL, ++ .max_speed_hz = 2 * 1000 * 1000, ++ .bus_num = 0, ++ .chip_select = 0, ++ .mode = SPI_MODE_0, ++ }, ++}; ++ ++void __init board_timer_init(void) ++{ ++ northstar_timer_init(&clk_ref); ++} ++ ++struct sys_timer board_timer = { ++ .init = board_timer_init, ++}; ++ ++ ++void __init board_init(void) ++{ ++ uint32_t sata_enable=0; ++ ++#if (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) ++ void *oh; ++#endif /* (defined(CONFIG_MACH_NSP) && defined(CONFIG_IPROC_OTP)) */ ++ ++ /* ++ * Add common platform devices that do not have board dependent HW ++ * configurations ++ */ ++ board_add_common_devices(&clk_ref); ++#ifndef CONFIG_MACH_CYGNUS ++#ifndef CONFIG_MACH_NS ++ /* register IDM timeout interrupt handler */ ++ request_idm_timeout_interrupts(); ++#endif ++#endif ++ ++#if defined(CONFIG_MACH_NSP) ++ #if defined(CONFIG_IPROC_OTP) ++ /* read otp row 0xd to figure if sata is enabled */ ++ oh = bcm5301x_otp_init(); ++ if (oh != NULL) ++ { ++ bcm5301x_otp_read_dword(oh, 0xd, &sata_enable); ++ printk("%s: %d %08x\n", __FUNCTION__, __LINE__, sata_enable); ++ if ((sata_enable & 0x40000000) == 0x40000000) ++ { ++ config_AHCI(); ++ configure_SATA_PHY(); ++ } ++ bcm5301x_otp_exit(); ++ } ++ else ++ printk("%s: %d bcm5301x_otp_init failed\n", __FUNCTION__, __LINE__); ++ #else /* defined(CONFIG_IPROC_OTP) */ ++ printk("%s(): IPROC OTP not configured, can not determine if SATA is enabled.\n", __FUNCTION__); ++ #endif /* defined(CONFIG_IPROC_OTP) */ ++#endif ++ ++ board_add_devices(); ++ if ((sata_enable & 0x40000000) == 0x40000000) ++ board_add_sata_device(); ++ ++ ++#if defined(CONFIG_IPROC_SD) || defined(CONFIG_IPROC_SD_MODULE) ++ /* only bcm53012 support sdio */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) == 0x0) { ++ setup_sdio(); ++ } ++#endif ++ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++ writel_relaxed(0xf, IPROC_CCB_GPIO_REG_VA + IPROC_GPIO_CCB_AUX_SEL); ++ pwm_add_table(board_pwm_lookup, ARRAY_SIZE(board_pwm_lookup)); ++#endif ++ ++ /* Register SPI device info */ ++ spi_register_board_info(bcm5301x_spi_device, ++ ARRAY_SIZE(bcm5301x_spi_device)); ++ ++ of_platform_populate(NULL, of_default_bus_match_table, ++ iproc_auxdata_lookup, NULL); ++ printk(KERN_DEBUG "board_init: Leave\n"); ++} ++ ++MACHINE_START(IPROC, "Broadcom iProc") ++ ++// Used micro9 as a reference. Micro9 removed these two fields, ++// and replaced them with a call to ep93xx_map_io(), which in turn ++// calls iotable_init(). Northstar appears to have an equivalent ++// init (refer to northstar_io_desc[] array, in io_map.c ++ .map_io = board_map_io, ++ .init_early = iproc_init_early, ++ .init_irq = iproc_init_irq, ++ .handle_irq = gic_handle_irq, ++ .timer = &board_timer, ++ .init_machine = board_init, ++MACHINE_END ++ ++static const char * helix4_dt_board_compat[] = { ++ "dni,dni_3448p", ++ "accton,as4610_54", ++ NULL ++}; ++ ++DT_MACHINE_START(HELIX4_DT, "Broadcom Helix4 (Flattened Device Tree)") ++ .map_io = board_map_io, ++ .init_early = iproc_init_early, ++ .init_irq = iproc_init_irq, ++ .handle_irq = gic_handle_irq, ++ .timer = &board_timer, ++ .init_machine = board_init, ++ .dt_compat = helix4_dt_board_compat, ++MACHINE_END +diff --git a/arch/arm/mach-iproc/common.c b/arch/arm/mach-iproc/common.c +new file mode 100644 +index 0000000..b116ffc diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch new file mode 100644 index 00000000..2fa4f8f0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.c.patch @@ -0,0 +1,353 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/common.c +@@ -0,0 +1,347 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IPROC_UART0_PA IPROC_CCA_UART0_REG_BASE ++#define IPROC_UART1_PA IPROC_CCA_UART1_REG_BASE ++#define IPROC_UART2_PA IPROC_CCB_UART0_REG_BASE ++#define IPROC_UART3_PA IPROC_CCA_UART3_REG_BASE ++#define IPROC_CCA_UART_CLK_PA IPROC_CCA_UART_CLK_REG_BASE ++#define IPROC_CCA_CCAP_PA IPROC_CCA_CORE_CAP_REG_BASE ++#define IPROC_CCA_CCTL_PA IPROC_CCA_CORE_CTL_REG_BASE ++#define IPROC_CCA_INTMASK_PA IPROC_CCA_INTMASK_REG_BASE ++ ++#define IPROC_UART0_VA HW_IO_PHYS_TO_VIRT(IPROC_UART0_PA) ++#define IPROC_UART1_VA HW_IO_PHYS_TO_VIRT(IPROC_UART1_PA) ++#define IPROC_UART2_VA HW_IO_PHYS_TO_VIRT(IPROC_UART2_PA) ++#define IPROC_UART3_VA HW_IO_PHYS_TO_VIRT(IPROC_UART3_PA) ++#define IPROC_CCA_UART_CLK_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_UART_CLK_PA) ++#define IPROC_CCA_CCAP_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_CCAP_PA) ++#define IPROC_CCA_CCTL_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_CCTL_PA) ++#define IPROC_CCA_INTMASK_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_INTMASK_PA) ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define IRQ_IPROC_UART0 117 ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P)) ++#define IRQ_IPROC_UART0 123 ++#elif defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IRQ_IPROC_UART0 123 ++#define IRQ_IPROC_UART2 124 ++#elif defined(CONFIG_MACH_HR2) ++#define IRQ_IPROC_UART0 123 ++#elif defined(CONFIG_MACH_GH) ++#define IRQ_IPROC_UART0 105 ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IRQ_IPROC_UART0 IPROC_INTERRUPTS__chipcommonG_uart0_intr ++ #define IRQ_IPROC_UART1 IPROC_INTERRUPTS__chipcommonG_uart1_intr//chandra:fix ++ #define IRQ_IPROC_UART2 IPROC_INTERRUPTS__chipcommonG_uart2_intr//chandra:fix ++ #define IRQ_IPROC_UART3 IPROC_INTERRUPTS__chipcommonG_uart3_intr//chandra:fix ++#else ++#error "No valid UART IRQ selected" ++#endif ++ ++#if defined(CONFIG_MACH_HR2) && defined(CONFIG_MACH_IPROC_EMULATION) ++#define IPROC_UART_CLK (76800) ++#elif defined(CONFIG_MACH_KT2) && defined(CONFIG_MACH_IPROC_EMULATION) ++#define IPROC_UART_CLK (65800) ++#elif defined(CONFIG_MACH_IPROC_P7) && defined(CONFIG_MACH_IPROC_EMULATION) ++#define IPROC_UART_CLK (56864) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_UART_CLK (100000000) ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IPROC_UART_CLK CONFIG_CYGNUS_EMULATION_SCLK ++#else ++#define IPROC_UART_CLK (62500000) ++#endif ++ ++#ifdef CONFIG_MACH_IPROC_P7 ++#define IPROC_8250PORT(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = IRQ_IPROC_UART0, \ ++ .uartclk = IPROC_UART_CLK, \ ++ .regshift = 2, \ ++ .iotype = UPIO_MEM32, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++#elif defined(CONFIG_MACH_CYGNUS) /* !CONFIG_MACH_IPROC_P7 */ ++#define IPROC_8250PORT(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = IRQ_IPROC_##name, \ ++ .uartclk = CONFIG_CYGNUS_EMULATION_SCLK, /*.uartclk = 62500000,*/ \ ++ .regshift = 2, \ ++ .iotype = UPIO_MEM32, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++#else /* ! CONFIG_MACH_CYGNUS */ ++#define IPROC_8250PORT(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = IRQ_IPROC_UART0, \ ++ .uartclk = IPROC_UART_CLK, \ ++ .regshift = 0, \ ++ .iotype = UPIO_MEM, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++ ++ ++#define IPROC_APB_CLK 125000000 ++ ++#define IPROC_8250PORT_UART2(name) \ ++{ \ ++ .membase = (void __iomem *)(IPROC_##name##_VA), \ ++ .mapbase = (resource_size_t)(IPROC_##name##_PA), \ ++ .irq = 124, \ ++ .uartclk = IPROC_APB_CLK, \ ++ .regshift = 2, \ ++ .iotype = UPIO_MEM32, \ ++ .type = PORT_16550A, \ ++ .flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ, \ ++ .private_data = (void __iomem *)((IPROC_##name##_VA) + 0x00), \ ++} ++ ++#endif /* CONFIG_MACH_IPROC_P7 */ ++ ++static struct plat_serial8250_port uart_data[] = { ++#if (defined(CONFIG_MACH_HR2) && !defined(CONFIG_MACH_IPROC_EMULATION)) ++ IPROC_8250PORT(UART1), /* Use UART2 as ttys0 */ ++ IPROC_8250PORT(UART0), ++#elif defined(CONFIG_MACH_CYGNUS) ++ IPROC_8250PORT(UART3), ++ IPROC_8250PORT(UART0), ++#else ++ IPROC_8250PORT(UART0), ++ IPROC_8250PORT(UART1), ++#endif ++ { .flags = 0, }, ++}; ++ ++static struct platform_device board_serial_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = uart_data, ++ }, ++}; ++ ++#if defined(CONFIG_MPCORE_WATCHDOG) ++static struct resource wdt_device_resource[] = { ++ [0] = { ++ .start = IPROC_PERIPH_PVT_TIM_REG_BASE, ++ .end = IPROC_PERIPH_PVT_TIM_REG_BASE + 0x34, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = BCM_INT_ID_CCB_TIM1_INT2, ++ .end = BCM_INT_ID_CCB_TIM1_INT2, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device wdt_device = ++{ ++ .name = "mpcore_wdt", ++ .id = -1, ++ .resource = wdt_device_resource, ++ .num_resources = ARRAY_SIZE(wdt_device_resource), ++}; ++#endif ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++/* ++ * API to return the type of platform retrieved from device tree ++ * Note: This is hack until complete device tree is supported for ++ * for all broadcom iproc device drivers ++ */ ++int brcm_get_hx4_model(void) ++{ ++ const char *model = NULL; ++ unsigned long dt_root; ++ ++ dt_root = of_get_flat_dt_root(); ++ model = of_get_flat_dt_prop(dt_root, "model", NULL); ++ if (!model) { ++ model = of_get_flat_dt_prop(dt_root, "compatible", NULL); ++ if (!model) ++ model = ""; ++ } ++ ++ if (!strcmp(model, "dni,3448p")) ++ return HX4_DNI_3448P; ++ else if (!strcmp(model, "accton,as4610_54")) ++ return HX4_ACCTON_AS4610_54; ++ ++ printk( KERN_ERR "Unknown Model %s\n", model ); ++ return HX4_NONE; ++} ++ ++/* Common devices among all Northstar boards */ ++//static struct platform_device *board_common_plat_devices[] __initdata = { ++// &board_serial_device, ++//#if defined(CONFIG_MPCORE_WATCHDOG) ++// &wdt_device, ++//#endif ++//}; ++ ++void __init iproc_config_boot_console(struct clk *ref_clk) ++{ ++ u32 i; ++ u32 clk_rate = IPROC_UART_CLK; ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++ u8 uart_clk_sel; ++ u8 uart_clk_ovr; ++ u16 uart_clk_div; ++ struct clk * clk = NULL ; ++ int modelnum; ++ ++ /* Get Core Capabilities Register, and extract ++ UART Clock Select from bits 4..3 which show ++ the clock source. Values are: ++ 0 = 25Mhz clock input ++ 1 = Internal clock ++ 2 = reserved ++ 3 = reserved ++ */ ++ uart_clk_sel = (readl(IPROC_CCA_CCAP_VA) >> 3) & 0x3; ++ ++ /* Get UARTClkOvr from bit 0 of the Core Control Register ++ If set, this bit indicates that the UART clock is supplied ++ from the internal ALP (APB) clock. If clear then it indicates ++ that APBX_IDM_IO_CONTROL_DIRECT register bit UARTClkSel controls ++ the clock source ++ */ ++ uart_clk_ovr = readl(IPROC_CCA_CCTL_VA) & 0x01; ++ ++ /* uart_clk_div: ChipcommonA_ClkDiv bits 0..7 */ ++ uart_clk_div = 0xff & readl(IPROC_CCA_UART_CLK_VA); ++ if( uart_clk_div == 0 ) ++ uart_clk_div = 0x100 ; ++ ++ if( uart_clk_sel == 0 ) { ++ /* uart_clk_sel = 0 -> external reference clock source */ ++ clk = ref_clk ; ++ BUG_ON( !clk ); ++ clk_rate = clk_get_rate(clk); ++ } else if( uart_clk_sel == 1 ) { ++ /* uart_clk_sel = 1 -> Internal clock optionally divided */ ++ clk = clk_get_sys( "iproc_slow", "c_clk125" ); ++ BUG_ON( !clk ); ++#if defined(CONFIG_MACH_IPROC_EMULATION) ++ clk_rate = IPROC_UART_CLK ; ++#else ++ clk_rate = clk_get_rate(clk) ; ++#endif ++ ++ if( ! uart_clk_ovr ) ++ clk_rate /= uart_clk_div; ++ } ++ ++ printk( KERN_INFO "Sel=%d Ovr=%d Div=%d\n", uart_clk_sel, uart_clk_ovr, uart_clk_div ); ++ printk( KERN_INFO "UART clock rate %u\n", clk_rate ); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ++ modelnum = brcm_get_hx4_model(); ++ if (modelnum == HX4_ACCTON_AS4610_54) { ++ for(i = 0; i < ARRAY_SIZE(uart_data); i++ ) { ++ switch (i) { ++ case 0: ++ uart_data[i].membase = (void __iomem *)(IPROC_UART1_VA); ++ uart_data[i].mapbase = (resource_size_t)(IPROC_UART1_PA); ++ uart_data[i].irq = IRQ_IPROC_UART0; ++ uart_data[i].uartclk = IPROC_UART_CLK; ++ uart_data[i].regshift = 0; ++ uart_data[i].iotype = UPIO_MEM; ++ uart_data[i].type = PORT_16550A; ++ uart_data[i].flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ; ++ uart_data[i].private_data = (void __iomem *)((IPROC_UART1_VA) + 0x00); ++ break; ++ case 1: ++ uart_data[i].membase = (void __iomem *)(IPROC_UART2_VA); ++ uart_data[i].mapbase = (resource_size_t)(IPROC_UART2_PA); ++ uart_data[i].irq = 124; ++ uart_data[i].uartclk = IPROC_APB_CLK; ++ uart_data[i].regshift = 2; ++ uart_data[i].iotype = UPIO_MEM32; ++ uart_data[i].type = PORT_16550A; ++ uart_data[i].flags = UPF_FIXED_TYPE | UPF_SHARE_IRQ; ++ uart_data[i].private_data = (void __iomem *)((IPROC_UART2_VA) + 0x00); ++ break; ++ } ++ } ++ } ++ ++ /* fixup UART port structure */ ++ for(i = 0; i < ARRAY_SIZE(uart_data); i++ ) { ++ if( uart_data[i].flags == 0 ) ++ break; ++ if( uart_data[i].irq == 0 ) ++ uart_data[i].flags |= UPF_AUTO_IRQ; ++ ++ /* XXX TBD - UART input clock source and rate */ ++ if(i != 1) { ++ uart_data[i].uartclk = clk_rate ; ++ } ++ ++ } ++ ++ /* Install SoC devices in the system: uarts */ ++ platform_device_register(&board_serial_device); ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++ /* Enable UART interrupt in ChipcommonA */ ++ i = readl(IPROC_CCA_INTMASK_VA); ++ i |= 1 << 6; ++ writel(i, IPROC_CCA_INTMASK_VA); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++} ++ ++void __init board_add_common_devices(struct clk *ref_clk) ++{ ++ /* ++ * Configure boot console ++ */ ++ iproc_config_boot_console(ref_clk); ++} +diff --git a/arch/arm/mach-iproc/common.h b/arch/arm/mach-iproc/common.h +new file mode 100644 +index 0000000..d49a6b9 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch new file mode 100644 index 00000000..42454e17 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_common.h.patch @@ -0,0 +1,34 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/common.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __MACH_NORTHSTAR_COMMON_H ++#define __MACH_NORTHSTAR_COMMON_H ++#include ++#include ++#include ++#include ++ ++#include ++ ++void __init board_add_common_devices(struct clk *ref_clk); ++ ++#endif /* __MACH_NORTHSTAR_COMMON_H */ +diff --git a/arch/arm/mach-iproc/flash.c b/arch/arm/mach-iproc/flash.c +new file mode 100644 +index 0000000..8fd637b diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch new file mode 100644 index 00000000..0f84f3b9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_flash.c.patch @@ -0,0 +1,381 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/flash.c +@@ -0,0 +1,375 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++ ++#ifdef CONFIG_MTD ++ ++#include ++#include ++#include ++ ++/* Since GSIO uses bus number 0, QSPI uses bus number 1 */ ++#define IPROC_QSPI_BUS_NUMBER (1) ++ ++/* Currently NAND controller only supports 2 LUNs */ ++#define IPROC_NAND_MAX_LUNS (2) ++ ++int brcm_get_hx4_model(void); ++ ++#if defined(CONFIG_IPROC_QSPI) || defined(CONFIG_IPROC_QSPI_MODULE) ++static struct mtd_partition accton_as4610_sflash_partition_map[] = { ++ { ++ .name = "nboot", ++ .offset = 0x00000000, ++ .size = 0x000e0000, ++ }, ++ { ++ .name = "shmoo", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x0010000, ++ }, ++ { ++ .name = "uboot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00010000, ++ }, ++ { ++ .name = "onie", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++#if defined(CONFIG_MACH_HX4) ++static struct mtd_partition sflash_partition_map[] = { ++ { ++ .name = "boot", ++ .offset = 0x00000000, ++ .size = 640 * 1024, ++ }, ++ { ++ .name = "env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 384 * 1024, ++ }, ++ { ++ .name = "system", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 15 * 1024 * 1024, ++ }, ++ { ++ .name = "rootfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++#endif /* Unused code for Accton AS4610-54 and DNI-3448P */ ++#endif /* CONFIG_IPROC_QSPI || CONFIG_IPROC_QSPI_MODULE */ ++ ++#if defined(CONFIG_IPROC_MTD_NAND) || defined(CONFIG_IPROC_MTD_NAND_MODULE) ++static struct mtd_partition dni_3448p_nand_partition_map[] = { ++ { ++ .name = "uboot", ++ .offset = 0x00000000, ++ .size = 0x00100000, ++ }, ++ { ++ .name = "uboot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00400000, ++ }, ++ { ++ .name = "vpd", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00200000, ++ }, ++ { ++ .name = "shmoo", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00200000, ++ }, ++ { ++ .name = "open", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0xf9500000, ++ }, ++ { ++ .name = "onie", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00c00000, ++ }, ++ { ++ .name = "onie2", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00c00000, ++ }, ++ { ++ .name = "board_eeprom", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x00600000, ++ }, ++ { ++ .name = "diag", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x02000000, ++ }, ++ { ++ .name = "diag2", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x02000000, ++ }, ++}; ++static struct mtd_partition accton_as4610_nand_partition_map[] = { ++}; ++ ++static struct mtd_partition nand_partition_map[] = { ++ { ++ .name = "nboot", ++ .offset = 0x00000000, ++ .size = 2 * 1024 * 1024, ++ }, ++ { ++ .name = "nenv", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 4 * 1024 * 1024, ++ }, ++ { ++ .name = "nsystem", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 10 * 1024 * 1024, ++ }, ++ { ++ .name = "nrootfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 48 * 1024 * 1024, ++ }, ++ { ++ .name = "ncustfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++#endif /* CONFIG_IPROC_MTD_NAND || CONFIG_IPROC_MTD_NAND_MODULE */ ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++#if defined(CONFIG_IPROC_QSPI) || defined(CONFIG_IPROC_QSPI_MODULE) ++static int __init ++brcm_setup_spi_master(int cs, int bus_id) ++{ ++ struct brcmspi_platform_data pdata; ++ struct platform_device *pdev; ++ const struct resource res[] = { ++ { ++ .start = IPROC_QSPI_IRQ_START, ++ .end = IPROC_QSPI_IRQ_END, ++ .flags = IORESOURCE_IRQ ++ }, ++ { ++ .start = QSPI_MSPI_SPCR0_LSB, ++ .end = QSPI_MSPI_DISABLE_FLUSH_GEN + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = QSPI_BSPI_REGS_REV_ID, ++ .end = QSPI_BSPI_REGS_BSPI_PIO_DATA + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = QSPI_RAF_START_ADDR, ++ .end = QSPI_RAF_CURR_ADDR + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = QSPI_RAF_INTERRUPT_LR_FULLNESS_REACHED, ++ .end = QSPI_MSPI_INTERRUPT_MSPI_HALT_SET_TRANSACTION_DONE + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IPROC_IDM_QSPI_REG_BASE, ++ .end = IPROC_IDM_QSPI_REG_BASE + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ { ++ .start = IPROC_CRU_REG_BASE, ++ .end = IPROC_CRU_REG_BASE + 3, ++ .flags = IORESOURCE_MEM ++ }, ++ }; ++ ++ memset(&pdata, 0, sizeof(pdata)); ++ pdata.flash_cs = cs; ++ pdev = platform_device_alloc("qspi_iproc", bus_id); ++ if (!pdev || ++ platform_device_add_resources(pdev, res, sizeof(res)/sizeof(res[0])) || ++ platform_device_add_data(pdev, &pdata, sizeof(pdata)) || ++ platform_device_add(pdev)) { ++ platform_device_put(pdev); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++static int __init ++brcm_setup_spi_flash(int cs, int bus_num, int nr_parts, struct mtd_partition *parts) ++{ ++ struct spi_board_info board_info; ++ struct flash_platform_data *pdata; ++ struct spi_master *master; ++ ++ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ ++ pdata->nr_parts = nr_parts; ++ pdata->parts = parts; ++ ++ memset(&board_info, 0, sizeof(board_info)); ++ ++ strcpy(board_info.modalias, "m25p80"); ++ board_info.bus_num = bus_num; ++ board_info.chip_select = cs; ++ board_info.max_speed_hz = CONFIG_IPROC_QSPI_MAX_HZ; ++ board_info.mode = SPI_MODE_3; ++ board_info.platform_data = pdata; ++ ++ master = spi_busnum_to_master(bus_num); ++ if (master) { ++ /* Master driver already loaded */ ++ if (spi_new_device(master, &board_info) == NULL) { ++ printk(KERN_WARNING "%s: can't add SPI device\n", __func__); ++ kfree(pdata); ++ return -ENODEV; ++ } ++ } else { ++ /* Master driver not yet loaded, register the board first. */ ++ if (spi_register_board_info(&board_info, 1) != 0) { ++ printk(KERN_WARNING "%s: can't register SPI device\n", __func__); ++ kfree(pdata); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_IPROC_QSPI || CONFIG_IPROC_QSPI_MODULE */ ++ ++#if defined(CONFIG_IPROC_MTD_NAND) || defined(CONFIG_IPROC_MTD_NAND_MODULE) ++static void __init ++northstar_setup_nand_flash(void) ++{ ++ u32 straps; ++ struct platform_device *pdev; ++ struct brcmnand_platform_data pdata; ++ int i, modelnum; ++ ++ straps = __REG32(IPROC_DMU_BASE_VA + IPROC_DMU_STRAPS_OFFSET); ++ pdata.strap_boot = ((straps >> IPROC_STRAP_BOOT_DEV_SHIFT) & 3) == 1; ++ pdata.strap_type = (straps >> IPROC_STRAP_NAND_TYPE_SHIFT) & 0xf; ++ pdata.strap_page_size = (straps >> IPROC_STRAP_NAND_PAGE_SHIFT) & 0x3; ++ if (!pdata.strap_boot) { ++ pdata.strap_type &= 0x7; ++ } ++ ++ modelnum = brcm_get_hx4_model(); ++ ++ if (modelnum == HX4_DNI_3448P) { ++ pdata.nr_parts = ARRAY_SIZE(dni_3448p_nand_partition_map); ++ pdata.parts = dni_3448p_nand_partition_map; ++ } else if (modelnum == HX4_ACCTON_AS4610_54) { ++ pdata.nr_parts = ARRAY_SIZE(accton_as4610_nand_partition_map); ++ pdata.parts = accton_as4610_nand_partition_map; ++ } else { ++ pdata.nr_parts = ARRAY_SIZE(nand_partition_map); ++ pdata.parts = nand_partition_map; ++ } ++ ++ for(i=0; i 0) { ++ pdata.nr_parts = 0; ++ pdata.parts = NULL; ++ } ++ ++ pdata.chip_select = i; ++ pdev = platform_device_alloc("nand_iproc", i); ++ if (!pdev || ++ platform_device_add_data(pdev, &pdata, sizeof(pdata)) || ++ platform_device_add(pdev)) { ++ platform_device_put(pdev); ++ } ++ } ++} ++#endif /* CONFIG_IPROC_MTD_NAND || CONFIG_IPROC_MTD_NAND_MODULE */ ++ ++static int __init ++northstar_mtd_setup(void) ++{ ++#if defined(CONFIG_IPROC_QSPI) || defined(CONFIG_IPROC_QSPI_MODULE) ++ if (brcm_get_hx4_model() == HX4_ACCTON_AS4610_54) { ++ /* SPI flash (currently used for primary) */ ++ brcm_setup_spi_master( ++ 0, ++ IPROC_QSPI_BUS_NUMBER ++ ); ++ brcm_setup_spi_flash( ++ 0, ++ IPROC_QSPI_BUS_NUMBER, ++ ARRAY_SIZE(accton_as4610_sflash_partition_map), ++ accton_as4610_sflash_partition_map ++ ); ++ } /* Required only for Accton AS4610 54*/ ++#endif /* CONFIG_IPROC_QSPI || CONFIG_IPROC_QSPI_MODULE */ ++ ++#if defined(CONFIG_IPROC_MTD_NAND) || defined(CONFIG_IPROC_MTD_NAND_MODULE) ++#ifdef CONFIG_MACH_NS ++ /* Don't bring up NAND driver if it's BCM53010 */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) != 0x4) ++#endif /* CONFIG_MACH_NS */ ++ northstar_setup_nand_flash(); ++#endif /* CONFIG_IPROC_MTD_NAND || CONFIG_IPROC_MTD_NAND_MODULE */ ++ ++ return 0; ++} ++ ++/* ++ * late_initcall means the flash drivers are already loaded, so we control ++ * the order in which the /dev/mtd* devices get created. ++ */ ++late_initcall(northstar_mtd_setup); ++ ++#endif /* CONFIG_MTD */ +diff --git a/arch/arm/mach-iproc/idm.c b/arch/arm/mach-iproc/idm.c +new file mode 100644 +index 0000000..444c3fe diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch new file mode 100644 index 00000000..d6aa9c6c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_idm.c.patch @@ -0,0 +1,729 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/idm.c +@@ -0,0 +1,723 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_MACH_NSP ++/* this is actually AXI_PCIE_S2 but for HX4, HR2, and KT2 it has been hijacked by CMICD */ ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL AXI_PCIE_S2_IDM_IDM_ERROR_LOG_CONTROL ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE AXI_PCIE_S2_IDM_IDM_ERROR_LOG_COMPLETE ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS AXI_PCIE_S2_IDM_IDM_ERROR_LOG_STATUS ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ADDR_LSB ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ID ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS AXI_PCIE_S2_IDM_IDM_ERROR_LOG_FLAGS ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS AXI_PCIE_S2_IDM_IDM_INTERRUPT_STATUS ++ ++#endif ++ ++#ifdef CONFIG_MACH_NS ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18106900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18106904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18106908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810690C ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18106914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810691C ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18106A00 ++ ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810790C ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810791C ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18107A00 ++ ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18108908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810890C ++#define DDR_S1_IDM_ERROR_LOG_ID 0x18108914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810891C ++#define DDR_S1_IDM_INTERRUPT_STATUS 0x18108A00 ++ ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0x18109908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810990C ++#define DDR_S2_IDM_ERROR_LOG_ID 0x18109914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810991C ++#define DDR_S2_IDM_INTERRUPT_STATUS 0x18109A00 ++ ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810A900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810A904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810A908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810A90C ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810A914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810A91C ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810AA00 ++ ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x1810B900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x1810B904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x1810B908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810B90C ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x1810B914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810B91C ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x1810BA00 ++ ++/* this is actually AXI_PCIE_S2 but for HX4, HR2, and KT2 it has been hijacked by CMICD */ ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810C900 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810C904 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810C908 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810C90C ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810C914 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810C91C ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810CA00 ++ ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1810D900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1810D904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1810D908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810D90C ++#define ROM_S0_IDM_ERROR_LOG_ID 0x1810D914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1810D91C ++#define ROM_S0_IDM_INTERRUPT_STATUS 0x1810DA00 ++ ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811A900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811A904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811A908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811A90C ++#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811A914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811A91C ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811AA00 ++ ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811B900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811B904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811B908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811B90C ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811B914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811B91C ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811BA00 ++ ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811C900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811C904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811C908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811C90C ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811C914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811C91C ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811CA00 ++ ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18121908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190C ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18121914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1812191C ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x1812A900 ++ ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x181312908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18132910 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x18132904 ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18132A00 ++ ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18133900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18133904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x181313908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1813390c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18133910 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x18133904 ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18133A00 ++ ++#define AXIIC_DS_2_IDM_ERROR_LOG_CONTROL 0x18134900 ++#define AXIIC_DS_2_IDM_ERROR_LOG_COMPLETE 0x18134904 ++#define AXIIC_DS_2_IDM_ERROR_LOG_STATUS 0x181314908 ++#define AXIIC_DS_2_IDM_ERROR_LOG_ADDR_LSB 0x1813490c ++#define AXIIC_DS_2_IDM_ERROR_LOG_ID 0x18134910 ++#define AXIIC_DS_2_IDM_ERROR_LOG_FLAGS 0x18134904 ++#define AXIIC_DS_2_IDM_INTERRUPT_STATUS 0x18134A00 ++ ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18135900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18135904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x181315908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1813590c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18135910 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x18135904 ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18135A00 ++ ++#define AXIIC_DS_4_IDM_ERROR_LOG_CONTROL 0x18136900 ++#define AXIIC_DS_4_IDM_ERROR_LOG_COMPLETE 0x18136904 ++#define AXIIC_DS_4_IDM_ERROR_LOG_STATUS 0x181316908 ++#define AXIIC_DS_4_IDM_ERROR_LOG_ADDR_LSB 0x1813690c ++#define AXIIC_DS_4_IDM_ERROR_LOG_ID 0x18136910 ++#define AXIIC_DS_4_IDM_ERROR_LOG_FLAGS 0x18136904 ++#define AXIIC_DS_4_IDM_INTERRUPT_STATUS 0x18136A00 ++ ++#define IHOST_L2C_INT_MASK 0x19022214 ++#define IHOST_GICDIST_enable_set2 0x19021108 ++ ++#endif ++ ++#define IHOST_L2C_INT_MASK_VA HW_IO_PHYS_TO_VIRT(IHOST_L2C_INT_MASK) ++#define IHOST_GICDIST_enable_set2_VA HW_IO_PHYS_TO_VIRT(IHOST_GICDIST_enable_set2) ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_CONTROL) ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_COMPLETE) ++#define IHOST_S1_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_STATUS) ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_ADDR_LSB) ++#define IHOST_S1_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_ID) ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(IHOST_S1_IDM_ERROR_LOG_FLAGS) ++ ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_CONTROL) ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_COMPLETE) ++#define IHOST_S0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_STATUS) ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_ADDR_LSB) ++#define IHOST_S0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_ID) ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(IHOST_S0_IDM_ERROR_LOG_FLAGS) ++ ++#define DDR_S1_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_CONTROL) ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_COMPLETE) ++#define DDR_S1_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_STATUS) ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_ADDR_LSB) ++#define DDR_S1_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_ID) ++#define DDR_S1_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(DDR_S1_IDM_ERROR_LOG_FLAGS) ++ ++#define DDR_S2_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_CONTROL) ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_COMPLETE) ++#define DDR_S2_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_STATUS) ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_ADDR_LSB) ++#define DDR_S2_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_ID) ++#define DDR_S2_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(DDR_S2_IDM_ERROR_LOG_FLAGS) ++ ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID) ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_ID) ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBY_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_ID) ++#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBY_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define ROM_S0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_CONTROL) ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_COMPLETE) ++#define ROM_S0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_STATUS) ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_ADDR_LSB) ++#define ROM_S0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_ID) ++#define ROM_S0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(ROM_S0_IDM_ERROR_LOG_FLAGS) ++ ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_CONTROL) ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_COMPLETE) ++#define NAND_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_STATUS) ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define NAND_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_ID) ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(NAND_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_CONTROL) ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_COMPLETE) ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_STATUS) ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define QSPI_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_ID) ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(QSPI_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_ID) ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_CONTROL) ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_COMPLETE) ++#define SRAM_S0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_STATUS) ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_ADDR_LSB) ++#define SRAM_S0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_ID) ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(SRAM_S0_IDM_ERROR_LOG_FLAGS) ++ ++#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_ID) ++#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_CONTROL) ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE) ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_STATUS) ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB) ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_ID) ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_3_IDM_ERROR_LOG_FLAGS) ++ ++#define APBW_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBW_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBW_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_STATUS) ++#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBW_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_ID) ++#define APBW_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBW_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_CONTROL) ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_COMPLETE) ++#define APBX_IDM_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_STATUS) ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_ADDR_LSB) ++#define APBX_IDM_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_ID) ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(APBX_IDM_IDM_ERROR_LOG_FLAGS) ++ ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_CONTROL) ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE) ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_STATUS) ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB) ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_ID) ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS_VA HW_IO_PHYS_TO_VIRT(AXIIC_DS_0_IDM_ERROR_LOG_FLAGS) ++ ++#define IDM_ERROR_LOG_ENABLE 0x33A ++#define IDM_ERROR_LOG_CLEAR 0x3 ++ ++#ifdef CONFIG_MACH_IPROC_P7 ++#define IHOST_S0_IDM_IRQ 52 ++#define DDR_S1_IDM_IRQ 54 ++#define DDR_S2_IDM_IRQ 55 ++#define AXI_PCIE_S0_IDM_IRQ 56 ++#define AXI_PCIE_S1_IDM_IRQ 57 ++#define ROM_S0_IDM_IRQ 58 ++#define NAND_IDM_IRQ 59 ++#define QSPI_IDM_IRQ 60 ++#define SRAM_S0_IDM_IRQ 62 ++#define A9JTAG_S0_IDM_IRQ 64 ++#define APX_IDM_IRQ 68 ++#define CMICD_S0_IDM_IRQ 71 ++#define AXIIC_DS_0_IDM_IRQ 78 ++#define AXIIC_DS_1_IDM_IRQ 79 ++#define AXIIC_DS_2_IDM_IRQ 80 ++#define AXIIC_DS_3_IDM_IRQ 81 ++#define AXIIC_DS_4_IDM_IRQ 83 ++#else ++#define IHOST_S1_IDM_IRQ 62 ++#define IHOST_S0_IDM_IRQ 63 ++#define DDR_S1_IDM_IRQ 64 ++#define DDR_S2_IDM_IRQ 65 ++#define AXI_PCIE_S0_IDM_IRQ 66 ++#define AXI_PCIE_S1_IDM_IRQ 67 ++#define CMICD_S0_IDM_IRQ 68 ++#define ROM_S0_IDM_IRQ 69 ++#define NAND_IDM_IRQ 70 ++#define QSPI_IDM_IRQ 71 ++#define SATA_IDM_IRQ 72 ++#define A9JTAG_S0_IDM_IRQ 73 ++#define SRAM_S0_IDM_IRQ 74 ++#define APW_IDM_IRQ 75 ++#define APX_IDM_IRQ 76 ++#define APBY_S0_IDM_IRQ 77 ++#define APBZ_S0_IDM_IRQ 78 ++#define AXIIC_DS_0_IDM_IRQ 79 ++#define AXIIC_DS_1_IDM_IRQ 80 ++#define AXIIC_DS_2_IDM_IRQ 81 ++#define AXIIC_DS_3_IDM_IRQ 82 ++#define AXIIC_DS_4_IDM_IRQ 83 ++#endif ++ ++static irqreturn_t idm_timeout_handler(int val, void *ptr) ++{ ++ u32 errStat; ++// printk("%s: %d, %d entry\n", __FUNCTION__, __LINE__, val); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, IHOST_S1_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(IHOST_S1_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(IHOST_S0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, DDR_S1_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(DDR_S1_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, DDR_S2_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(DDR_S2_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(CMICD_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#if !defined(CONFIG_MACH_NS) && !defined(CONFIG_MACH_IPROC_P7) ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBY_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#endif ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, ROM_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(ROM_S0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, NAND_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(NAND_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, QSPI_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(QSPI_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#if !defined(CONFIG_MACH_NS) && !defined(CONFIG_MACH_IPROC_P7) ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, SRAM_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(SRAM_S0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBZ_S0_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#endif ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(AXIIC_DS_3_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#if !defined(CONFIG_MACH_NS) && !defined(CONFIG_MACH_IPROC_P7) ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBW_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBW_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++#endif ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, APBX_IDM_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(APBX_IDM_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA); ++ if (errStat > 0) ++ { ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_ID_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_FLAGS_VA); ++// printk("%s: %d, %08x\n", __FUNCTION__, __LINE__, errStat); ++ __raw_writel(IDM_ERROR_LOG_CLEAR, AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE_VA); ++ errStat = __raw_readl(AXIIC_DS_0_IDM_ERROR_LOG_STATUS_VA); ++// printk("%s: %d, %d\n", __FUNCTION__, __LINE__, errStat); ++ } ++// printk("%s: %d exit\n", __FUNCTION__, __LINE__); ++ return IRQ_HANDLED; ++} ++ ++int l2cc_interrupt_error_handler(int val, void *ptr) ++{ ++ printk("%s: %d, %d entry\n", __FUNCTION__, __LINE__, val); ++ printk("%s: %d exit\n", __FUNCTION__, __LINE__); ++ return 0; ++} ++ ++void request_idm_timeout_interrupts(void) ++{ ++ u32 l2cc_mask; ++ int ret = 0; ++ ++// printk("%s: %d entry\n", __FUNCTION__, __LINE__); ++ ++ /* clear all pending idm interrupts */ ++ idm_timeout_handler(0, NULL); ++ ++ /* enable idm error log for all slaves */ ++ ++ __raw_writel(IDM_ERROR_LOG_ENABLE, IHOST_S1_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, IHOST_S0_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, DDR_S1_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, DDR_S2_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ ++#ifndef CONFIG_MACH_NS ++ __raw_writel(IDM_ERROR_LOG_ENABLE, SRAM_S0_IDM_ERROR_LOG_CONTROL_VA); ++#ifndef CONFIG_MACH_IPROC_P7 ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBY_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBW_IDM_IDM_ERROR_LOG_CONTROL_VA); ++#endif ++#endif ++ ++ __raw_writel(IDM_ERROR_LOG_ENABLE, ROM_S0_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, NAND_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, QSPI_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, APBX_IDM_IDM_ERROR_LOG_CONTROL_VA); ++ __raw_writel(IDM_ERROR_LOG_ENABLE, AXIIC_DS_0_IDM_ERROR_LOG_CONTROL_VA); ++ ++ /* now enable the idm interrupts */ ++ ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(IHOST_S1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ret = request_irq(IHOST_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(DDR_S1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(DDR_S2_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXI_PCIE_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXI_PCIE_S1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(CMICD_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(ROM_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(NAND_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(QSPI_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(SATA_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ret = request_irq(A9JTAG_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(SRAM_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(APX_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(APW_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(APBY_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(APBZ_S0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++ ret = request_irq(AXIIC_DS_0_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXIIC_DS_1_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXIIC_DS_2_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++ ret = request_irq(AXIIC_DS_3_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#ifndef CONFIG_MACH_IPROC_P7 ++ ret = request_irq(AXIIC_DS_4_IDM_IRQ, (irq_handler_t)idm_timeout_handler, IRQF_DISABLED | IRQF_PERCPU, "IDM", NULL); ++ if (ret != 0) ++ printk("%s: %d request_irq return = %d\n", __FUNCTION__, __LINE__, ret); ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++// printk("%s: %d exit\n", __FUNCTION__, __LINE__); ++} +diff --git a/arch/arm/mach-iproc/include/mach/io_map.h b/arch/arm/mach-iproc/include/mach/io_map.h +new file mode 100644 +index 0000000..01dd6fd diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch new file mode 100644 index 00000000..ea279572 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_io_map.h.patch @@ -0,0 +1,92 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/io_map.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __NORTHSTAR_IO_MAP_H ++#define __NORTHSTAR_IO_MAP_H ++ ++#include ++#include ++#include ++ ++#define IPROC_CCA_CORE_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_REG_BASE) ++#define IPROC_CCA_UART0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCA_UART0_REG_BASE) ++#define IPROC_CCB_GPIO_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_GPIO_REG_BASE) ++#define IPROC_CCB_PWM_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_PWM_REG_BASE) ++#define IPROC_CCB_MDIO_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_MDIO_REG_BASE) ++#define IPROC_CCB_RNG_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_RNG_REG_BASE) ++#define IPROC_CCB_TIM0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_TIM0_REG_BASE) ++#define IPROC_CCB_TIM1_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_TIM1_REG_BASE) ++#define IPROC_CCB_SRAU_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_SRAU_REG_BASE) ++#define IPROC_CCB_UART0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_CCB_UART0_REG_BASE) ++ ++#define IPROC_DDRC_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_DDRC_REG_BASE) ++#define IPROC_DMAC_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_DMAC_REG_BASE) ++#define IPROC_PCIE_AXIB0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PCIE_AXIB0_REG_BASE) ++#define IPROC_PCIE_AXIB1_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PCIE_AXIB1_REG_BASE) ++#define IPROC_PCIE_AXIB2_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PCIE_AXIB2_REG_BASE) ++ ++#define IPROC_SDIO3_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_SDIO3_REG_BASE) ++#define IPROC_USB20_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB20_REG_BASE) ++#define IPROC_USB30_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB30_REG_BASE) ++#define IPROC_USB20_PHY_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB20_PHY_REG_BASE) ++#define IPROC_GMAC0_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC0_REG_BASE) ++#define IPROC_GMAC1_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC1_REG_BASE) ++#define IPROC_GMAC2_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC2_REG_BASE) ++#define IPROC_GMAC3_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_GMAC3_REG_BASE) ++#define IPROC_DMU_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_DMU_REG_BASE) ++#define IPROC_CRU_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_CRU_REG_BASE) ++#define IPROC_IDM_REGISTER_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_REG_BASE) ++#define IPROC_USB2D_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2D_REG_BASE) ++ ++#define IPROC_CTF_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_CTF_REG_BASE) ++ ++/* ARM9 Private memory region */ ++#define PERIPH_BASE IPROC_PERIPH_BASE ++#define IPROC_PERIPH_VA HW_IO_PHYS_TO_VIRT(IPROC_PERIPH_BASE) ++#define IPROC_PERIPH_SCU_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_PERIPH_BASE) ++#define IPROC_PERIPH_INT_CTRL_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x100) ++#define IPROC_PERIPH_GLB_TIM_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x200) ++#define IPROC_PERIPH_PVT_TIM_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x600) ++#define IPROC_PERIPH_PVT_WDT_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x620) ++#define IPROC_PERIPH_INT_DISTR_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x1000) ++#define IPROC_L2CC_REG_VA HW_IO_PHYS_TO_VIRT(PERIPH_BASE + 0x2000) ++ ++#define IPROC_ROOT_CLK_VA HW_IO_PHYS_TO_VIRT(IPROC_CLK_WR_ACC_REG_BASE) ++#define IPROC_GICCPU_VA HW_IO_PHYS_TO_VIRT(IPROC_GICCPU_CTL_REG_BASE) ++ ++#define CCU_PROF_REG_BASE IPROC_CCU_PROF_CTL_REG_BASE ++#define IPROC_CCU_PROF_CTL_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE) ++#define IPROC_CCU_PROF_SEL_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE + 0x004) ++#define IPROC_CCU_PROF_CNT_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE + 0x008) ++#define IPROC_CCU_PROF_DBG_REG_VA HW_IO_PHYS_TO_VIRT(CCU_PROF_REG_BASE + 0x00C) ++ ++#ifdef CONFIG_MACH_CYGNUS ++ #define IPROC_UART_LLDEBUG_PA IPROC_CCA_UART3_REG_BASE ++ #define IPROC_UART_LLDEBUG_VA HW_IO_PHYS_TO_VIRT(IPROC_UART_LLDEBUG_PA) ++#else ++ #define IPROC_UART_LLDEBUG_PA IPROC_CCA_UART0_REG_BASE ++ #define IPROC_UART_LLDEBUG_VA IPROC_CCA_UART0_REG_VA ++#endif ++ ++#define IPROC_I2S_REG_VA HW_IO_PHYS_TO_VIRT(IPROC_I2S_REG_BASE) ++ ++#endif /*__NORTHSTAR_IO_MAP_H */ +diff --git a/arch/arm/mach-iproc/include/mach/iproc_regs.h b/arch/arm/mach-iproc/include/mach/iproc_regs.h +new file mode 100644 +index 0000000..460c436 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch new file mode 100644 index 00000000..d3f9f688 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_iproc_regs.h.patch @@ -0,0 +1,830 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/iproc_regs.h +@@ -0,0 +1,824 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __IPROC_REGS_H ++#define __IPROC_REGS_H __FILE__ ++#include ++#ifdef CONFIG_MACH_CYGNUS ++#include "socregs-cygnus.h" ++#elif defined(CONFIG_MACH_NS) ++#include "socregs_ns_open.h" ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "socregs_ing_open.h" ++#elif defined(CONFIG_MACH_NSP) ++#include "socregs_nsp_open.h" ++#elif defined(CONFIG_MACH_IPROC_P7) ++#include "socregs_p7_open.h" ++#else ++#error "No valid iProc Machine type selected" ++#endif ++ ++#if defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_IPROC_P7) || \ ++ defined(CONFIG_MACH_CYGNUS) ++#define IPROC_NUM_CPUS (1) ++#else ++#define IPROC_NUM_CPUS (2) ++#endif ++ ++#if defined(CONFIG_MACH_CYGNUS) ++#define IPROC_NUM_IRQS (IPROC_INTERRUPTS_WIDTH) ++#else ++#define IPROC_NUM_IRQS (256) ++#endif /* end of CONFIG_MACH_CYGNUS) */ ++ ++#define IPROC_CPU0_MIN_INT_PRIORITY (0) ++#define IPROC_CPU1_MIN_INT_PRIORITY (0) ++ ++#if defined(CONFIG_MACH_CYGNUS) ++#define IPROC_DDR_MEM_BASE1 (0x02000000) ++#else ++#define IPROC_DDR_MEM_BASE1 (0x0) ++#endif /* end of CONFIG_MACH_CYGNUS */ ++ ++#if defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_CYGNUS) ++#define IPROC_DDR_MEM_BASE2 (0x60000000) ++#else ++#define IPROC_DDR_MEM_BASE2 (0x80000000) ++#endif ++ ++ ++/* remap to newer reg file defs */ ++#ifndef CONFIG_MACH_NS ++#ifdef CONFIG_MACH_CYGNUS //chandra: todo- has to check ++ #define CCA_CHIPID ICFG_CHIP_ID_REG ++#else ++ #define CCA_CHIPID ChipcommonA_ChipID ++#endif ++ ++#define NAND_NAND_FLASH_REV NAND_nand_flash_REVISION ++#define NAND_DIRECT_READ_RD_MISS NAND_direct_read_rd_miss ++#define NAND_ECC_MIPS_CORR NAND_ecc_mips_corr ++#define NAND_NAND_FLASH_FLASH_CACHE127 NAND_nand_flash_FLASH_CACHE127 ++#define QSPI_MSPI_SPCR0_LSB QSPI_mspi_SPCR0_LSB ++#define QSPI_MSPI_DISABLE_FLUSH_GEN QSPI_mspi_DISABLE_FLUSH_GEN ++#define QSPI_BSPI_REGS_REV_ID QSPI_bspi_registers_REVISION_ID ++#define QSPI_BSPI_REGS_BSPI_PIO_DATA QSPI_bspi_registers_BSPI_PIO_DATA ++#define QSPI_RAF_START_ADDR QSPI_raf_START_ADDR ++#define QSPI_RAF_CURR_ADDR QSPI_raf_CURR_ADDR ++#define QSPI_RAF_INTERRUPT_LR_FULLNESS_REACHED QSPI_raf_interrupt_LR_fullness_reached ++#define QSPI_MSPI_INTERRUPT_MSPI_HALT_SET_TRANSACTION_DONE QSPI_mspi_interrupt_MSPI_halt_set_transaction_done ++ ++#define CCB_TIM0_TIM_TMR1_LOAD ChipcommonB_tim0_TIM_TIMER1Load ++#define CCB_TIM1_TIM_TMR1_LOAD ChipcommonB_tim1_TIM_TIMER1Load ++ ++#define GMAC0_DEVCT GMAC0_DEVCONTROL ++ ++#define CCA_GPIO_EVT_BASE ChipcommonA_GPIOEvent_BASE ++#define CCA_GPIO_INPUT_BASE ChipcommonA_GPIOInput_BASE ++#define CCB_GP_INT_CLR_BASE ChipcommonB_GP_INT_TYPE_BASE ++ ++#define PAXB_0_PCIE_CTL (PAXB_0_CLK_CONTROL) ++ ++#define CCB_MII_MGMT_CTL ChipcommonB_MII_Management_Control ++ ++#endif ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define CCB_RNG_CTRL ChipcommonB_rng_CTRL ++#endif ++ ++ ++/* the below might be NS specific */ ++#ifdef CONFIG_MACH_CYGNUS //chandra: todo- only timers are mapped correctly ++ #define IPROC_CCA_REG_BASE CCA_CHIPID ++ #define IPROC_CCB_GPIO_REG_BASE (CCB_GP_DATA_IN) ++ #define IPROC_CCB_PWM_REG_BASE (CCB_PWMCTL) ++ #define IPROC_CCB_MDIO_REG_BASE (CCB_MII_MGMT_CTL) ++ #define IPROC_CCB_RNG_REG_BASE (CCB_RNG_CTRL) ++ #define IPROC_CCB_TIM0_REG_BASE (ChipcommonG_tim0_TIM_TIMER1Load) ++ #define IPROC_CCB_TIM1_REG_BASE (ChipcommonG_tim1_TIM_TIMER1Load) ++ #define IPROC_CCB_SRAU_REG_BASE (CCB_SRAB_CMDSTAT) ++ #define IPROC_D1W_REG_BASE (ASIU_D1W_DIN) ++ #define IPROC_D1W_INTR (CHIP_INTR1__ASIU_D1W_INTR) ++ #define IPROC_D1W_CLK_GATE_CTRL (ASIU_TOP_CLK_GATING_CTRL) ++ #define IPROC_D1W_IO_MUX_REG (CRMU_IOMUX_CTRL4) ++ ++ #define IPROC_KEYPAD_INTR (ASIU_INTR_STATUS__asiu_keypad_intr) ++ #define IPROC_KEYPAD_REG_BASE (KEYPAD_TOP_REGS_KPCR) ++ #define IPROC_KEYPAD_TOP_REGS_KPCR (KEYPAD_TOP_REGS_KPCR) ++ #define IPROC_KEYPAD_TOP_REGS_KPIOR (KEYPAD_TOP_REGS_KPIOR) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR0 (KEYPAD_TOP_REGS_KPEMR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR1 (KEYPAD_TOP_REGS_KPEMR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR2 (KEYPAD_TOP_REGS_KPEMR2) ++ #define IPROC_KEYPAD_TOP_REGS_KPEMR3 (KEYPAD_TOP_REGS_KPEMR3) ++ #define IPROC_KEYPAD_TOP_REGS_KPSSR0 (KEYPAD_TOP_REGS_KPSSR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPSSR1 (KEYPAD_TOP_REGS_KPSSR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPIMR0 (KEYPAD_TOP_REGS_KPIMR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPIMR1 (KEYPAD_TOP_REGS_KPIMR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPICR0 (KEYPAD_TOP_REGS_KPICR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPICR1 (KEYPAD_TOP_REGS_KPICR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPISR0 (KEYPAD_TOP_REGS_KPISR0) ++ #define IPROC_KEYPAD_TOP_REGS_KPISR1 (KEYPAD_TOP_REGS_KPISR1) ++ #define IPROC_KEYPAD_TOP_REGS_KPSSR0 (KEYPAD_TOP_REGS_KPSSR0) ++ #define IPROC_CRMU_ASIU_KEYPAD_CLK_DIV (CRMU_ASIU_KEYPAD_CLK_DIV) ++ #define IPROC_IO_MUX_REG_BASE (CRMU_IOMUX_CTRL1) ++ #define IPROC_CLK_GATING_CTRL (ASIU_TOP_CLK_GATING_CTRL) ++ #define IPROC_KEYPAD_CLK_GATE_EN_BIT (ASIU_TOP_CLK_GATING_CTRL__KEYPAD_CLK_GATE_EN) ++ ++ #define IPROC_TSC_REG_BASE (TSCRegCtl1) ++ #define IPROC_TSC_INTR (ASIU_INTR_STATUS__asiu_touch_screen_intr) ++ #define IPROC_ADC_REG_BASE (TSCRegCtl1) ++ #define IPROC_ADC_INTR (ASIU_INTR_STATUS__asiu_touch_screen_intr) ++// #define IPROC_CCB_UART0_REG_BASE (CCB_UART0_RBR_THR_DLL) ++#else ++#define IPROC_CCA_REG_BASE CCA_CHIPID ++#define IPROC_CCB_GPIO_REG_BASE (IPROC_GPIO_CCB_BASE) ++#define IPROC_CCB_PWM_REG_BASE (CCB_PWMCTL) ++#define IPROC_CCB_MDIO_REG_BASE (CCB_MII_MGMT_CTL) ++#define IPROC_CCB_RNG_REG_BASE (CCB_RNG_CTRL) ++#define IPROC_CCB_TIM0_REG_BASE (CCB_TIM0_TIM_TMR1_LOAD) ++#define IPROC_CCB_TIM1_REG_BASE (CCB_TIM1_TIM_TMR1_LOAD) ++#define IPROC_CCB_SRAU_REG_BASE (CCB_SRAB_CMDSTAT) ++#define CCB_UART0_RBR_THR_DLL (0x18037000) ++#define IPROC_CCB_UART0_REG_BASE (CCB_UART0_RBR_THR_DLL) ++#endif /* end of CONFIG_MACH_CYGNUS */ ++ ++/* iProc Profile 7 specific remapping */ ++#if defined(CONFIG_MACH_IPROC_P7) ++ ++#define ChipcommonA_ChipID (ICFG_CHIP_ID_REG) ++#define IPROC_CCA_UART0_REG_BASE (ChipcommonG_UART0_UART_RBR_THR_DLL) ++#define IPROC_CCA_UART1_REG_BASE (ChipcommonG_UART1_UART_RBR_THR_DLL) ++#define IPROC_CCS_RNG_REG_BASE (ChipcommonS_RNG_CTRL) ++ ++#else /* !CONFIG_MACH_IPROC_P7 */ ++ ++#define IPROC_CCA_BASE IPROC_CCA_REG_BASE ++#define IPROC_CCA_CORE_CAP_REG_BASE (IPROC_CCA_BASE + 0x04) ++#define IPROC_CCA_CORE_CTL_REG_BASE (IPROC_CCA_BASE + 0x08) ++ ++#if defined(CONFIG_MACH_CYGNUS) ++ #define IPROC_CCA_UART0_REG_BASE (ChipcommonG_UART0_UART_RBR_THR_DLL) //(IPROC_CCA_BASE + 0x300) //chandra: ++ #define IPROC_CCA_UART1_REG_BASE (ChipcommonG_UART1_UART_RBR_THR_DLL) //(IPROC_CCA_BASE + 0x400) ++ #define IPROC_CCA_UART2_REG_BASE (ChipcommonG_UART2_UART_RBR_THR_DLL) ++ #define IPROC_CCA_UART3_REG_BASE (ChipcommonG_UART3_UART_RBR_THR_DLL) ++ #define IPROC_CCA_UART4_REG_BASE (ChipcommonG_UART4_UART_RBR_THR_DLL) ++#else ++#define IPROC_CCA_UART0_REG_BASE (IPROC_CCA_BASE + 0x300) ++#define IPROC_CCA_UART1_REG_BASE (IPROC_CCA_BASE + 0x400) ++#endif /*end of CYGNUS */ ++#define IPROC_CCA_INTMASK_REG_BASE (IPROC_CCA_BASE + 0x24) ++#define IPROC_CCA_UART_CLK_REG_BASE (IPROC_CCA_BASE + 0xa4) ++ ++#endif /* CONFIG_MACH_IPROC_P7 */ ++ ++#define IPROC_CLK_WR_ACC_REG_BASE (0x19000000) ++#define IPROC_CLK_WR_ACC_REG_OFFSET (0x000) ++#define IPROC_CLK_POLICY_FREQ_REG (0x19000008) ++#define IPROC_CLK_POLICY_FREQ_OFFSET (0x008) ++#define IPROC_CLK_POLICY_CTL_REG (0x1900000C) ++#define IPROC_CLK_POLICY_CTL_OFFSET (0x00C) ++#define IPROC_CLK_POLICY0_MSK_REG (0x19000010) ++#define IPROC_CLK_POLICY0_MSK_OFFSET (0x010) ++#define IPROC_CLK_POLICY1_MSK_REG (0x19000014) ++#define IPROC_CLK_POLICY1_MSK_OFFSET (0x014) ++#define IPROC_CLK_POLICY2_MSK_REG (0x19000018) ++#define IPROC_CLK_POLICY2_MSK_OFFSET (0x018) ++#define IPROC_CLK_POLICY3_MSK_REG (0x1900001C) ++#define IPROC_CLK_POLICY3_MSK_OFFSET (0x01C) ++#define IPROC_CLK_INT_EN_REG (0x19000020) ++#define IPROC_CLK_INT_EN_OFFSET (0x020) ++#define IPROC_CLK_INT_STAT_REG (0x19000024) ++#define IPROC_CLK_INT_STAT_OFFSET (0x024) ++#define IPROC_CLK_LVM_EN_REG (0x19000034) ++#define IPROC_CLK_LVM_EN_OFFSET (0x034) ++#define IPROC_CLK_LVM0_3_REG (0x19000038) ++#define IPROC_CLK_LVM0_3_OFFSET (0x038) ++#define IPROC_CLK_LVM4_7_REG (0x1900003C) ++#define IPROC_CLK_LVM4_7_OFFSET (0x03C) ++#define IPROC_CLK_VLT0_3_REG (0x19000040) ++#define IPROC_CLK_VLT0_3_OFFSET (0x040) ++#define IPROC_CLK_VLT4_7_REG (0x19000044) ++#define IPROC_CLK_VLT4_7_OFFSET (0x044) ++#define IPROC_CLK_BUS_QUIESC_REG (0x19000100) ++#define IPROC_CLK_BUS_QUIESC_OFFSET (0x100) ++#define IPROC_CLK_CORE0_GATE_REG (0x19000200) ++#define IPROC_CLK_CORE0_GATE_OFFSET (0x200) ++#define IPROC_CLK_CORE1_GATE_REG (0x19000204) ++#define IPROC_CLK_CORE1_GATE_OFFSET (0x204) ++#define IPROC_CLK_ARM_SW_GATE_REG (0x19000210) ++#define IPROC_CLK_ARM_SW_GATE_OFFSET (0x210) ++#define IPROC_CLK_ARM_PERIPH_GATE_REG (0x19000300) ++#define IPROC_CLK_ARM_PERIPH_GATE_OFFSET (0x300) ++#define IPROC_CLK_APB0_CLKGATE_REG (0x19000400) ++#define IPROC_CLK_APB0_CLKGATE_OFFSET (0x400) ++#define IPROC_CLK_PL310_DIV_REG (0x19000A00) ++#define IPROC_CLK_PL310_DIV_OFFSET (0xA00) ++#define IPROC_CLK_PL310_TRG_REG (0x19000A04) ++#define IPROC_CLK_PL310_TRG_OFFSET (0xA04) ++#define IPROC_CLK_ARM_SW_DIV_REG (0x19000A08) ++#define IPROC_CLK_ARM_SW_DIV_OFFSET (0xA08) ++#define IPROC_CLK_ARM_SW_TRG_REG (0x19000A0C) ++#define IPROC_CLK_ARM_SW_TRG_OFFSET (0xA0C) ++#define IPROC_CLK_APB_SW_DIV_REG (0x19000A10) ++#define IPROC_CLK_APB_SW_DIV_OFFSET (0xA10) ++#define IPROC_CLK_APB_SW_TRG_REG (0x19000A14) ++#define IPROC_CLK_APB_SW_TRG_OFFSET (0xA14) ++#define IPROC_CLK_PLL_ARMA_REG (0x19000C00) ++#define IPROC_CLK_PLL_ARMA_OFFSET (0xC00) ++#define IPROC_CLK_PLL_ARMB_REG (0x19000C04) ++#define IPROC_CLK_PLL_ARMB_OFFSET (0xC04) ++#define IPROC_CLK_PLL_ARMC_REG (0x19000C08) ++#define IPROC_CLK_PLL_ARMC_OFFSET (0xC08) ++#define IPROC_CLK_PLL_ARMCTL0_REG (0x19000C0C) ++#define IPROC_CLK_PLL_ARMCTL0_OFFSET (0xC0C) ++#define IPROC_CLK_PLL_ARMCTL1_REG (0x19000C10) ++#define IPROC_CLK_PLL_ARMCTL1_OFFSET (0xC10) ++#define IPROC_CLK_PLL_ARMCTL2_REG (0x19000C14) ++#define IPROC_CLK_PLL_ARMCTL2_OFFSET (0xC14) ++#define IPROC_CLK_PLL_ARMCTL3_REG (0x19000C18) ++#define IPROC_CLK_PLL_ARMCTL3_OFFSET (0xC18) ++#define IPROC_CLK_PLL_ARMCTL4_REG (0x19000C1C) ++#define IPROC_CLK_PLL_ARMCTL4_OFFSET (0xC1C) ++#define IPROC_CLK_PLL_ARMCTL5_REG (0x19000C20) ++#define IPROC_CLK_PLL_ARMCTL5_OFFSET (0xC20) ++#define IPROC_CLK_PLL_ARM_OFFSET_REG (0x19000C24) ++#define IPROC_CLK_PLL_ARM_OFFSET_OFFSET (0xC24) ++#define IPROC_CLK_ARM_DIV_REG (0x19000E00) ++#define IPROC_CLK_ARM_DIV_OFFSET (0xE00) ++#define IPROC_CLK_ARM_SEG_TRG_REG (0x19000E04) ++#define IPROC_CLK_ARM_SEG_TRG_OFFSET (0xE04) ++#define IPROC_CLK_ARM_SEG_TRG_OVRD_REG (0x19000E08) ++#define IPROC_CLK_ARM_SEG_TRG_OVRD_OFFSET (0xE08) ++#define IPROC_CLK_PLL_DEBUG_REG (0x19000E10) ++#define IPROC_CLK_PLL_DEBUG_OFFSET (0xE10) ++#define IPROC_CLK_ACTIVITY_MON1_REG (0x19000E20) ++#define IPROC_CLK_ACTIVITY_MON1_OFFSET (0xE20) ++#define IPROC_CLK_ACTIVITY_MON2_REG (0x19000E24) ++#define IPROC_CLK_ACTIVITY_MON2_OFFSET (0xE24) ++#define IPROC_CLK_GATE_DBG_REG (0x19000E40) ++#define IPROC_CLK_GATE_DBG_OFFSET (0xE40) ++#define IPROC_CLK_APB_CLKGATE_DBG1_REG (0x19000E48) ++#define IPROC_CLK_APB_CLKGATE_DBG1_OFFSET (0xE48) ++#define IPROC_CLK_CLKMON_REG (0x19000E64) ++#define IPROC_CLK_CLKMON_OFFSET (0xE64) ++#define IPROC_CLK_KPROC_CCU_PROF_CTL_REG (0x19000E90) ++#define IPROC_CLK_KPROC_CCU_PROF_CTL_OFFSET (0xE90) ++#define IPROC_CLK_KPROC_CCU_PROF_SEL_REG (0x19000E94) ++#define IPROC_CLK_KPROC_CCU_PROF_SEL_OFFSET (0xE94) ++#define IPROC_CLK_KPROC_CCU_PROF_CNT_REG (0x19000E98) ++#define IPROC_CLK_KPROC_CCU_PROF_CNT_OFFSET (0xE98) ++#define IPROC_CLK_KPROC_CCU_PROF_DBG_REG (0x19000E9C) ++#define IPROC_CLK_KPROC_CCU_PROF_DBG_OFFSET (0xE9C) ++#define IPROC_CLK_POLICY_DBG_REG (0x19000EC0) ++#define IPROC_CLK_POLICY_DBG_OFFSET (0xEC0) ++#define IPROC_CLK_TGTMASK_DBG1_REG (0x19000EC4) ++#define IPROC_CLK_TGTMASK_DBG1_OFFSET (0xEC4) ++#define IPROC_RST_WR_ACCESS_REG (0x19000F00) ++#define IPROC_RST_WR_ACCESS_OFFSET (0xF00) ++#define IPROC_RST_SOFT_RSTN_REG (0x19000F04) ++#define IPROC_RST_SOFT_RSTN_OFFSET (0xF04) ++#define IPROC_RST_A9C_SOFT_RSTN_REG (0x19000F08) ++#define IPROC_RST_A9C_SOFT_RSTN_OFFSET (0xF08) ++#define IPROC_RST_A9CORE_SOFT_RSTN_REG (0x19000F08) ++#define IPROC_RST_A9CORE_SOFT_RSTN_OFFSET (0xF08) ++ ++#define PLLARMC_PLLARM_MDIV_SHIFT 0 ++#define PLLARMC_PLLARM_LOAD_EN_MASK (0x00000800) ++#define PLLARMA_PLLARM_NDIV_INT_MASK (0x0003FF00) ++#define PLLARMA_PLLARM_NDIV_INT_SHIFT 8 ++#define PLLARMB_PLLARM_NDIV_FRAC_MASK (0x000FFFFF) ++#define PLLARMB_PLLARM_NDIV_FRAC_SHIFT 0 ++#define ARMCTL5_PLLARM_H_MDIV_MASK (0x000000FF) ++#define ARMCTL5_PLLARM_H_MDIV_SHIFT 0 ++ ++#define IPROC_CLK_CTL_REG (IPROC_CCA_CLK_CTL_REG_BASE + 0x000) ++#define IPROC_CCA_CLK_HW_REQ_OFF 0x00000020 ++ ++#define IPROC_DDRC_REG_BASE (DDR_DENALI_CTL_00) //(0x18010000) ++#define IPROC_DMAC_REG_BASE (DMAC_P1330_NON_DS) //(0x1802C000) ++#define IPROC_PCIE_AXIB0_REG_BASE (PAXB_0_PCIE_CTL) //(0x18012000) ++#define IPROC_PCIE_AXIB1_REG_BASE (PAXB_1_PCIE_CTL) //(0x18013000) ++#define IPROC_PCIE_AXIB2_REG_BASE (PAXB_2_PCIE_CTL) //(0x18014000) ++ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_SDIO3_REG_BASE (SDIO_EMMC_SDXC_SYSADDR) //(0x18020000) ++#define IPROC_SDIO_IDM_RESET_CONTROL (0x16800) ++#define IPROC_SDIO_IRQ (177) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT (0x18116408) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE (22) ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_SDIO3_REG_BASE (SDIO_eMMCSDXC_SYSADDR) ++#define IPROC_SDIO_IDM_RESET_CONTROL (0x17800) ++#define IPROC_SDIO_IRQ (177) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT (SDIO_IDM_IO_CONTROL_DIRECT) ++#define IPROC_SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE (SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE) ++ ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_USB20_REG_BASE (0x18021000) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_USB20_REG_BASE (0x1802A000) ++#define IPROC_UDC_IRQ (238) ++#endif ++#define IPROC_USB30_REG_BASE (0x18023000) ++//#define IPROC_USB30_REG_BASE (0x18022000) ++#define IPROC_USB20_PHY_REG_BASE (0x18023000) /* ??*/ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_USB2D_REG_BASE USB2D_ENDPNT_IN_CTRL_0 ++#define IPROC_USB2D_REG_SIZE (0x2000) /* 8KB */ ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_NUM_GMACS 4 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCTL) //(0x18024000) ++#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCTL) //(0x18025000) ++#define IPROC_GMAC2_REG_BASE (GMAC2_DEVCTL) //(0x18026000) ++#define IPROC_GMAC3_REG_BASE (GMAC3_DEVCTL) //(0x18027000) ++#define IPROC_GMAC0_INT 179 ++#define IPROC_GMAC1_INT 180 ++#define IPROC_GMAC2_INT 181 ++#define IPROC_GMAC3_INT 182 ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_NUM_GMACS 2 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000) ++#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCONTROL) //(0x18023000) ++#define IPROC_GMAC2_REG_BASE (0) // n/a ++#define IPROC_GMAC3_REG_BASE (0) // n/a ++#define IPROC_GMAC0_INT 234 ++#define IPROC_GMAC1_INT 235 ++#define IPROC_GMAC2_INT 0 // n/a ++#define IPROC_GMAC3_INT 0 // n/a ++#elif defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_CYGNUS) ++#define IPROC_NUM_GMACS 1 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000) ++#define IPROC_GMAC1_REG_BASE (0) // n/a ++#define IPROC_GMAC2_REG_BASE (0) // n/a ++#define IPROC_GMAC3_REG_BASE (0) // n/a ++#define IPROC_GMAC0_INT 234 ++#define IPROC_GMAC1_INT 0 // n/a ++#define IPROC_GMAC2_INT 0 // n/a ++#define IPROC_GMAC3_INT 0 // n/a ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_NUM_GMACS 4 ++#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000) ++#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCONTROL) //(0x18023000) ++#define IPROC_GMAC2_REG_BASE (FA_GMAC0_DEVCONTROL) //(0x18024000) ++#define IPROC_GMAC3_REG_BASE (FA_GMAC1_DEVCONTROL) //(0x18025000) ++#define IPROC_GMAC0_INT 179 ++#define IPROC_GMAC1_INT 180 ++#define IPROC_GMAC2_INT 181 ++#define IPROC_GMAC3_INT 182 ++#endif ++ ++#define IPROC_CTF_REG_BASE (0x18027C00) ++ ++#define IPROC_I2S_REG_BASE (0x1802A000) ++#define IPROC_CCU_PROF_CTL_REG_BASE (0x19000E90) ++ ++/* IDM / CRU / DMU */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_CRU_REG_BASE (0x1800b000) ++#define IPROC_DMU_REG_BASE (0x1800c000) ++#define IPROC_IDM_REG_BASE (0x18100000) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) \ ++ || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || defined (CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_CRU_REG_BASE CRU_control ++#define IPROC_DMU_REG_BASE DMU_PCU_IPROC_CONTROL ++#define IPROC_IDM_REG_BASE (IHOST_M0_IO_CONTROL_DIRECT - 0x408) ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_CRU_REG_BASE CRU_control ++#define IPROC_DMU_REG_BASE PCU_MDIO_MGT ++ ++#define IPROC_IDM_REG_BASE (IHOST_M0_IO_CONTROL_DIRECT - 0x408) ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IPROC_CRU_REG_BASE (CRU_control) ++#define IPROC_DMU_REG_BASE DMU_S0_IDM_IDM_RESET_CONTROL ++#endif ++#ifndef CONFIG_MACH_GH ++#define DMU_PCU_IPROC_CONTROL 0x1803f000 ++#endif ++ ++/* Straps */ ++#if defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++#define IPROC_DMU_STRAPS_OFFSET (0x2a0) ++#define IPROC_STRAP_BOOT_DEV_SHIFT (16) ++#define IPROC_STRAP_NAND_TYPE_SHIFT (12) ++#define IPROC_STRAP_NAND_PAGE_SHIFT (10) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) \ ++ || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_DMU_STRAPS_OFFSET DMU_PCU_IPROC_STRAPS_CAPTURED_BASE ++#define IPROC_STRAP_BOOT_DEV_SHIFT DMU_PCU_IPROC_STRAPS_CAPTURED__strap_boot_dev_R ++#define IPROC_STRAP_NAND_TYPE_SHIFT DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_type_R ++#define IPROC_STRAP_NAND_PAGE_SHIFT DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_page_R ++#endif ++#define IPROC_STRAP_BOOT_DEV_QSPI (0) ++#define IPROC_STRAP_BOOT_DEV_NAND (1) ++#define IPROC_STRAP_BOOT_DEV_PNOR (4) ++ ++/* NAND and QSPI */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_IDM_NAND_REG_BASE (0x1811a408) ++#define IPROC_NAND_IRQ_START (100) ++#define IPROC_IDM_QSPI_REG_BASE (0x1811b408) ++#define IPROC_QSPI_IRQ_START (104) ++#define IPROC_QSPI_IRQ_END (109) ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_IDM_NAND_REG_BASE NAND_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_NAND_IRQ_START (100) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (104) ++#define IPROC_QSPI_IRQ_END (109) ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_IDM_NAND_REG_BASE NAND_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_NAND_IRQ_START (106) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (110) ++#define IPROC_QSPI_IRQ_END (116) ++#elif defined(CONFIG_MACH_CYGNUS) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (IPROC_INTERRUPTS__chipcommonG_spi0_intr) ++#define IPROC_QSPI_IRQ_END (IPROC_INTERRUPTS__chipcommonG_spi5_intr) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_IDM_NAND_REG_BASE NAND_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_NAND_IRQ_START (101) ++#define IPROC_IDM_QSPI_REG_BASE QSPI_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_QSPI_IRQ_START (102) ++#define IPROC_QSPI_IRQ_END (102) ++#endif ++ ++/* PNOR */ ++#ifdef CONFIG_MACH_IPROC_P7 ++#define S29GL_FLASH_SIZE 0x04000000 ++#define S29GL_FLASH_PHYS 0xe8000000 ++#define PNOR_NAND_SEL_REG ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL ++#define PNOR_NAND_SEL_REG_OVERRIDE ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel_sw_ovwr ++#define PNOR_NAND_SEL_REG_PNOR_SEL ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel ++#elif defined(CONFIG_MACH_HR2) ++#define S29GL_FLASH_SIZE 0x04000000 ++#define S29GL_FLASH_PHYS 0x20000000 ++#define PNOR_NAND_SEL_REG 0x1803fc3c ++#define PNOR_NAND_SEL_REG_OVERRIDE 2 ++#define PNOR_NAND_SEL_REG_PNOR_SEL 3 ++#endif ++ ++/* ARM9 Private memory region */ ++#if defined(CONFIG_MACH_CYGNUS) ++#define IPROC_PERIPH_BASE (IHOST_SCU_CONTROL)//chandra: ++#else ++#define IPROC_PERIPH_BASE (0x19020000) //(IHOST_A9MP_scu_CONTROL) ++#endif ++#define IPROC_PERIPH_SCU_REG_BASE (IPROC_PERIPH_BASE) ++#define IPROC_PERIPH_INT_CTRL_REG_BASE (IPROC_PERIPH_BASE + 0x100) ++#define IPROC_PERIPH_GLB_TIM_REG_BASE (IPROC_PERIPH_BASE + 0x200) ++#define IPROC_PERIPH_PVT_TIM_REG_BASE (IPROC_PERIPH_BASE + 0x600) ++#define IPROC_PERIPH_PVT_WDT_REG_BASE (IPROC_PERIPH_BASE + 0x620) ++#define IPROC_PERIPH_INT_DISTR_REG_BASE (IPROC_PERIPH_BASE + 0x1000) ++#define IPROC_L2CC_REG_BASE (IPROC_PERIPH_BASE + 0x2000) ++#define IPROC_GTIM_GLB_LO (0x00000000) ++#define IPROC_GTIM_GLB_HI (0x00000004) ++#define IPROC_GTIM_GLB_CTL (0x00000008) ++#define IPROC_GTIM_GLB_STS (0x0000000C) ++#define IPROC_GTIM_GLB_CMP_LO (0x00000010) ++#define IPROC_GTIM_GLB_CMP_HI (0x00000014) ++#define IPROC_GTIM_GLB_INCR (0x00000018) ++ ++/* Structures and bit definitions */ ++/* SCU Control register */ ++#define IPROC_SCU_CTRL_SCU_EN (0x00000001) ++#define IPROC_SCU_CTRL_ADRFLT_EN (0x00000002) ++#define IPROC_SCU_CTRL_PARITY_EN (0x00000004) ++#define IPROC_SCU_CTRL_SPEC_LNFL_EN (0x00000008) ++#define IPROC_SCU_CTRL_FRC2P0_EN (0x00000010) ++#define IPROC_SCU_CTRL_SCU_STNDBY_EN (0x00000020) ++#define IPROC_SCU_CTRL_IC_STNDBY_EN (0x00000040) ++ ++/* ARM A9 Private Timer */ ++#define IPROC_PVT_TIM_CTRL_TIM_EN (0x00000001) ++#define IPROC_PVT_TIM_CTRL_AUTO_RELD (0x00000002) ++#define IPROC_PVT_TIM_CTRL_INT_EN (0x00000004) ++#define IPROC_PVT_TIM_CTRL_PRESC_MASK (0x0000FF00) ++#define IPROC_PVT_TIM_INT_STATUS_SET (0x00000001) ++ ++/* Global timer */ ++#define IPROC_GLB_TIM_CTRL_STCS_EN (0x00000000) ++#define IPROC_GLB_TIM_CTRL_TIM_EN (0x00000001) ++#define IPROC_GLB_TIM_CTRL_COMP_EN (0x00000002) ++#define IPROC_GLB_TIM_CTRL_INT_EN (0x00000004) ++#define IPROC_GLB_TIM_CTRL_AUTO_INC (0x00000008) ++#define IPROC_GLB_TIM_CTRL_STCM_SET (0x0000000C) ++#define IPROC_GLB_TIM_CTRL_PRESC_MASK (0x0000FF00) ++#define IPROC_GLB_TIM_INT_STATUS_SET (0x00000001) ++ ++#define GLBTMR_GLOB_STATUS_EVENT_G_SHIFT (0x00000000) ++#define GLBTMR_GLOB_CTRL_TIMER_EN_G_SHIFT (0x00000000) ++ ++/* GIC(Generic Interrupt controller) CPU interface registers */ ++#if defined(CONFIG_MACH_CYGNUS) ++ #define IPROC_GICCPU_CTL_REG_BASE (IHOST_GICCPU_CONTROL) ++#else ++ #define IPROC_GICCPU_CTL_REG_BASE (0x19020100) ++#endif ++#define IPROC_GICCPU_PRI_MASK_OFFSET (0x04) ++#define IPROC_GICCPU_BIN_PT_OFFSET (0x08) ++#define IPROC_GICCPU_INT_ACK_OFFSET (0x0C) ++#define IPROC_GICCPU_EOI_OFFSET (0x10) ++#define IPROC_GICCPU_RUN_PRI_OFFSET (0x14) ++#define IPROC_GICCPU_HI_PEND_OFFSET (0x18) ++#define IPROC_GICCPU_ALIAS_BIN_PT_NS_OFFSET (0x1C) ++#define IPROC_GICCPU_INT_GFC_OFFSET (0x40) ++#define IPROC_GICCPU_INT_FIQ_SET_OFFSET (0x44) ++#define IPROC_GICCPU_INTEG_MATCH_OFFSET (0x50) ++#define IPROC_GICCPU_INTEG_ENABLE_OFFSET (0x54) ++#define IPROC_GICCPU_CPU_IDENT_OFFSET (0xFC) ++ ++#define IPROC_GIC_CI_CTRL_EN (0x00000001) ++#define IPROC_GIC_CI_PMR_PRIO_MASK (0x000000FF) ++#define IPROC_GIC_CI_BPR_BP_MASK (0x00000003) ++#define IPROC_GIC_CI_IAR_INTID_MASK (0x000003FF) ++#define IPROC_GIC_CI_IAR_CPUID_MASK (0x00001C00) ++#define IPROC_GIC_CI_IAR_CPUID_OFFSET (10) ++#define IPROC_GIC_CI_EOIR_INTID_MASK (0x000003FF) ++#define IPROC_GIC_CI_EOIR_CPUID_MASK (0x00001C00) ++#define IPROC_GIC_CI_EOIR_CPUID_OFFSET (10) ++#define IPROC_GIC_CI_RPR_PRIO_MASK (0x000000FF) ++#define IPROC_GIC_CI_HPIR_PENDID_MASK (0x000003FF) ++#define IPROC_GIC_CI_HPIR_CPUID_MASK (0x00001C00) ++#define IPROC_GIC_CI_HPIR_CPUID_OFFSET (10) ++#define IPROC_GIC_CI_ABPR_BP_MASK (0x00000003) ++ ++#define IPROC_GIC_DIST_CTRL_S_EN_S (0x00000001) ++#define IPROC_GIC_DIST_CTRL_S_EN_NS (0x00000002) ++#define IPROC_GIC_DIST_CTRL_NS_EN_NS (0x00000001) ++ ++#define IPROC_GIC_DIST_ISR_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ISER_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ICER_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ISPR_BIT_SIZE (1) ++#define IPROC_GIC_DIST_ISPR_SECURE (1) ++#define IPROC_GIC_DIST_ISPR_NON_SECURE (0) ++#define IPROC_GIC_DIST_ICPR_BIT_SIZE (1) ++#define IPROC_GIC_DIST_IPR_BIT_SIZE (8) ++#define IPROC_GIC_DIST_IPTR_BIT_SIZE (8) ++#define IPROC_GIC_DIST_IPTR_CPU0 (0x01) ++#define IPROC_GIC_DIST_IPTR_CPU1 (0x02) ++#define IPROC_GIC_DIST_SGIR_ID_MASK (0xF) ++#define IPROC_GIC_DIST_SGIR_TR_LIST_MASK (0x00FF0000) ++#define IPROC_GIC_DIST_SGIR_TR_LIST_BOFFSET (16) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_MASK (0x03000000) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_BOFFSET (24) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_FW_LIST (0) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_FW_ALL_EX_ME (0x01) ++#define IPROC_GIC_DIST_SGIR_TR_FILT_FW_ME_ONLY (0x02) ++ ++#define IPROC_INTR_LEVEL_SENSITIVE (1) ++#define IPROC_INTR_EDGE_TRIGGERED (2) ++ ++/* GPIO Driver */ ++#if defined(CONFIG_IPROC_GPIO) || defined(CONFIG_IPROC_GPIO_MODULE) || \ ++ defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++ ++/* Chipcommon A GPIO */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_CCA_INT_STS (CCA_INT_STS_BASE) ++#define IPROC_CCA_INT_MASK (CCA_INT_MASK_BASE) ++#define IPROC_GPIO_CCA_BASE (CCA_GPIO_INPUT) ++#define IPROC_GPIO_CCA_DIN (CCA_GPIO_INPUT_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_DOUT (CCA_GPIO_OUT_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_EN (CCA_GPIO_OUT_EN_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL (CCA_GPIO_INT_POLARITY_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL_MASK (CCA_GPIOINT_MASK_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT (CCA_GPIO_EVT_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT_MASK (CCA_GPIO_EVTINT_MASK_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_WATCHDOG_COUNTER (CCA_WDOG_CTR_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_INT_EDGE (CCA_GPIO_EVT_INT_POLARITY_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_TIMER_VAL (CCA_GPIO_TMR_VAL_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_TIMEOUT_MASK (CCA_GPIO_TMR_OUT_MASK_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_CLK_DIV (CCA_CLK_DIV_BASE - CCA_GPIO_INPUT_BASE) ++#define IPROC_GPIO_CCA_DEBUG (CCA_GPIODBG_SEL_BASE - CCA_GPIO_INPUT_BASE) ++ ++#define IPROC_DMU_BASE (0x1800c000) ++ ++#define IPROC_GPIO_CCA_PULL_UP (0x01dc) ++#define IPROC_GPIO_CCA_PULL_DOWN (0x01e0) ++#define IPROC_GPIO_CCA_CTRL0 (0x01c0) ++ ++#else ++/* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_NSP, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_CCA_INT_STS (ChipcommonA_IntStatus_BASE) ++#define IPROC_CCA_INT_MASK (ChipcommonA_IntMask_BASE) ++#define IPROC_GPIO_CCA_BASE (ChipcommonA_GPIOInput) ++#define IPROC_GPIO_CCA_DIN (ChipcommonA_GPIOInput_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_DOUT (ChipcommonA_GPIOOut_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_EN (ChipcommonA_GPIOOutEn_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL (ChipcommonA_GPIOIntPolarity_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_LEVEL_MASK (ChipcommonA_GPIOIntMask_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT (ChipcommonA_GPIOEvent_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_EVENT_MASK (ChipcommonA_GPIOEventIntMask_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_WATCHDOG_COUNTER (ChipcommonA_WatchdogCounter_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_INT_EDGE (ChipcommonA_GPIOEventIntPolarity_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_TIMER_VAL (ChipcommonA_GPIOTimerVal_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_TIMEOUT_MASK (ChipcommonA_GPIOTimerOutMask_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_CLK_DIV (ChipcommonA_ClkDiv_BASE - ChipcommonA_GPIOInput_BASE) ++#define IPROC_GPIO_CCA_DEBUG (ChipcommonA_GPIODebugSel_BASE - ChipcommonA_GPIOInput_BASE) ++#endif ++ ++#if defined(CONFIG_MACH_NSP) ++#define IPROC_DMU_BASE (DMAC_pl330_DS) ++#define IPROC_GPIO_CCA_PULL_UP (CRU_GPIO_CONTROL7_BASE) ++#define IPROC_GPIO_CCA_PULL_DOWN (CRU_GPIO_CONTROL8_BASE) ++#define IPROC_GPIO_CCA_CTRL0 (CRU_GPIO_CONTROL0_BASE) ++#endif ++ ++/* Chipcommon B GPIO */ ++#if defined(CONFIG_MACH_NS) ++#define IPROC_GPIO_CCB_BASE (CCB_GP_DATA_IN) ++#define IPROC_GPIO_CCB_DIN (CCB_GP_DATA_IN_BASE) ++#define IPROC_GPIO_CCB_DOUT (CCB_GP_DATA_OUT_BASE) ++#define IPROC_GPIO_CCB_EN (CCB_GP_OUT_EN_BASE) ++#define IPROC_GPIO_CCB_INT_TYPE (CCB_GP_INT_TYPE_BASE) ++#define IPROC_GPIO_CCB_INT_DE (CCB_GP_INT_DE_BASE) ++#define IPROC_GPIO_CCB_INT_EDGE (CCB_GP_INT_EDGE_BASE) ++#define IPROC_GPIO_CCB_INT_MASK (CCB_GP_INT_MSK_BASE) ++#define IPROC_GPIO_CCB_INT_STAT (CCB_GP_INT_STAT_BASE) ++#define IPROC_GPIO_CCB_INT_MSTAT (CCB_GP_INT_MSTAT_BASE) ++#define IPROC_GPIO_CCB_INT_CLR (CCB_GP_INT_CLR_BASE) ++#define IPROC_GPIO_CCB_AUX_SEL (CCB_GP_AUX_SEL_BASE) ++#define IPROC_GPIO_CCB_INIT_VAL (CCB_GP_INIT_VAL_BASE) ++#define IPROC_GPIO_CCB_PAD_RES (CCB_GP_PAD_RES_BASE) ++#define IPROC_GPIO_CCB_RES_EN (CCB_GP_RES_EN_BASE) ++#define IPROC_GPIO_CCB_TST_IN (CCB_GP_TEST_INPUT_BASE) ++#define IPROC_GPIO_CCB_TST_OUT (CCB_GP_TEST_OUTPUT_BASE) ++#define IPROC_GPIO_CCB_TST_EN (CCB_GP_TEST_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_EN (CCB_GP_PRB_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_OE (CCB_GP_PRB_OE_BASE) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG_BASE (ChipcommonG_GP_DATA_IN) ++#define IPROC_GPIO_CCB_BASE (ChipcommonG_GP_DATA_IN) ++#define IPROC_GPIO_CCB_DIN (ChipcommonG_GP_DATA_IN_BASE) ++#define IPROC_GPIO_CCB_DOUT (ChipcommonG_GP_DATA_OUT_BASE) ++#define IPROC_GPIO_CCB_EN (ChipcommonG_GP_OUT_EN_BASE) ++#define IPROC_GPIO_CCB_INT_TYPE (ChipcommonG_GP_INT_TYPE_BASE) ++#define IPROC_GPIO_CCB_INT_DE (ChipcommonG_GP_INT_DE_BASE) ++#define IPROC_GPIO_CCB_INT_EDGE (ChipcommonG_GP_INT_EDGE_BASE) ++#define IPROC_GPIO_CCB_INT_MASK (ChipcommonG_GP_INT_MSK_BASE) ++#define IPROC_GPIO_CCB_INT_STAT (ChipcommonG_GP_INT_STAT_BASE) ++#define IPROC_GPIO_CCB_INT_MSTAT (ChipcommonG_GP_INT_MSTAT_BASE) ++#define IPROC_GPIO_CCB_INT_CLR (ChipcommonG_GP_INT_CLR_BASE) ++#define IPROC_GPIO_CCB_AUX_SEL (ChipcommonG_GP_AUX_SEL_BASE) ++#define IPROC_GPIO_CCB_INIT_VAL (ChipcommonG_GP_INIT_VAL_BASE) ++#define IPROC_GPIO_CCB_PAD_RES (ChipcommonG_GP_PAD_RES_BASE) ++#define IPROC_GPIO_CCB_RES_EN (ChipcommonG_GP_RES_EN_BASE) ++#define IPROC_GPIO_CCB_TST_IN (ChipcommonG_GP_TEST_INPUT_BASE) ++#define IPROC_GPIO_CCB_TST_OUT (ChipcommonG_GP_TEST_OUTPUT_BASE) ++#define IPROC_GPIO_CCB_TST_EN (ChipcommonG_GP_TEST_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_EN (ChipcommonG_GP_PRB_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_OE (ChipcommonG_GP_PRB_OE_BASE) ++#else ++/* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_NSP, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_GPIO_CCB_BASE (ChipcommonB_GP_DATA_IN) ++#define IPROC_GPIO_CCB_DIN (ChipcommonB_GP_DATA_IN_BASE) ++#define IPROC_GPIO_CCB_DOUT (ChipcommonB_GP_DATA_OUT_BASE) ++#define IPROC_GPIO_CCB_EN (ChipcommonB_GP_OUT_EN_BASE) ++#define IPROC_GPIO_CCB_INT_TYPE (ChipcommonB_GP_INT_TYPE_BASE) ++#define IPROC_GPIO_CCB_INT_DE (ChipcommonB_GP_INT_DE_BASE) ++#define IPROC_GPIO_CCB_INT_EDGE (ChipcommonB_GP_INT_EDGE_BASE) ++#define IPROC_GPIO_CCB_INT_MASK (ChipcommonB_GP_INT_MSK_BASE) ++#define IPROC_GPIO_CCB_INT_STAT (ChipcommonB_GP_INT_STAT_BASE) ++#define IPROC_GPIO_CCB_INT_MSTAT (ChipcommonB_GP_INT_MSTAT_BASE) ++#define IPROC_GPIO_CCB_INT_CLR (ChipcommonB_GP_INT_CLR_BASE) ++#define IPROC_GPIO_CCB_AUX_SEL (ChipcommonB_GP_AUX_SEL_BASE) ++#define IPROC_GPIO_CCB_INIT_VAL (ChipcommonB_GP_INIT_VAL_BASE) ++#define IPROC_GPIO_CCB_PAD_RES (ChipcommonB_GP_PAD_RES_BASE) ++#define IPROC_GPIO_CCB_RES_EN (ChipcommonB_GP_RES_EN_BASE) ++#define IPROC_GPIO_CCB_TST_IN (ChipcommonB_GP_TEST_INPUT_BASE) ++#define IPROC_GPIO_CCB_TST_OUT (ChipcommonB_GP_TEST_OUTPUT_BASE) ++#define IPROC_GPIO_CCB_TST_EN (ChipcommonB_GP_TEST_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_EN (ChipcommonB_GP_PRB_ENABLE_BASE) ++#define IPROC_GPIO_CCB_PRB_OE (ChipcommonB_GP_PRB_OE_BASE) ++#endif ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define IPROC_GPIO_CCA_INT (117) ++#define IPROC_GPIO_CCB_INT (119) ++#elif defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG_INT (116) ++#else ++/* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_GPIO_CCA_INT (123) ++#define IPROC_GPIO_CCB_INT (125) ++#endif ++#endif /* CONFIG_IPROC_GPIO || CONFIG_IPROC_GPIO_MODULE */ ++ ++/* PWM Driver */ ++#if defined(CONFIG_IPROC_PWM) || defined(CONFIG_IPROC_PWM_MODULE) ++#if defined(CONFIG_MACH_NS) ++#define IPROC_CCB_PWM_CTL (CCB_PWM_CTL) ++#define IPROC_CCB_PWM_CTL_BASE (CCB_PWM_CTL_BASE) ++#define IPROC_CCB_PWM_PRESCALE_BASE (CCB_PWM_PRESCALE_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT0_BASE (CCB_PWM_PERIOD_COUNT0_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT1_BASE (CCB_PWM_PERIOD_COUNT1_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT2_BASE (CCB_PWM_PERIOD_COUNT2_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT3_BASE (CCB_PWM_PERIOD_COUNT3_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE (CCB_PWM_DUTY_HI_COUNT0_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE (CCB_PWM_DUTY_HI_COUNT1_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE (CCB_PWM_DUTY_HI_COUNT2_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE (CCB_PWM_DUTY_HI_COUNT3_BASE) ++#endif /* CONFIG_MACH_NS */ ++ ++#if defined(CONFIG_MACH_NSP) ++#define IPROC_CCB_PWM_CTL (ChipcommonB_PWMCTL) ++#define IPROC_CCB_PWM_CTL_BASE (ChipcommonB_PWMCTL_BASE) ++#define IPROC_CCB_PWM_PRESCALE_BASE (ChipcommonB_PWM_PRESCALE_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT0_BASE (ChipcommonB_PWM_PERIOD_COUNT0_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT1_BASE (ChipcommonB_PWM_PERIOD_COUNT1_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT2_BASE (ChipcommonB_PWM_PERIOD_COUNT2_BASE) ++#define IPROC_CCB_PWM_PERIOD_COUNT3_BASE (ChipcommonB_PWM_PERIOD_COUNT3_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE (ChipcommonB_PWM_DUTYHI_COUNT0_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE (ChipcommonB_PWM_DUTYHI_COUNT1_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE (ChipcommonB_PWM_DUTYHI_COUNT2_BASE) ++#define IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE (ChipcommonB_PWM_DUTYHI_COUNT3_BASE) ++#endif /* CONFIG_MACH_NSP */ ++ ++#endif /* CONFIG_IPROC_PWM */ ++ ++/* ChipCommonB Timer */ ++#if defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_CCB_TIMER0_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim0_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER1_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim1_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER2_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim2_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER3_REGS_VA HW_IO_PHYS_TO_VIRT(ChipcommonG_tim3_TIM_TIMER1Load) ++#define IPROC_CCB_TIMER_INT_START (119) ++#define IPROC_CCB_TIMER_INT_COUNT (4) ++#elif (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define IPROC_CCB_TIMER0_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x00) ++#define IPROC_CCB_TIMER1_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x20) ++#define IPROC_CCB_TIMER2_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x00) ++#define IPROC_CCB_TIMER3_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x20) ++#define IPROC_CCB_TIMER_INT_START (122) ++#define IPROC_CCB_TIMER_INT_COUNT (4) ++#else /* CONFIG_MACH_HX4, CONFIG_MACH_HR2, CONFIG_MACH_KT2, CONFIG_MACH_DNI_3448P */ ++#define IPROC_CCB_TIMER0_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x00) ++#define IPROC_CCB_TIMER1_REGS_VA (IPROC_CCB_TIM0_REG_VA + 0x20) ++#define IPROC_CCB_TIMER2_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x00) ++#define IPROC_CCB_TIMER3_REGS_VA (IPROC_CCB_TIM1_REG_VA + 0x20) ++#define IPROC_CCB_TIMER_INT_START (129) ++#define IPROC_CCB_TIMER_INT_COUNT (4) ++#endif ++ ++/* ChipCommonB Watchdog */ ++/* ++ * CCB WDT could be set only when CONFIG_MACH_HR2, CONFIG_MACH_HX4, ++ * CONFIG_MACH_DNI_3448P or CONFIG_MACH_NSP is set ++ */ ++#define IPROC_CCB_WDT_WDOGLOAD ChipcommonB_WDT_WDOGLOAD ++#define IPROC_CCB_WDT_REG_BASE IPROC_CCB_WDT_WDOGLOAD ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_CCB_WDT_BOOTSTATUS DMU_PCU_CRU_RESET_REASON ++#define IPROC_CCB_WDT_BOOTSTATUS_BIT DMU_PCU_CRU_RESET_REASON__watchdog_reset ++#elif defined(CONFIG_MACH_NSP) ++#define IPROC_CCB_WDT_BOOTSTATUS CRU_WATCHDOG_PCIE_RESET_STATUS ++#define IPROC_CCB_WDT_BOOTSTATUS_BIT CRU_WATCHDOG_PCIE_RESET_STATUS__CCB_WATCHDOG_RESET_EVENT ++#endif ++ ++/* ChipCommonG Watchdog */ ++#if defined(CONFIG_IPROC_CCG_WDT) || defined(CONFIG_IPROC_CCG_WDT_MODULE) ++#define IPROC_CCG_WDT_REG_BASE ChipcommonG_WDT_WDOGLOAD ++#define IPROC_CCG_WDT_BOOTSTATUS DMU_PCU_CRU_RESET_REASON ++#define IPROC_CCG_WDT_BOOTSTATUS_BIT DMU_PCU_CRU_RESET_REASON__watchdog_reset ++#endif /* CONFIG_IPROC_CCG_WDT || CONFIG_IPROC_CCG_WDT_MODULE */ ++ ++#if defined(CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++#define IPROC_SP805_WDT_REG_BASE IPROC_CCB_WDT_REG_BASE ++#define IPROC_SP805_WDT_BOOTSTATUS IPROC_CCB_WDT_BOOTSTATUS ++#define IPROC_SP805_WDT_BOOTSTATUS_BIT IPROC_CCB_WDT_BOOTSTATUS_BIT ++#endif /* CONFIG_IPROC_SP805_WDT */ ++ ++#endif /*__IPROC_REGS_H */ +diff --git a/arch/arm/mach-iproc/include/mach/nand_iproc.h b/arch/arm/mach-iproc/include/mach/nand_iproc.h +new file mode 100644 +index 0000000..9c4d4fc diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch new file mode 100644 index 00000000..90d7b97d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_nand_iproc.h.patch @@ -0,0 +1,43 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/nand_iproc.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _NAND_IPROC_H_ ++#define _NAND_IPROC_H_ ++ ++/* ++ * Registers used directly in driver ++ */ ++ ++/* ++ * Shared Structure ++ */ ++struct mtd_partition; ++struct brcmnand_platform_data { ++ int chip_select; ++ int strap_boot; ++ int strap_type; ++ int strap_page_size; ++ int nr_parts; ++ struct mtd_partition *parts; ++}; ++ ++#endif /* _NAND_IPROC_H_ */ +diff --git a/arch/arm/mach-iproc/include/mach/qspi_iproc.h b/arch/arm/mach-iproc/include/mach/qspi_iproc.h +new file mode 100644 +index 0000000..14fcac8 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch new file mode 100644 index 00000000..d52845fd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/qspi_iproc.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _QSPI_IPROC_H_ ++#define _QSPI_IPROC_H_ ++ ++/* ++ * Shared Structure ++ */ ++struct brcmspi_platform_data { ++ int flash_cs; ++}; ++ ++#endif /* _SPI_IPROC_H_ */ +diff --git a/arch/arm/mach-iproc/include/mach/reg_utils.h b/arch/arm/mach-iproc/include/mach/reg_utils.h +new file mode 100644 +index 0000000..6cc36bf diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch new file mode 100644 index 00000000..bf6dea5c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_reg_utils.h.patch @@ -0,0 +1,166 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/reg_utils.h +@@ -0,0 +1,160 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef REG_UTILS ++#define REG_UTILS ++ ++/* ---- Include Files ---------------------------------------------------- */ ++ ++#include ++ ++/* ---- Public Constants and Types --------------------------------------- */ ++ ++#define __REG32(x) (*((volatile uint32_t *)(x))) ++#define __REG16(x) (*((volatile uint16_t *)(x))) ++#define __REG8(x) (*((volatile uint8_t *) (x))) ++ ++/* ---- Public Variable Externs ------------------------------------------ */ ++/* ---- Public Function Prototypes --------------------------------------- */ ++ ++/****************************************************************************/ ++/* ++ * 32-bit register access functions ++ */ ++/****************************************************************************/ ++ ++static inline void ++reg32_clear_bits(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg &= ~(value); ++} ++ ++static inline void ++reg32_set_bits(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg |= value; ++} ++ ++static inline void ++reg32_toggle_bits(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg ^= value; ++} ++ ++static inline void ++reg32_write_masked(volatile uint32_t *reg, uint32_t mask, ++ uint32_t value) ++{ ++ *reg = (*reg & (~mask)) | (value & mask); ++} ++ ++static inline void ++reg32_write(volatile uint32_t *reg, uint32_t value) ++{ ++ *reg = value; ++} ++ ++static inline uint32_t ++reg32_read(volatile uint32_t *reg) ++{ ++ return *reg; ++} ++ ++/****************************************************************************/ ++/* ++ * 16-bit register access functions ++ */ ++/****************************************************************************/ ++ ++static inline void ++reg16_clear_bits(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg &= ~(value); ++} ++ ++static inline void ++reg16_set_bits(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg |= value; ++} ++ ++static inline void ++reg16_toggle_bits(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg ^= value; ++} ++ ++static inline void ++reg16_write_masked(volatile uint16_t *reg, uint16_t mask, uint16_t value) ++{ ++ *reg = (*reg & (~mask)) | (value & mask); ++} ++ ++static inline void ++reg16_write(volatile uint16_t *reg, uint16_t value) ++{ ++ *reg = value; ++} ++ ++static inline uint16_t ++reg16_read(volatile uint16_t *reg) ++{ ++ return *reg; ++} ++ ++/****************************************************************************/ ++/* ++ * 8-bit register access functions ++ */ ++/****************************************************************************/ ++ ++static inline void ++reg8_clear_bits(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg &= ~(value); ++} ++ ++static inline void ++reg8_set_bits(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg |= value; ++} ++ ++static inline void ++reg8_toggle_bits(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg ^= value; ++} ++ ++static inline void ++reg8_write_masked(volatile uint8_t *reg, uint8_t mask, uint8_t value) ++{ ++ *reg = (*reg & (~mask)) | (value & mask); ++} ++ ++static inline void ++reg8_write(volatile uint8_t *reg, uint8_t value) ++{ ++ *reg = value; ++} ++ ++static inline uint8_t ++reg8_read(volatile uint8_t *reg) ++{ ++ return *reg; ++} ++#endif /* REG_UTILS */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_ing_open.h b/arch/arm/mach-iproc/include/mach/socregs_ing_open.h +new file mode 100644 +index 0000000..2431b98 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch new file mode 100644 index 00000000..95057dd1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch @@ -0,0 +1,781 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_ing_open.h +@@ -0,0 +1,775 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_ING_OPEN_H ++#define __SOCREGS_ING_OPEN_H ++ ++#define ChipcommonA_ChipID 0x18000000 ++#define ChipcommonB_PWMCTL 0x18031000 ++#define ChipcommonB_WDT_WDOGLOAD 0x18039000 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonB_SMBus_Config 0x18038000 ++#define ChipcommonA_OTPProg 0x18000018 ++#define ChipcommonA_OTPLayout 0x1800001c ++#define ChipcommonA_CoreCapabilities 0x18000004 ++#define ChipcommonA_OTPStatus 0x18000010 ++#define ChipcommonB_rng_CTRL 0x18033000 ++#define QSPI_mspi_SPCR0_LSB 0x18027200 ++#define QSPI_mspi_DISABLE_FLUSH_GEN 0x18027384 ++#define QSPI_bspi_registers_REVISION_ID 0x18027000 ++#define QSPI_bspi_registers_BSPI_PIO_DATA 0x1802704c ++#define QSPI_raf_START_ADDR 0x18027100 ++#define QSPI_raf_interrupt_LR_fullness_reached 0x180273a0 ++#define QSPI_mspi_interrupt_MSPI_halt_set_transaction_done 0x180273b8 ++#define QSPI_IDM_IDM_IO_CONTROL_DIRECT 0x1811c408 ++#define QSPI_raf_CURR_ADDR 0x18027120 ++#define CRU_control 0x1803e000 ++#define GMAC0_DEVCONTROL 0x18022000 ++#define GMAC1_DEVCONTROL 0x18023000 ++#define ChipcommonA_GPIOEvent_BASE 0x078 ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_CLR_BASE 0x024 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOIntMask_BASE 0x074 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonB_GP_INT_MSTAT_BASE 0x020 ++#define ChipcommonA_GPIOEventIntPolarity_BASE 0x084 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonB_GP_INT_DE_BASE 0x010 ++#define ChipcommonB_GP_INT_EDGE_BASE 0x014 ++#define ChipcommonB_GP_INT_TYPE_BASE 0x00c ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonB_GP_PAD_RES_BASE 0x034 ++#define ChipcommonB_GP_RES_EN_BASE 0x038 ++#define ChipcommonA_ChipID 0x18000000 ++#define DMAC_pl330_DS 0x18020000 ++#define ChipcommonA_GPIOInput 0x18000060 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define PAXB_0_CLK_CONTROL 0x18012000 ++#define PAXB_0_CONFIG_IND_ADDR_BASE 0x120 ++#define ChipcommonB_MII_Management_Control 0x18032000 ++#define ChipcommonB_MII_Management_Command_Data 0x18032004 ++#define NAND_nand_flash_REVISION 0x18026000 ++#define NAND_direct_read_rd_miss 0x18026f00 ++#define NAND_IDM_IDM_IO_CONTROL_DIRECT 0x1811b408 ++#define ChipcommonB_PWM_PERIOD_COUNT0_BASE 0x004 ++#define ChipcommonB_PWM_PRESCALE_BASE 0x024 ++#define ChipcommonB_PWM_PERIOD_COUNT1_BASE 0x00c ++#define ChipcommonB_PWM_PERIOD_COUNT2_BASE 0x014 ++#define ChipcommonB_PWM_PERIOD_COUNT3_BASE 0x01c ++#define ChipcommonB_PWM_DUTYHI_COUNT0_BASE 0x008 ++#define ChipcommonB_PWM_DUTYHI_COUNT1_BASE 0x010 ++#define ChipcommonB_PWM_DUTYHI_COUNT2_BASE 0x018 ++#define ChipcommonB_PWM_DUTYHI_COUNT3_BASE 0x020 ++#define ChipcommonB_PWMCTL_BASE 0x000 ++#define ChipcommonB_rng_CTRL 0x18033000 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define USB2_IDM_IDM_IO_CONTROL_DIRECT 0x18115408 ++#define USB2D_IDM_IDM_IO_CONTROL_DIRECT 0x18116408 ++#define USB2D_IDM_IDM_IO_CONTROL_DIRECT__clk_enable 0 ++#define USB2D_IDM_IDM_RESET_CONTROL 0x18116800 ++#define USB2D_IDM_IDM_RESET_CONTROL__RESET 0 ++#endif ++#define DMU_CRU_RESET_BASE 0x200 ++#define ChipcommonB_SMBus1_SMBus_Config 0x1803b000 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define USB2D_ENDPNT_IN_CTRL_0 0x18042000 ++#endif ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810790c ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810791c ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18107a00 ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18108908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810890c ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18108914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810891c ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18108a00 ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18109908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810990c ++#define DDR_S1_IDM_ERROR_LOG_ID 0x18109914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810991c ++#define DDR_S1_IDM_INTERRUPT_STATUS 0x18109a00 ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x1810a900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x1810a904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0x1810a908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c ++#define DDR_S2_IDM_ERROR_LOG_ID 0x1810a914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810a91c ++#define DDR_S2_IDM_INTERRUPT_STATUS 0x1810aa00 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810b900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810b904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810b908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810b90c ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810b914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810b91c ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810ba00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x1810c900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x1810c904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x1810c908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810c90c ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x1810c914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810c91c ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x1810ca00 ++#endif ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810d900 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810d904 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810d908 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810d90c ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810d914 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810d91c ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810da00 ++#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810f900 ++#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810f904 ++#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810f908 ++#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810f90c ++#define APBY_S0_IDM_IDM_ERROR_LOG_ID 0x1810f914 ++#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810f91c ++#define APBY_S0_IDM_IDM_INTERRUPT_STATUS 0x1810fa00 ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1811a900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1811a904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1811a908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811a90c ++#define ROM_S0_IDM_ERROR_LOG_ID 0x1811a914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1811a91c ++#define ROM_S0_IDM_INTERRUPT_STATUS 0x1811aa00 ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811b900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811b904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811b908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c ++#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811b914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811b91c ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811ba00 ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811c900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811c904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811c908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811c90c ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811c914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811c91c ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811ca00 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811d900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811d904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811d908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811d914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811d91c ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811da00 ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x18120900 ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x18120904 ++#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x18120908 ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c ++#define SRAM_S0_IDM_ERROR_LOG_ID 0x18120914 ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1812091c ++#define SRAM_S0_IDM_INTERRUPT_STATUS 0x18120a00 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS 0x18121908 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190c ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ID 0x18121914 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812191c ++#define APBZ_S0_IDM_IDM_INTERRUPT_STATUS 0x18121a00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define APBV_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18122900 ++#define APBV_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18122904 ++#define APBV_S0_IDM_IDM_ERROR_LOG_STATUS 0x18122908 ++#define APBV_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812290c ++#define APBV_S0_IDM_IDM_ERROR_LOG_ID 0x18122914 ++#define APBV_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812291c ++#define APBV_S0_IDM_IDM_INTERRUPT_STATUS 0x18122a00 ++#endif ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18123900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18123904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x18123908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1812390c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18123914 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1812391c ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18123a00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define AXIIC_DS_4_IDM_ERROR_LOG_CONTROL 0x18124900 ++#define AXIIC_DS_4_IDM_ERROR_LOG_COMPLETE 0x18124904 ++#define AXIIC_DS_4_IDM_ERROR_LOG_STATUS 0x18124908 ++#define AXIIC_DS_4_IDM_ERROR_LOG_ADDR_LSB 0x1812490c ++#define AXIIC_DS_4_IDM_ERROR_LOG_ID 0x18124914 ++#define AXIIC_DS_4_IDM_ERROR_LOG_FLAGS 0x1812491c ++#define AXIIC_DS_4_IDM_INTERRUPT_STATUS 0x18124a00 ++#endif ++#define APBW_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 ++#define APBW_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 ++#define APBW_IDM_IDM_ERROR_LOG_STATUS 0x18131908 ++#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c ++#define APBW_IDM_IDM_ERROR_LOG_ID 0x18131914 ++#define APBW_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c ++#define APBW_IDM_IDM_INTERRUPT_STATUS 0x18131a00 ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18132908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18132914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18132a00 ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18141900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18141904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18141908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1814190c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18141914 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1814191c ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18141a00 ++#if (defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18142900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18142904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x18142908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1814290c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18142914 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x1814291c ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18142a00 ++#endif ++#define DMU_PCU_IPROC_STRAPS_CAPTURED_BASE 0x028 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_boot_dev_R 9 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_type_R 5 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_page_R 3 ++#define ChipcommonA_IntMask_BASE 0x024 ++#define DMU_PCU_CRU_RESET_REASON 0x1803f014 ++#define DMU_PCU_CRU_RESET_REASON__watchdog_reset 0 ++#define ChipcommonA_GPIOInput 0x18000060 ++#define ChipcommonA_GPIOOut 0x18000064 ++#define ChipcommonA_GPIOOutEn 0x18000068 ++#define AMAC_IDM0_IO_CONTROL_DIRECT 0x18110408 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__DIRECT_GMII_MODE 5 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__DEST_SYNC_MODE_EN 3 ++#define AMAC_IDM1_IO_CONTROL_DIRECT 0x18111408 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__DIRECT_GMII_MODE 5 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__DEST_SYNC_MODE_EN 3 ++#if defined(CONFIG_MACH_KT2) ++#define IPROC_WRAP_USBPHY_CTRL 0x1803fc20 ++#define IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL 1 ++#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 3 ++#define IPROC_WRAP_MISC_CONTROL 0x1803fc24 ++#define IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0 0x1803fc00 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_BASE 0xc00 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__CH0_MDEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__NDIV_RELOCK 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__NDIV_RELOCK_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__NDIV_RELOCK_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__FAST_LOCK 27 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__FAST_LOCK_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__FAST_LOCK_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DIV2 26 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DIV2_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DIV2_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_L 25 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_R 24 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_WIDTH 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__VCO_DLY_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_L 23 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_R 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_WIDTH 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__PWM_RATE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_L 21 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_R 20 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_WIDTH 2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_MODE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__AUX_CTRL 19 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__AUX_CTRL_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__AUX_CTRL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__TESTCLKOUT 18 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__TESTCLKOUT_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__TESTCLKOUT_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_UPDATE 17 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_UPDATE_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_UPDATE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_L 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_R 14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_SELECT_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_RESET 13 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_RESET_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__STAT_RESET_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_ENABLE 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_ENABLE_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_ENABLE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_L 11 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_WIDTH 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__DCO_CTRL_BYPASS_RESETVALUE 0x000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_0_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1 0x1803fc04 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_BASE 0xc04 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KA_RESETVALUE 0x2 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_L 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_R 26 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KI_RESETVALUE 0x3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_L 25 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_R 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_WIDTH 4 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__KP_RESETVALUE 0x7 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_L 21 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_WIDTH 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__SSC_LIMIT_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_1_RESETVALUE 0x4dc00000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2 0x1803fc08 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_BASE 0xc08 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__PDIV_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_PHASE_EN 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_PHASE_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_PHASE_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_L 27 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_R 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_WIDTH 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__FB_OFFSET_RESETVALUE 0x000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_L 15 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_WIDTH 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__SSC_STEP_RESETVALUE 0x0000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_2_RESETVALUE 0x20000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3 0x1803fc0c ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_BASE 0xc0c ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__SSC_MODE 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__SSC_MODE_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__SSC_MODE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__PHASE8_EN 30 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__PHASE8_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__PHASE8_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_L 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_R 10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_WIDTH 20 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_FRAC_RESETVALUE 0x00000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_L 9 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_WIDTH 10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__NDIV_INT_RESETVALUE 0x80 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_3_RESETVALUE 0x80 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4 0x1803fc10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_BASE 0xc10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_R 29 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__RESERVED_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__PWRDWN 28 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__PWRDWN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__PWRDWN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_L 27 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_R 24 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_WIDTH 4 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__SPARE_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_EN 23 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_SEL 22 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_SEL_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__TEST_SEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__D2C_HYST_EN 21 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__D2C_HYST_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__D2C_HYST_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__BYPASS_POR 20 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__BYPASS_POR_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__BYPASS_POR_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_L 19 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_R 14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_WIDTH 6 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__LOAD_EN_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_L 13 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_R 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_WIDTH 6 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__HOLD_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_L 7 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_WIDTH 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__CH0_MDIV_RESETVALUE 0x08 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_4_RESETVALUE 0x8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5 0x1803fc14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_BASE 0xc14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_R 17 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_WIDTH 15 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__RESERVED_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_SW_OVWR 16 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_SW_OVWR_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_SW_OVWR_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT1_EN 15 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT1_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT1_EN_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT0_EN 14 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT0_EN_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_OUT0_EN_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_IN_SEL 13 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_IN_SEL_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_CLK_IN_SEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_POST_RESETB 12 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_POST_RESETB_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_POST_RESETB_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_RESETB 11 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_RESETB_WIDTH 1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__IPROC_DDR_PLL_RESETB_RESETVALUE 0x1 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_L 10 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_R 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_WIDTH 3 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDEL_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_L 7 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_WIDTH 8 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__CH1_MDIV_RESETVALUE 0x64 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__WIDTH 32 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__ALL_L 31 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5__ALL_R 0 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_CTRL_REGISTER_5_RESETVALUE 0xd864 ++#define IPROC_DDR_PLL_STATUS 0x1803fc18 ++#define IPROC_DDR_PLL_STATUS_BASE 0xc18 ++#define IPROC_DDR_PLL_STATUS__RESERVED_L 31 ++#define IPROC_DDR_PLL_STATUS__RESERVED_R 14 ++#define IPROC_DDR_PLL_STATUS__RESERVED_WIDTH 18 ++#define IPROC_DDR_PLL_STATUS__RESERVED_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_LOST 13 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_LOST_WIDTH 1 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_LOST_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK 12 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_WIDTH 1 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_LOCK_RESETVALUE 0x0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_L 11 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_R 0 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_WIDTH 12 ++#define IPROC_DDR_PLL_STATUS__IPROC_DDR_PLL_STAT_OUT_RESETVALUE 0x000 ++#define IPROC_DDR_PLL_STATUS_WIDTH 32 ++#define IPROC_DDR_PLL_STATUS__WIDTH 32 ++#define IPROC_DDR_PLL_STATUS_ALL_L 31 ++#define IPROC_DDR_PLL_STATUS_ALL_R 0 ++#define IPROC_DDR_PLL_STATUS__ALL_L 31 ++#define IPROC_DDR_PLL_STATUS__ALL_R 0 ++#define IPROC_DDR_PLL_STATUS_DATAMASK 0xffffffff ++#define IPROC_DDR_PLL_STATUS_RDWRMASK 0x00000000 ++#define IPROC_DDR_PLL_STATUS_RESETVALUE 0x0 ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_WRAP_USBPHY_CTRL 0x1803fc34 ++#define IPROC_WRAP_GEN_PLL_STATUS__GEN_PLL_LOCK 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_WIDTH 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_R 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_WIDTH 3 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH0_MDIV_R 13 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH1_MDIV_R 21 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH2_MDIV_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R 8 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH4_MDIV_R 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0 0x1803fc1c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_BASE 0xc1c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_R 24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH5_MDIV_RESETVALUE 0x18 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_L 23 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_R 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH4_MDIV_RESETVALUE 0x0f ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_L 15 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_R 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH3_MDIV_RESETVALUE 0x64 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_L 7 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__CH0_MDIV_RESETVALUE 0x1e ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_0_RESETVALUE 0x180f641e ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1 0x1803fc20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_BASE 0xc20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_R 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__Reserved_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__SW_OVWR 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__SW_OVWR_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__SW_OVWR_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__POST_RESETB 26 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__POST_RESETB_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__POST_RESETB_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__RESETB 25 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__RESETB_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__RESETB_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_L 24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_R 22 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__PDIV_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_L 21 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_R 18 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KP_RESETVALUE 0x8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_L 17 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_R 15 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KI_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_L 14 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_R 12 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__KA_RESETVALUE 0x4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_L 11 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_R 6 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_WIDTH 6 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__LOAD_EN_CH_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_L 5 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_WIDTH 6 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__HOLD_CH_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_1_RESETVALUE 0x660c000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2 0x1803fc24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_BASE 0xc24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_R 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__RSVD_0_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_L 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_R 20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH2_MDIV_RESETVALUE 0x00 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_L 19 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_R 17 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH5_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_L 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_R 14 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH4_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_L 13 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_R 11 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH3_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_L 10 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_R 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH0_MDEL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_L 7 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__CH1_MDIV_RESETVALUE 0x0f ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_2_RESETVALUE 0xf ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3 0x1803fc28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_BASE 0xc28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_R 30 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_WIDTH 2 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__RSVD_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT2_EN 29 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT2_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT2_EN_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_2ED_OUT_EN 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_2ED_OUT_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_2ED_OUT_EN_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_L 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_R 26 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_WIDTH 2 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DIG_LDO_CTRL_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_L 25 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_R 24 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_WIDTH 2 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ANA_LDO_CTRL_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT_EN 23 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__TESTOUT_EN_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_OUTPUT_EN 22 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_OUTPUT_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_OUTPUT_EN_RESETVALUE 0x1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_BYP_EN 21 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_BYP_EN_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__CML_BYP_EN_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__VCOdiv2 20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__VCOdiv2_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__VCOdiv2_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__AUX_CTRL 19 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__AUX_CTRL_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__AUX_CTRL_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__REFCLKOUT 18 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__REFCLKOUT_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__REFCLKOUT_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_UPDATE 17 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_UPDATE_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_UPDATE_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_L 16 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_R 14 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_WIDTH 3 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_SELECT_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_RESET 13 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_RESET_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__STAT_RESET_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_ENABLE 12 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_ENABLE_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_ENABLE_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_L 11 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_WIDTH 12 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__DCO_CTRL_BYPASS_RESETVALUE 0x000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_3_RESETVALUE 0x15400000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4 0x1803fc2c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_BASE 0xc2c ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_R 28 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_WIDTH 4 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__RSVD_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_L 27 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_R 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_WIDTH 20 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_FRAC_RESETVALUE 0x00000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_L 7 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_WIDTH 8 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__NDIV_INT_RESETVALUE 0x78 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_CTRL_4_RESETVALUE 0x78 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS 0x1803fc30 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_BASE 0xc30 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__IPROC_WRAP_XGPLL_LOCK 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__IPROC_WRAP_XGPLL_LOCK_WIDTH 1 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__IPROC_WRAP_XGPLL_LOCK_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_L 30 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_WIDTH 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__XGPLL_STATUS_RESETVALUE 0x0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__WIDTH 32 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__ALL_L 31 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS__ALL_R 0 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_DATAMASK 0xffffffff ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_RDWRMASK 0x00000000 ++#define IPROC_WRAP_IPROC_XGPLL_STATUS_RESETVALUE 0x0 ++#if defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL 3 ++#define IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL 2 ++#define IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL 4 ++#endif ++#define IPROC_WRAP_MISC_CONTROL 0x1803fc3c ++#endif ++ ++#endif /* __SOCREGS_ING_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_ns_open.h b/arch/arm/mach-iproc/include/mach/socregs_ns_open.h +new file mode 100644 +index 0000000..8f3d2eb diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch new file mode 100644 index 00000000..f694a373 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch @@ -0,0 +1,87 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_ns_open.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_NS_OPEN_H ++#define __SOCREGS_NS_OPEN_H ++ ++ ++#define CCA_CHIPID 0x18000000 ++#define CCA_CHIPID_BASE 0x000 ++#define CCB_GP_DATA_IN 0x18001000 ++#define USB30_BASE 0x18023000 ++#define SDIO_EMMC_SDXC_SYSADDR 0x18020000 ++#define CCB_PWM_CTL 0x18002000 ++#define CCB_TIM0_TIM_TMR1_LOAD 0x18005000 ++#define CCB_TIM1_TIM_TMR1_LOAD 0x18006000 ++#define CCB_SMBUS_START 0x18009000 ++#define CCB_GP_AUX_SEL_BASE 0x028 ++#define QSPI_MSPI_SPCR0_LSB 0x18029200 ++#define QSPI_MSPI_DISABLE_FLUSH_GEN 0x18029384 ++#define QSPI_BSPI_REGS_REV_ID 0x18029000 ++#define QSPI_BSPI_REGS_BSPI_PIO_DATA 0x1802904c ++#define QSPI_RAF_START_ADDR 0x18029100 ++#define QSPI_RAF_CURR_ADDR 0x18029120 ++#define QSPI_RAF_INTERRUPT_LR_FULLNESS_REACHED 0x180293a0 ++#define QSPI_MSPI_INTERRUPT_MSPI_HALT_SET_TRANSACTION_DONE 0x180293b8 ++#define GMAC0_DEVCTL 0x18024000 ++#define GMAC1_DEVCTL 0x18025000 ++#define GMAC2_DEVCTL 0x18026000 ++#define GMAC3_DEVCTL 0x18027000 ++#define CCA_GPIO_EVT_BASE 0x078 ++#define CCA_GPIO_INPUT 0x18000060 ++#define CCA_GPIO_INPUT_BASE 0x060 ++#define CCB_GP_INT_CLR_BASE 0x024 ++#define CCA_GPIO_EVTINT_MASK_BASE 0x07c ++#define CCB_GP_INT_MSK_BASE 0x018 ++#define CCA_GPIOINT_MASK_BASE 0x074 ++#define CCA_GPIO_EVT_INT_POLARITY_BASE 0x084 ++#define CCA_GPIO_INT_POLARITY_BASE 0x070 ++#define CCA_INT_MASK_BASE 0x024 ++#define CCB_GP_INT_TYPE_BASE 0x00c ++#define CCB_GP_INT_DE_BASE 0x010 ++#define CCB_GP_INT_EDGE_BASE 0x014 ++#define CCA_INT_STS_BASE 0x020 ++#define CCB_GP_INT_MSTAT_BASE 0x020 ++#define CCB_GP_PAD_RES_BASE 0x034 ++#define CCB_GP_RES_EN_BASE 0x038 ++#define CCB_MII_MGMT_CTL 0x18003000 ++#define CCB_MII_MGMT_DATA 0x18003004 ++#define NAND_NAND_FLASH_REV 0x18028000 ++#define ChipcommonB_MII_Management_Control CCB_MII_MGMT_CTL ++#define ChipcommonB_MII_Management_Command_Data CCB_MII_MGMT_DATA ++#define NAND_DIRECT_READ_RD_MISS 0x18028f00 ++#define CCB_PWM_PRESCALE_BASE 0x024 ++#define CCB_PWM_PERIOD_COUNT0_BASE 0x004 ++#define CCB_PWM_PERIOD_COUNT1_BASE 0x00c ++#define CCB_PWM_DUTY_HI_COUNT2_BASE 0x018 ++#define CCB_PWM_PERIOD_COUNT3_BASE 0x01c ++#define CCB_PWM_DUTY_HI_COUNT0_BASE 0x008 ++#define CCB_PWM_DUTY_HI_COUNT1_BASE 0x010 ++#define CCB_PWM_DUTY_HI_COUNT2_BASE 0x018 ++#define CCB_PWM_DUTY_HI_COUNT3_BASE 0x020 ++#define CCB_PWM_CTL_BASE 0x000 ++#define CCB_PWM_PERIOD_COUNT2_BASE 0x014 ++#define CCB_RNG_CTRL 0x18004000 ++ ++ ++#endif /* __SOCREGS_NS_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_nsp_open.h b/arch/arm/mach-iproc/include/mach/socregs_nsp_open.h +new file mode 100644 +index 0000000..e98c003 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch new file mode 100644 index 00000000..a0d18cd2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch @@ -0,0 +1,404 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_nsp_open.h +@@ -0,0 +1,398 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_NSP_OPEN_H ++#define __SOCREGS_NSP_OPEN_H ++ ++#define ChipcommonA_ChipID 0x18000000 ++#define PCU_MDIO_MGT 0x1803f000 ++#define ChipcommonB_PWMCTL 0x18031000 ++#define ChipcommonB_WDT_WDOGLOAD 0x18039000 ++#define USB3_CAPLENGTH 0x18029000 ++#define USB30_BASE USB3_CAPLENGTH ++#define SATA_AHCI_GHC_HBA_CAP 0x18041000 ++#define SATA_M0_IDM_IO_CONTROL_DIRECT 0x1811e408 ++#define SATA_M0_IDM_IDM_RESET_CONTROL 0x1811e800 ++#define SATA3_PCB_UPPER_REG1 0x18040304 ++#define SATA3_PCB_UPPER_REG0 0x18040300 ++#define SATA3_PCB_UPPER_REG1 0x18040304 ++#define SATA3_PCB_UPPER_REG11 0x1804032c ++#define SATA3_PCB_UPPER_REG5 0x18040314 ++#define SATA3_PCB_UPPER_REG15 0x1804033c ++#define SATA_TOP_CTRL_BUS_CTRL 0x18040024 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonB_SMBus_Config 0x18038000 ++#define ChipcommonB_tim0_TIM_TIMER1Load 0x18034000 ++#define ChipcommonB_tim1_TIM_TIMER1Load 0x18035000 ++#define QSPI_mspi_SPCR0_LSB 0x18027200 ++#define QSPI_mspi_DISABLE_FLUSH_GEN 0x18027384 ++#define QSPI_bspi_registers_REVISION_ID 0x18027000 ++#define QSPI_bspi_registers_BSPI_PIO_DATA 0x1802704c ++#define QSPI_raf_START_ADDR 0x18027100 ++#define QSPI_raf_interrupt_LR_fullness_reached 0x180273a0 ++#define QSPI_mspi_interrupt_MSPI_halt_set_transaction_done 0x180273b8 ++#define QSPI_IDM_IDM_IO_CONTROL_DIRECT 0x1811c408 ++#define QSPI_raf_CURR_ADDR 0x18027120 ++#define CRU_control 0x1803e000 ++#define GMAC0_DEVCONTROL 0x18022000 ++#define GMAC1_DEVCONTROL 0x18023000 ++#define FA_GMAC0_DEVCONTROL 0x18024000 ++#define FA_GMAC1_DEVCONTROL 0x18025000 ++#define CRU_CLKSET_KEY_OFFSET 0x1803f180 ++#define CRU_LCPLL2_CONTROL0 0x1803f548 ++#define CRU_LCPLL2_CONTROL0__PWRDWN 12 ++#define CRU_LCPLL2_CONTROL0__RESETB 11 ++#define CRU_LCPLL2_STATUS__LOCK 12 ++#define CRU_LCPLL2_CONTROL0__PWRDWN 12 ++#define CRU_LCPLL2_CONTROL0__RESETB 11 ++#define CRU_RESET__SGMII_RESET_N 8 ++#define CRU_RESET 0x1803f184 ++#define SGMII_CONFIG 0x1803f410 ++#define SGMII_CONFIG__RSTB_PLL 17 ++#define SGMII_CONFIG__RSTB_MDIOREGS 16 ++#define SGMII_CONFIG__TXD1G_FIFO_RSTB_WIDTH 4 ++#define SGMII_CONFIG__TXD1G_FIFO_RSTB_R 11 ++#define P5_MUX_CONFIG__P5_MODE_WIDTH 3 ++#define CRU_LCPLL2_CONTROL0__POST_RESETB 10 ++#define P5_MUX_CONFIG 0x1803f308 ++#define P5_MUX_CONFIG__P5_MODE_R 0 ++#define P5_MUX_CONFIG__P5_MODE_SGMII 0x0 ++#define P5_MUX_CONFIG__P5_MODE_GPHY3 0x4 ++#define P4_MUX_CONFIG 0x1803f30c ++#define P4_MUX_CONFIG__P4_MODE_R 0 ++#define P4_MUX_CONFIG__P4_MODE_WIDTH 3 ++#define P4_MUX_CONFIG__P4_MODE_SGMII 0x0 ++#define ChipcommonA_GPIOEvent_BASE 0x078 ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_CLR_BASE 0x024 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonA_GPIOInput_BASE 0x060 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOIntMask_BASE 0x074 ++#define ChipcommonB_GP_INT_MSK_BASE 0x018 ++#define ChipcommonA_GPIOEventIntMask_BASE 0x07c ++#define ChipcommonB_GP_INT_MSTAT_BASE 0x020 ++#define ChipcommonA_GPIOEventIntPolarity_BASE 0x084 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define ChipcommonA_IntStatus_BASE 0x020 ++#define ChipcommonB_GP_INT_DE_BASE 0x010 ++#define ChipcommonB_GP_INT_EDGE_BASE 0x014 ++#define ChipcommonB_GP_INT_TYPE_BASE 0x00c ++#define ChipcommonA_GPIOIntPolarity_BASE 0x070 ++#define CRU_GPIO_CONTROL0_BASE 0x1f1c0 ++#define ChipcommonB_GP_AUX_SEL_BASE 0x028 ++#define CRU_GPIO_CONTROL7_BASE 0x1f1dc ++#define CRU_GPIO_CONTROL8_BASE 0x1f1e0 ++#define ChipcommonB_GP_PAD_RES_BASE 0x034 ++#define ChipcommonB_GP_RES_EN_BASE 0x038 ++#define ChipcommonA_ChipID 0x18000000 ++#define DMAC_pl330_DS 0x18020000 ++#define ChipcommonA_GPIOInput 0x18000060 ++#define ChipcommonB_GP_DATA_IN 0x18030000 ++#define PAXB_0_CLK_CONTROL 0x18012000 ++#define PAXB_0_CONFIG_IND_ADDR_BASE 0x120 ++#define ChipcommonB_MII_Management_Control 0x18032000 ++#define ChipcommonB_MII_Management_Command_Data 0x18032004 ++#define NAND_nand_flash_REVISION 0x18026000 ++#define NAND_direct_read_rd_miss 0x18026f00 ++#define NAND_IDM_IDM_IO_CONTROL_DIRECT 0x1811b408 ++#define ChipcommonB_PWM_PERIOD_COUNT0_BASE 0x004 ++#define ChipcommonB_PWM_PRESCALE_BASE 0x024 ++#define ChipcommonB_PWM_PERIOD_COUNT1_BASE 0x00c ++#define ChipcommonB_PWM_PERIOD_COUNT2_BASE 0x014 ++#define ChipcommonB_PWM_PERIOD_COUNT3_BASE 0x01c ++#define ChipcommonB_PWM_DUTYHI_COUNT0_BASE 0x008 ++#define ChipcommonB_PWM_DUTYHI_COUNT1_BASE 0x010 ++#define ChipcommonB_PWM_DUTYHI_COUNT2_BASE 0x018 ++#define ChipcommonB_PWM_DUTYHI_COUNT3_BASE 0x020 ++#define ChipcommonB_PWMCTL_BASE 0x000 ++#define ChipcommonB_rng_CTRL 0x18033000 ++#define USB2_IDM_IDM_IO_CONTROL_DIRECT 0x18115408 ++#define USB3_IDM_IDM_RESET_CONTROL 0x18104800 ++#define CRU_WATCHDOG_PCIE_RESET_STATUS 0x1803f564 ++#define CRU_WATCHDOG_PCIE_RESET_STATUS__CCB_WATCHDOG_RESET_EVENT 0 ++#define SDIO_eMMCSDXC_SYSADDR 0x18021000 ++#define IHOST_M0_IO_CONTROL_DIRECT 0x18100408 ++#define ChipcommonA_IntMask_BASE 0x024 ++#define ChipcommonA_OTPProg 0x18000018 ++#define ChipcommonA_OTPLayout 0x1800001c ++#define ChipcommonA_CoreCapabilities 0x18000004 ++#define ChipcommonA_OTPStatus 0x18000010 ++#define SDIO_IDM_IO_CONTROL_DIRECT 0x18117408 ++#define SDIO_IDM_IO_CONTROL_DIRECT__CMD_COMFLICT_DISABLE 22 ++ ++ ++/* IDM registers */ ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810790c ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810791c ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18107a00 ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18108908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810890c ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18108914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810891c ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18108a00 ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0x18109908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810990c ++#define DDR_S1_IDM_ERROR_LOG_ID 0x18109914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0x1810991c ++#define DDR_S1_IDM_INTERRUPT_STATUS 0x18109a00 ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0x1810a900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0x1810a904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0x1810a908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c ++#define DDR_S2_IDM_ERROR_LOG_ID 0x1810a914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0x1810a91c ++#define DDR_S2_IDM_INTERRUPT_STATUS 0x1810aa00 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810b900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810b904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810b908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810b90c ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x1810b914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810b91c ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x1810ba00 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x1810c900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x1810c904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x1810c908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810c90c ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x1810c914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810c91c ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x1810ca00 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_CONTROL 0x1810d900 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_COMPLETE 0x1810d904 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_STATUS 0x1810d908 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810d90c ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_ID 0x1810d914 ++#define AXI_PCIE_S2_IDM_IDM_ERROR_LOG_FLAGS 0x1810d91c ++#define AXI_PCIE_S2_IDM_IDM_INTERRUPT_STATUS 0x1810da00 ++#define APBY_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810f900 ++#define APBY_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810f904 ++#define APBY_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810f908 ++#define APBY_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810f90c ++#define APBY_S0_IDM_IDM_ERROR_LOG_ID 0x1810f914 ++#define APBY_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810f91c ++#define APBY_S0_IDM_IDM_INTERRUPT_STATUS 0x1810fa00 ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0x1811a900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0x1811a904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0x1811a908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811a90c ++#define ROM_S0_IDM_ERROR_LOG_ID 0x1811a914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0x1811a91c ++#define ROM_S0_IDM_INTERRUPT_STATUS 0x1811aa00 ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0x1811b900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0x1811b904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0x1811b908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c ++#define NAND_IDM_IDM_ERROR_LOG_ID 0x1811b914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0x1811b91c ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0x1811ba00 ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0x1811c900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0x1811c904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0x1811c908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811c90c ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0x1811c914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0x1811c91c ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0x1811ca00 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1811d900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1811d904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x1811d908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x1811d914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811d91c ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x1811da00 ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x18120900 ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x18120904 ++#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x18120908 ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c ++#define SRAM_S0_IDM_ERROR_LOG_ID 0x18120914 ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1812091c ++#define SRAM_S0_IDM_INTERRUPT_STATUS 0x18120a00 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_STATUS 0x18121908 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812190c ++#define APBZ_S0_IDM_IDM_ERROR_LOG_ID 0x18121914 ++#define APBZ_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812191c ++#define APBZ_S0_IDM_IDM_INTERRUPT_STATUS 0x18121a00 ++#define APBV_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18122900 ++#define APBV_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18122904 ++#define APBV_S0_IDM_IDM_ERROR_LOG_STATUS 0x18122908 ++#define APBV_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1812290c ++#define APBV_S0_IDM_IDM_ERROR_LOG_ID 0x18122914 ++#define APBV_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1812291c ++#define APBV_S0_IDM_IDM_INTERRUPT_STATUS 0x18122a00 ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x18123900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x18123904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x18123908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1812390c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x18123914 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1812391c ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x18123a00 ++#define AXIIC_DS_4_IDM_ERROR_LOG_CONTROL 0x18124900 ++#define AXIIC_DS_4_IDM_ERROR_LOG_COMPLETE 0x18124904 ++#define AXIIC_DS_4_IDM_ERROR_LOG_STATUS 0x18124908 ++#define AXIIC_DS_4_IDM_ERROR_LOG_ADDR_LSB 0x1812490c ++#define AXIIC_DS_4_IDM_ERROR_LOG_ID 0x18124914 ++#define AXIIC_DS_4_IDM_ERROR_LOG_FLAGS 0x1812491c ++#define AXIIC_DS_4_IDM_INTERRUPT_STATUS 0x18124a00 ++#define APBW_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 ++#define APBW_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 ++#define APBW_IDM_IDM_ERROR_LOG_STATUS 0x18131908 ++#define APBW_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c ++#define APBW_IDM_IDM_ERROR_LOG_ID 0x18131914 ++#define APBW_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c ++#define APBW_IDM_IDM_INTERRUPT_STATUS 0x18131a00 ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18132908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18132914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18132a00 ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18141900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18141904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18141908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1814190c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18141914 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1814191c ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18141a00 ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18142900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18142904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x18142908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1814290c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18142914 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x1814291c ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18142a00 ++#define CTF_CONTROL_REG 0x18025c00 ++#define CTF_CONTROL_BASE 0x5c00 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_TWO_EXP37 0x0 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_TWO_EXP31 0x1 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_TWO_EXP26 0x2 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_ESTABLISHED_TIMEBASE_R 2 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_FINISHED_TIMEBASE_R 0 ++#define CTF_FLOW_TIMER_CONFIG1__TCP_ESTABLISHED_TIMEOUT_R 8 ++#define CTF_FLOW_TIMER_CONFIG1__UDP_ESTABLISHED_TIMEOUT_R 16 ++#define CTF_FLOW_TIMER_CONFIG1__TCP_FINISHED_TIMEOUT_R 0 ++#define CTF_FLOW_TIMER_CONFIG0__UDP_ESTABLISHED_TIMEBASE_R 4 ++#define CTF_FLOW_TIMER_CONFIG0__UDP_ESTABLISHED_TIMEBASE_R 4 ++#define CTF_FLOW_TIMER_CONFIG0__UDP_ESTABLISHED_TIMEBASE_TWO_EXP31 0x1 ++#define CTF_FLOW_TIMER_CONFIG0__TCP_ESTABLISHED_TIMEBASE_TWO_EXP31 0x1 ++#define CTF_FLOW_TIMEOUT_CONTROL__FLOW_ENTRY_POINTER_R 5 ++ ++#define CTF_DRR_CONFIG__MAC_WEIGHT_R 7 ++#define CTF_MEM_ACC_CONTROL__RD_WR_N 15 ++#define CTF_MEM_ACC_CONTROL__TABLE_SELECT_R 12 ++#define CTF_MEM_ACC_CONTROL__ALL_R 0 ++ ++#define PAE_M0_IDM_IDM_RESET_CONTROL 0x1811f800 ++#define PAE_S0_IDM_IDM_RESET_CONTROL 0x18125800 ++#define CTF_CONTROL__MEM_INIT 1 ++#define AMAC_IDM0_IO_CONTROL_DIRECT 0x18110408 ++#define AMAC_IDM0_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define AMAC_IDM1_IO_CONTROL_DIRECT 0x18111408 ++#define AMAC_IDM1_IO_CONTROL_DIRECT__CLK_250_SEL 6 ++#define CTF_CONTROL__CTF_MODE 0 ++#define CTF_CONTROL__FRAGMENTATION_ENABLE 2 ++#define CTF_CONTROL__DISABLE_MAC_DA_CHECK 3 ++#define CTF_CONTROL__PAE_ENABLED 5 ++#define CTF_CONTROL__SPU_ENABLE 6 ++#define CTF_BRCM_HDR_CONTROL 0x18025c08 ++#define CTF_BRCM_HDR_CONTROL__BRCM_HDR_REASON_CODE_MASK_WIDTH 8 ++#define CTF_BRCM_HDR_CONTROL__BRCM_HDR_REASON_CODE_MASK_R 0 ++#define SPU_CONTROL 0x1802f000 ++#define SPU_CONTROL__OUT_ENDIAN 12 ++#define SPU_CONTROL__IN_ENDIAN 11 ++#define SPU_CONTROL__SOFT_RST 1 ++#define R5_CONFIG0 0x180490d8 ++#define R5_CONFIG0__TE_INIT 31 ++#define R5_CONFIG0__SYS_PORESET 30 ++#define R5_CONFIG0__RESET_N 29 ++#define R5_CONFIG0__PARITY_ODD 28 ++#define R5_CONFIG0__PADDR_DEBUG31 27 ++#define R5_CONFIG0__LOC_ZERO_RAMA 26 ++#define R5_CONFIG0__INTERRUPT_ASYNC 25 ++#define R5_CONFIG0__INITRAMB 24 ++#define R5_CONFIG0__INITRAMA 23 ++#define R5_CONFIG0__DEBUG_RESTART 22 ++#define R5_CONFIG0__DEBUG_RESET_N 21 ++#define R5_CONFIG0__DEBUG_RESET 20 ++#define R5_CONFIG0__DEBUG_RESET 20 ++#define R5_CONFIG0__DEBUG_NO_CLK_STOP 19 ++#define R5_CONFIG0__DEBUG_NIDEN 18 ++#define R5_CONFIG0__DEBUG_ENTCM1IF 17 ++#define R5_CONFIG0__DEBUG_EN 16 ++#define R5_CONFIG0__DEBUG_EDBGRQ 15 ++#define R5_CONFIG0__DAP_DAP_TO_DEBUG_APB_EN 14 ++#define R5_CONFIG0__CPU_HALT 13 ++#define R5_CONFIG0__CFG_ENDIAN 12 ++#define R5_CONFIG0__CFG_EE 11 ++#define R5_CONFIG0__BTCM_SPLIT 10 ++#define R5_CONFIG0__BTCM_SIZE_R 6 ++#define R5_CONFIG0__BTCM_SIZE_WIDTH 4 ++#define R5_CONFIG0__ATCM_SIZE_R 2 ++#define R5_CONFIG0__ATCM_SIZE_WIDTH 4 ++#define R5_CONFIG0__RMW_RAM_R 0 ++#define R5_CONFIG0__RMW_RAM_WIDTH 2 ++ ++#define PAE_ECC_DEBUG 0x180490cc ++#define PAE_ECC_DEBUG__ECC_DISABLE 10 ++#define PAE_BUFFER_CONFIG 0x18049010 ++#define PAE_BUFFER_CONFIG__PAE_MEM_INIT 1 ++#define PAE_BUFFER_CONFIG__PAE_SYS_INIT 0 ++#define PAE_BUFFER_CONFIG__PAE_MEM_INIT_DONE 2 ++#define PAE_BUFFER_ALLOCATION0 0x18049018 ++#define PAE_BUFFER_ALLOCATION0 0x18049018 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_END_ADDR_R 16 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_END_ADDR_WIDTH 12 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_START_ADDR_R 0 ++#define PAE_BUFFER_ALLOCATION__INTERCEPT_PT_START_ADDR_WIDTH 12 ++ ++#define PAE_BUFFER_ALLOCATION1 0x1804901c ++#define PAE_BUFFER_BACKPRESSURE_CONFIG0 0x18049020 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XOFF_R 16 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XOFF_WIDTH 12 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XON_R 0 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG__WATERMARK_DEPTH_XON_WIDTH 12 ++#define PAE_BUFFER_BACKPRESSURE_CONFIG1 0x18049024 ++#define PAE_BUFFER_CONGESTION_CONFIG 0x18049028 ++#define PAE_BUFFER_CONGESTION_CONFIG__ENQ0_STOP_LEVEL_R 0 ++#define PAE_BUFFER_CONGESTION_CONFIG__ENQ0_STOP_LEVEL_WIDTH 12 ++#define PAE_BUFFER_BACKPRESSURE_MAP0 0x1804902c ++#define PAE_BUFFER_BACKPRESSURE_MAP__INTERCEPT_PT_BACKPRESSURE_CONTRIBUTOR_MASK_R 0 ++#define PAE_BUFFER_BACKPRESSURE_MAP__INTERCEPT_PT_BACKPRESSURE_CONTRIBUTOR_MASK_WIDTH 2 ++#define PAE_BUFFER_BACKPRESSURE_MAP1 0x18049030 ++#define PAE_SCRATCHPAD_ALLOCATION 0x18049014 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_END_ADDR_R 16 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_END_ADDR_WIDTH 12 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_START_ADDR_R 0 ++#define PAE_SCRATCHPAD_ALLOCATION__SCRATCHPAD_START_ADDR_WIDTH 12 ++#define CTF_DEBUG_CONTROL 0x18025ca0 ++#define CTF_DEBUG_CONTROL__DM_FIFO_BP_LEVEL_R 10 ++#define CTF_DEBUG_CONTROL__DM_FIFO_BP_LEVEL_WIDTH 8 ++#define AXIIC_sata_m0_fn_mod 0x1a051108 ++ ++#endif /* __SOCREGS_NSP_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/socregs_p7_open.h b/arch/arm/mach-iproc/include/mach/socregs_p7_open.h +new file mode 100644 +index 0000000..4ffeeba diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch new file mode 100644 index 00000000..4a9e13f3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch @@ -0,0 +1,267 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/socregs_p7_open.h +@@ -0,0 +1,261 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __SOCREGS_P7_OPEN_H ++#define __SOCREGS_P7_OPEN_H ++ ++#ifdef CONFIG_MACH_GH ++/* ++ * Greyhound only registers ++ */ ++#define DMU_PCU_IPROC_CONTROL 0x1800f000 ++#define DMU_CRU_RESET_BASE 0x200 ++ ++#define DMU_PCU_IPROC_STRAPS_CAPTURED_BASE 0x028 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_boot_dev_R 9 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_type_R 5 ++#define DMU_PCU_IPROC_STRAPS_CAPTURED__strap_nand_page_R 3 ++ ++#define IPROC_WRAP_GEN_PLL_STATUS__GEN_PLL_LOCK 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_WIDTH 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_R 10 ++#define IPROC_WRAP_GEN_PLL_CTRL1__PDIV_WIDTH 4 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH0_MDIV_R 14 ++#define IPROC_WRAP_GEN_PLL_CTRL1__CH1_MDIV_R 22 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH2_MDIV_R 0 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R 8 ++#define IPROC_WRAP_GEN_PLL_CTRL2__CH4_MDIV_R 16 ++ ++#endif /* End of Greyhound only registers */ ++ ++#define ICFG_CHIP_ID_REG 0x18000000 ++#define ChipcommonG_UART0_UART_RBR_THR_DLL 0x18020000 ++#define ChipcommonG_UART1_UART_RBR_THR_DLL 0x18021000 ++ ++#define QSPI_mspi_SPCR0_LSB 0x18047200 ++#define QSPI_mspi_DISABLE_FLUSH_GEN 0x18047384 ++#define QSPI_bspi_registers_REVISION_ID 0x18047000 ++#define QSPI_bspi_registers_BSPI_PIO_DATA 0x1804704c ++#define QSPI_raf_START_ADDR 0x18047100 ++#define QSPI_raf_CURR_ADDR 0x18047120 ++#define QSPI_raf_interrupt_LR_fullness_reached 0x180473a0 ++#define QSPI_mspi_interrupt_MSPI_halt_set_transaction_done 0x180473b8 ++#define QSPI_IDM_IDM_IO_CONTROL_DIRECT 0x1811c408 ++#define CRU_control 0x1800e000 ++ ++#define NAND_nand_flash_REVISION 0x18046000 ++#define NAND_direct_read_rd_miss 0x18046f00 ++#define NAND_IDM_IDM_IO_CONTROL_DIRECT 0xf8105408 ++ ++#define ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL 0x18000c8c ++#define ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel 1 ++#define ICFG_IPROC_IOPAD_SW_OVERRIDE_CTRL__iproc_pnor_sel_sw_ovwr 0 ++#define ICFG_PNOR_STRAPS 0x18000a5c ++#define ICFG_PNOR_STRAPS__PNOR_SRAM_MW_R 0 ++#define PNOR_set_opmode 0x18045018 ++#define PNOR_set_opmode__set_mw_R 0 ++#define PNOR_direct_cmd 0x18045010 ++#define PNOR_direct_cmd__cmd_type_R 21 ++ ++#define ChipcommonG_tim0_TIM_TIMER1Load 0x18003000 ++#define ChipcommonG_tim1_TIM_TIMER1Load 0x18004000 ++#define ChipcommonG_tim2_TIM_TIMER1Load 0x18005000 ++#define ChipcommonG_tim3_TIM_TIMER1Load 0x18006000 ++ ++#define ChipcommonS_RNG_CTRL 0x18032000 ++ ++#define IHOST_S0_IDM_ERROR_LOG_CONTROL 0x18107900 ++#define IHOST_S0_IDM_ERROR_LOG_COMPLETE 0x18107904 ++#define IHOST_S0_IDM_ERROR_LOG_STATUS 0x18107908 ++#define IHOST_S0_IDM_ERROR_LOG_ADDR_LSB 0x1810790c ++#define IHOST_S0_IDM_ERROR_LOG_ID 0x18107914 ++#define IHOST_S0_IDM_ERROR_LOG_FLAGS 0x1810791c ++#define IHOST_S0_IDM_INTERRUPT_STATUS 0x18107a00 ++ ++#define IHOST_S1_IDM_ERROR_LOG_CONTROL 0x18106900 ++#define IHOST_S1_IDM_ERROR_LOG_COMPLETE 0x18106904 ++#define IHOST_S1_IDM_ERROR_LOG_STATUS 0x18106908 ++#define IHOST_S1_IDM_ERROR_LOG_ADDR_LSB 0x1810690c ++#define IHOST_S1_IDM_ERROR_LOG_ID 0x18106914 ++#define IHOST_S1_IDM_ERROR_LOG_FLAGS 0x1810691c ++#define IHOST_S1_IDM_INTERRUPT_STATUS 0x18106a00 ++ ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18108900 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18108904 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_STATUS 0x18108908 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810890c ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_ID 0x18108914 ++#define AXI_PCIE_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810891c ++#define AXI_PCIE_S0_IDM_IDM_INTERRUPT_STATUS 0x18108a00 ++ ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_CONTROL 0x18109900 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_COMPLETE 0x18109904 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_STATUS 0x18109908 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810990c ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_ID 0x18109914 ++#define AXI_PCIE_S1_IDM_IDM_ERROR_LOG_FLAGS 0x1810991c ++#define AXI_PCIE_S1_IDM_IDM_INTERRUPT_STATUS 0x18109a00 ++ ++#define CMICD_S0_IDM_IDM_ERROR_LOG_CONTROL 0x1810a900 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x1810a904 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_STATUS 0x1810a908 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1810a90c ++#define CMICD_S0_IDM_IDM_ERROR_LOG_ID 0x1810a914 ++#define CMICD_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1810a91c ++#define CMICD_S0_IDM_IDM_INTERRUPT_STATUS 0x1810aa00 ++ ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_CONTROL 0x18119900 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_COMPLETE 0x18119904 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_STATUS 0x18119908 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1811990c ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_ID 0x18119914 ++#define A9JTAG_S0_IDM_IDM_ERROR_LOG_FLAGS 0x1811991c ++#define A9JTAG_S0_IDM_IDM_INTERRUPT_STATUS 0x18119a00 ++ ++#define SRAM_S0_IDM_ERROR_LOG_CONTROL 0x1811b900 ++#define SRAM_S0_IDM_ERROR_LOG_COMPLETE 0x1811b904 ++#define SRAM_S0_IDM_ERROR_LOG_STATUS 0x1811b908 ++#define SRAM_S0_IDM_ERROR_LOG_ADDR_LSB 0x1811b90c ++#define SRAM_S0_IDM_ERROR_LOG_ID 0x1811b914 ++#define SRAM_S0_IDM_ERROR_LOG_FLAGS 0x1811b91c ++#define SRAM_S0_IDM_INTERRUPT_STATUS 0x1811ba00 ++ ++#define APBX_IDM_IDM_ERROR_LOG_CONTROL 0x18130900 ++#define APBX_IDM_IDM_ERROR_LOG_COMPLETE 0x18130904 ++#define APBX_IDM_IDM_ERROR_LOG_STATUS 0x18130908 ++#define APBX_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813090c ++#define APBX_IDM_IDM_ERROR_LOG_ID 0x18130914 ++#define APBX_IDM_IDM_ERROR_LOG_FLAGS 0x1813091c ++#define APBX_IDM_IDM_INTERRUPT_STATUS 0x18130a00 ++ ++#define APBY_IDM_IDM_ERROR_LOG_CONTROL 0x18131900 ++#define APBY_IDM_IDM_ERROR_LOG_COMPLETE 0x18131904 ++#define APBY_IDM_IDM_ERROR_LOG_STATUS 0x18131908 ++#define APBY_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813190c ++#define APBY_IDM_IDM_ERROR_LOG_ID 0x18131914 ++#define APBY_IDM_IDM_ERROR_LOG_FLAGS 0x1813191c ++#define APBY_IDM_IDM_INTERRUPT_STATUS 0x18131a00 ++ ++#define APBZ_IDM_IDM_ERROR_LOG_CONTROL 0x18132900 ++#define APBZ_IDM_IDM_ERROR_LOG_COMPLETE 0x18132904 ++#define APBZ_IDM_IDM_ERROR_LOG_STATUS 0x18132908 ++#define APBZ_IDM_IDM_ERROR_LOG_ADDR_LSB 0x1813290c ++#define APBZ_IDM_IDM_ERROR_LOG_ID 0x18132914 ++#define APBZ_IDM_IDM_ERROR_LOG_FLAGS 0x1813291c ++#define APBZ_IDM_IDM_INTERRUPT_STATUS 0x18132a00 ++ ++#define DDR_S1_IDM_ERROR_LOG_CONTROL 0xf8102900 ++#define DDR_S1_IDM_ERROR_LOG_COMPLETE 0xf8102904 ++#define DDR_S1_IDM_ERROR_LOG_STATUS 0xf8102908 ++#define DDR_S1_IDM_ERROR_LOG_ADDR_LSB 0xf810290c ++#define DDR_S1_IDM_ERROR_LOG_ID 0xf8102914 ++#define DDR_S1_IDM_ERROR_LOG_FLAGS 0xf810291c ++#define DDR_S1_IDM_INTERRUPT_STATUS 0xf8102a00 ++ ++#define DDR_S2_IDM_ERROR_LOG_CONTROL 0xf8103900 ++#define DDR_S2_IDM_ERROR_LOG_COMPLETE 0xf8103904 ++#define DDR_S2_IDM_ERROR_LOG_STATUS 0xf8103908 ++#define DDR_S2_IDM_ERROR_LOG_ADDR_LSB 0xf810390c ++#define DDR_S2_IDM_ERROR_LOG_ID 0xf8103914 ++#define DDR_S2_IDM_ERROR_LOG_FLAGS 0xf810391c ++#define DDR_S2_IDM_INTERRUPT_STATUS 0xf8103a00 ++ ++#define ROM_S0_IDM_ERROR_LOG_CONTROL 0xf8104900 ++#define ROM_S0_IDM_ERROR_LOG_COMPLETE 0xf8104904 ++#define ROM_S0_IDM_ERROR_LOG_STATUS 0xf8104908 ++#define ROM_S0_IDM_ERROR_LOG_ADDR_LSB 0xf810490c ++#define ROM_S0_IDM_ERROR_LOG_ID 0xf8104914 ++#define ROM_S0_IDM_ERROR_LOG_FLAGS 0xf810491c ++#define ROM_S0_IDM_INTERRUPT_STATUS 0xf8104a00 ++ ++#define NAND_IDM_IDM_ERROR_LOG_CONTROL 0xf8105900 ++#define NAND_IDM_IDM_ERROR_LOG_COMPLETE 0xf8105904 ++#define NAND_IDM_IDM_ERROR_LOG_STATUS 0xf8105908 ++#define NAND_IDM_IDM_ERROR_LOG_ADDR_LSB 0xf810590c ++#define NAND_IDM_IDM_ERROR_LOG_ID 0xf8105914 ++#define NAND_IDM_IDM_ERROR_LOG_FLAGS 0xf810591c ++#define NAND_IDM_IDM_INTERRUPT_STATUS 0xf8105a00 ++ ++#define QSPI_IDM_IDM_ERROR_LOG_CONTROL 0xf8106900 ++#define QSPI_IDM_IDM_ERROR_LOG_COMPLETE 0xf8106904 ++#define QSPI_IDM_IDM_ERROR_LOG_STATUS 0xf8106908 ++#define QSPI_IDM_IDM_ERROR_LOG_ADDR_LSB 0xf810690c ++#define QSPI_IDM_IDM_ERROR_LOG_ID 0xf8106914 ++#define QSPI_IDM_IDM_ERROR_LOG_FLAGS 0xf810691c ++#define QSPI_IDM_IDM_INTERRUPT_STATUS 0xf8106a00 ++ ++#define AXIIC_DS_0_IDM_ERROR_LOG_CONTROL 0x18120900 ++#define AXIIC_DS_0_IDM_ERROR_LOG_COMPLETE 0x18120904 ++#define AXIIC_DS_0_IDM_ERROR_LOG_STATUS 0x18120908 ++#define AXIIC_DS_0_IDM_ERROR_LOG_ADDR_LSB 0x1812090c ++#define AXIIC_DS_0_IDM_ERROR_LOG_ID 0x18120914 ++#define AXIIC_DS_0_IDM_ERROR_LOG_FLAGS 0x1812091c ++#define AXIIC_DS_0_IDM_INTERRUPT_STATUS 0x18120a00 ++ ++#define AXIIC_DS_1_IDM_ERROR_LOG_CONTROL 0x18121900 ++#define AXIIC_DS_1_IDM_ERROR_LOG_COMPLETE 0x18121904 ++#define AXIIC_DS_1_IDM_ERROR_LOG_STATUS 0x18121908 ++#define AXIIC_DS_1_IDM_ERROR_LOG_ADDR_LSB 0x1812190c ++#define AXIIC_DS_1_IDM_ERROR_LOG_ID 0x18121914 ++#define AXIIC_DS_1_IDM_ERROR_LOG_FLAGS 0x1812191c ++#define AXIIC_DS_1_IDM_INTERRUPT_STATUS 0x18121a00 ++ ++#define AXIIC_DS_2_IDM_ERROR_LOG_CONTROL 0x1811d900 ++#define AXIIC_DS_2_IDM_ERROR_LOG_COMPLETE 0x1811d904 ++#define AXIIC_DS_2_IDM_ERROR_LOG_STATUS 0x1811d908 ++#define AXIIC_DS_2_IDM_ERROR_LOG_ADDR_LSB 0x1811d90c ++#define AXIIC_DS_2_IDM_ERROR_LOG_ID 0x1811d914 ++#define AXIIC_DS_2_IDM_ERROR_LOG_FLAGS 0x1811d91c ++#define AXIIC_DS_2_IDM_INTERRUPT_STATUS 0x1811da00 ++ ++#define AXIIC_DS_3_IDM_ERROR_LOG_CONTROL 0x1811e900 ++#define AXIIC_DS_3_IDM_ERROR_LOG_COMPLETE 0x1811e904 ++#define AXIIC_DS_3_IDM_ERROR_LOG_STATUS 0x1811e908 ++#define AXIIC_DS_3_IDM_ERROR_LOG_ADDR_LSB 0x1811e90c ++#define AXIIC_DS_3_IDM_ERROR_LOG_ID 0x1811e914 ++#define AXIIC_DS_3_IDM_ERROR_LOG_FLAGS 0x1811e91c ++#define AXIIC_DS_3_IDM_INTERRUPT_STATUS 0x1811ea00 ++ ++/* GPIO */ ++#define ChipcommonG_GP_DATA_IN 0x1800a000 ++#define ChipcommonG_GP_DATA_IN_BASE 0x000 ++#define ChipcommonG_GP_DATA_OUT_BASE 0x004 ++#define ChipcommonG_GP_OUT_EN_BASE 0x008 ++#define ChipcommonG_GP_INT_TYPE_BASE 0x00c ++#define ChipcommonG_GP_INT_DE_BASE 0x010 ++#define ChipcommonG_GP_INT_EDGE_BASE 0x014 ++#define ChipcommonG_GP_INT_MSK_BASE 0x018 ++#define ChipcommonG_GP_INT_STAT_BASE 0x01c ++#define ChipcommonG_GP_INT_MSTAT_BASE 0x020 ++#define ChipcommonG_GP_INT_CLR_BASE 0x024 ++#define ChipcommonG_GP_AUX_SEL_BASE 0x028 ++#define ChipcommonG_GP_INIT_VAL_BASE 0x030 ++#define ChipcommonG_GP_PAD_RES_BASE 0x034 ++#define ChipcommonG_GP_RES_EN_BASE 0x038 ++#define ChipcommonG_GP_TEST_INPUT_BASE 0x03c ++#define ChipcommonG_GP_TEST_OUTPUT_BASE 0x040 ++#define ChipcommonG_GP_TEST_ENABLE_BASE 0x044 ++#define ChipcommonG_GP_PRB_ENABLE_BASE 0x048 ++#define ChipcommonG_GP_PRB_OE_BASE 0x04c ++ ++/* Watchdog */ ++#define ChipcommonG_WDT_WDOGLOAD 0x18009000 ++#define DMU_PCU_CRU_RESET_REASON 0x1800f014 ++#define DMU_PCU_CRU_RESET_REASON__watchdog_reset 0 ++ ++#endif /* __SOCREGS_P7_OPEN_H */ +diff --git a/arch/arm/mach-iproc/include/mach/vmalloc.h b/arch/arm/mach-iproc/include/mach/vmalloc.h +new file mode 100644 +index 0000000..0611b30 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch new file mode 100644 index 00000000..94925e96 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_include_mach_vmalloc.h.patch @@ -0,0 +1,30 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/include/mach/vmalloc.h +@@ -0,0 +1,24 @@ ++/* ++ * arch/arm/mach-iproc/include/mach/vmalloc.h ++ * ++ * Copyright (C) 2014 ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifdef __ASSEMBLY__ ++#define VMALLOC_END 0xff000000 ++#else ++#define VMALLOC_END 0xff000000UL ++#endif +diff --git a/arch/arm/mach-iproc/io_map.c b/arch/arm/mach-iproc/io_map.c +new file mode 100644 +index 0000000..cbea0a2 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch new file mode 100644 index 00000000..8a1283a1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_io_map.c.patch @@ -0,0 +1,63 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/io_map.c +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define IO_DESC(va, sz) { .virtual = va, \ ++ .pfn = __phys_to_pfn(HW_IO_VIRT_TO_PHYS(va)), \ ++ .length = sz, \ ++ .type = MT_DEVICE } ++ ++ ++static struct map_desc northstar_io_desc[] __initdata = ++{ ++ IO_DESC(IO_CORE_IDM_VA,IO_CORE_IDM_SIZE), ++ IO_DESC(IO_ARMCORE_VA, IO_ARMCORE_SIZE), ++#ifdef CONFIG_MACH_IPROC_P7 ++ IO_DESC(IO_SMAU_IDM_VA, IO_SMAU_IDM_SIZE), ++#endif /* !CONFIG_MACH_IPROC_P7 */ ++}; ++ ++extern void __init iproc_map_io(void); ++ ++void __init northstar_map_io(void) ++{ ++ iotable_init(northstar_io_desc, ARRAY_SIZE(northstar_io_desc)); ++} +diff --git a/arch/arm/mach-iproc/localtimer.c b/arch/arm/mach-iproc/localtimer.c +new file mode 100644 +index 0000000..b139cac diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch new file mode 100644 index 00000000..5294b538 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_localtimer.c.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/localtimer.c +@@ -0,0 +1,27 @@ ++/* ++ * linux/arch/arm/mach-iproc/localtimer.c ++ * ++ * Copyright (C) 2002 ARM Ltd. ++ * All Rights Reserved ++ * ++ * 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 ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * Setup the local clock events for a CPU. ++ */ ++int __cpuinit local_timer_setup(struct clock_event_device *evt) ++{ ++ evt->irq = IRQ_LOCALTIMER; ++ twd_timer_setup(evt); ++ return 0; ++} +diff --git a/arch/arm/mach-iproc/northstar.c b/arch/arm/mach-iproc/northstar.c +new file mode 100644 +index 0000000..dc23a34 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch new file mode 100644 index 00000000..9ed0bde4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.c.patch @@ -0,0 +1,172 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/northstar.c +@@ -0,0 +1,166 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++ ++ ++ ++#define TIMER_LOAD 0x00 ++#define TIMER_VALUE 0x04 ++#define TIMER_CTRL 0x08 ++#define TIMER_CTRL_PRESC_SHFT (8) ++#define TIMER_CTRL_IE (1 << 2) ++#define TIMER_CTRL_PERIODIC (1 << 1) ++#define TIMER_CTRL_ENABLE (1 << 0) ++ ++#define TIMER_INTCLR 0x0c ++#define IPROC_L2CC_REG_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_L2CC_REG_BASE) ++ ++extern void __iomem *twd_base; ++extern void iproc_clocksource_init(void __iomem *); ++extern void iproc_clockevents_init(void __iomem *, unsigned int); ++extern void __init northstar_dmu_init(struct clk *clk_ref); ++extern void __init iproc_cru_init(struct clk *clk_ref); ++extern void iproc_enable_data_prefetch_aborts(void); ++extern void northstar_restart(char mode, const char *cmd); ++ ++static void ++northstar_poweroff(void) ++{ ++ while(1) ++ ; ++} ++ ++ ++#ifdef CONFIG_CACHE_L2X0 ++static void __init northstar_l2x0_init(void) ++{ ++ void __iomem *l2cache_base = IOMEM(IPROC_L2CC_REG_VA); ++ void __iomem *cca = IOMEM(IPROC_CCA_CORE_REG_VA); ++ unsigned int chipid = (readl(cca) & 0x0000ffff); ++ ++ /* ++ * 16KB way size, 16-way associativity ++ */ ++#if defined(CONFIG_MACH_NS) ++ if (chipid >= 0xcf19 /* costar */) { ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ /* inst/data prefetch & Early BRESP & Fill line zero (also need A9) */ ++ l2x0_init(l2cache_base, (0x0A150000 | 0x3 << 28 | 0x1 << 30 | 0x1 << 0), ~(0x000F0000)); ++#else ++ l2x0_init(l2cache_base, 0x0A150000, ~(0x000F0000)); ++#endif /* CONFIG_BCM_IPROC_CA9_PREFETCH */ ++ } else { /* northstar */ ++ l2x0_init(l2cache_base, 0x0A130000, ~(0x000F0000)); ++ } ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ l2x0_init(l2cache_base, 0x0A150000, ~(0x000F0000)); ++#elif defined(CONFIG_MACH_HR2) ++ l2x0_init(l2cache_base, 0x0A120000, ~(0x000F0000)); ++#elif defined(CONFIG_MACH_NSP) ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ /* inst/data prefetch & Early BRESP & Fill line zero (also need A9) */ ++ l2x0_init(l2cache_base, (0x0A150000 | 0x3 << 28 | 0x1 << 30 | 0x1 << 0), ~(0x000F0000)); ++#else ++ l2x0_init(l2cache_base, 0x0A150000, ~(0x000F0000)); ++#endif /* CONFIG_BCM_IPROC_CA9_PREFETCH */ ++#elif defined(CONFIG_MACH_IPROC_P7) ++ l2x0_init(l2cache_base, 0x0A130000, ~(0x000F0000)); ++#endif ++} ++#endif ++ ++static int __init northstar_init(void) ++{ ++#ifdef CONFIG_PM ++ pm_power_off = northstar_poweroff; ++#endif ++ arm_pm_restart = northstar_restart; ++ ++#ifdef CONFIG_MACH_CYGNUS ++#else ++#ifdef CONFIG_CACHE_L2X0 ++ northstar_l2x0_init(); ++#endif ++#endif /* END of CYGNUS */ ++ ++ return 0; ++} ++early_initcall(northstar_init); ++ ++/* ++ * CPU global and MPCORE Per CPU local timer ++ */ ++#define GLB_TIMER IOMEM(IPROC_PERIPH_GLB_TIM_REG_VA); ++#define PVT_TIMER IOMEM(IPROC_PERIPH_PVT_TIM_REG_VA); ++ ++void __iomem *gtimer_va_base = GLB_TIMER; ++void __iomem *ptimer_va_base = PVT_TIMER; ++ ++/* ++ * Set up the clock source and clock events devices ++ */ ++void __init northstar_timer_init(struct clk *clk_ref) ++{ ++ int err; ++ ++ /* ++ * Setup DMU and CRU early ++ */ ++ northstar_dmu_init(clk_ref); ++ iproc_cru_init(clk_ref); ++ ++ /* ++ * Initialise to a known state (all timers off) ++ */ ++ writel(0, ptimer_va_base + TIMER_CTRL); ++ writel(0, gtimer_va_base + TIMER_CTRL); ++ ++#ifdef CONFIG_HAVE_ARM_TWD ++ /* ++ * Setup the local clock events for a CPU. ++ */ ++ twd_base = IO_ADDRESS(IPROC_PERIPH_PVT_TIM_REG_VA); ++#endif ++ ++ iproc_clocksource_init(gtimer_va_base); ++ iproc_clockevents_init(gtimer_va_base, BCM_INT_ID_PPI11); ++ ++ iproc_enable_data_prefetch_aborts(); ++} +diff --git a/arch/arm/mach-iproc/northstar.h b/arch/arm/mach-iproc/northstar.h +new file mode 100644 +index 0000000..09b3ccc diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch new file mode 100644 index 00000000..eb6fa038 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar.h.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/northstar.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __NORTHSTAR_H ++#define __NORTHSTAR_H ++ ++#include ++#include ++ ++extern struct platform_device northstar_ipc_device; ++ ++void __init northstar_map_io(void); ++ ++#endif /* __NORTHSTAR_H */ +diff --git a/arch/arm/mach-iproc/northstar_dmu.c b/arch/arm/mach-iproc/northstar_dmu.c +new file mode 100644 +index 0000000..f95b0e3 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch new file mode 100644 index 00000000..02de3943 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_northstar_dmu.c.patch @@ -0,0 +1,808 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/northstar_dmu.c +@@ -0,0 +1,802 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define IPROC_DMU_BASE_PA IPROC_DMU_BASE_REG ++//#define IPROC_DMU_BASE_VA HW_IO_PHYS_TO_VIRT(IPROC_DMU_BASE_PA) ++ ++static struct resource dmu_regs = { ++ .name = "dmu_regs", ++ .start = (resource_size_t) IOMEM(IPROC_DMU_BASE_VA), ++ .end = (resource_size_t) (IOMEM(IPROC_DMU_BASE_VA) + SZ_4K - 1), ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * Clock management scheme is a provisional implementation ++ * only intended to retreive the pre-set frequencies for each ++ * of the clocks. ++ * Better handling of post-dividers and fractional part of ++ * feedbeck dividers need to be added. ++ * Need to understand what diagnostics from CRU registers could ++ * be handy, and export that via a sysfs interface. ++ */ ++ ++/* ++ * The CRU contains two similar PLLs: LCPLL and GENPLL, ++ * both with several output channels divided from the PLL ++ * output ++ */ ++ ++/* ++ * Get PLL running status and update output frequency ++ */ ++static int lcpll_status(struct clk * clk) ++{ ++ u32 reg; ++ u64 x; ++ unsigned pdiv, ndiv_int, ndiv_frac; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ /* read status register */ ++ reg = readl(clk->regs_base + 0x10); ++ ++ /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ ++ if ((reg & (1 << 12)) == 0) { ++ clk->rate = 0; ++ } ++ ++ /* Update PLL frequency */ ++ ++ /* control1 register */ ++ reg = readl(clk->regs_base + 0x04); ++ ++ /* feedback divider integer and fraction parts */ ++ pdiv = (reg >> 28) & 7 ; ++ ndiv_int = (reg >> 20) & 0xff; ++ ndiv_frac = reg & ((1<<20)-1); ++ ++ if (pdiv == 0) ++ return -EIO; ++ ++ x = clk->parent->rate / pdiv ; ++ ++ x = x * ((u64) ndiv_int << 20 | ndiv_frac) ; ++ ++ clk->rate = x >> 20 ; ++ ++ return 0; ++} ++ ++static const struct clk_ops lcpll_ops = { ++ .status = lcpll_status, ++}; ++ ++static int lcpll_chan_status(struct clk * clk) ++{ ++ void * __iomem base; ++ u32 reg; ++ unsigned enable; ++ unsigned mdiv; ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* Register address is only stored in PLL structure */ ++ base = clk->parent->regs_base; ++ BUG_ON(base == NULL); ++ ++ /* enable bit is in enableb_ch[] inversed */ ++ enable = ((readl(base + 0) >> 6) & 7) ^ 7; ++ ++ if (0 == (enable & (1 << clk->chan))) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* get divider */ ++ reg = readl(base + 0x08); ++ ++ mdiv = 0xff & (reg >> ((0x3^clk->chan) << 3)); ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("LCPLL[%d] mdiv=%u rate=%lu\n", clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = (clk->parent->rate / mdiv); ++ return 0; ++} ++ ++ ++static const struct clk_ops lcpll_chan_ops = { ++ .status = lcpll_chan_status, ++}; ++ ++/* ++ * LCPLL has 4 output channels ++ */ ++static struct clk clk_lcpll = { ++ .ops = &lcpll_ops, ++ .name = "LCPLL", ++ .type = CLK_PLL, ++ .chan = 4, ++}; ++ ++/* ++ * LCPLL output clocks - ++ * chan 0 - PCIe ref clock, should be 1 GHz, ++ * chan 1 - SDIO clock, e.g. 200 MHz, ++ * chan 2 - DDR clock, typical 166.667 MHz for DDR667, ++ * chan 3 - Unknown ++ */ ++ ++static struct clk clk_lcpll_ch[4] = { ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch0", ++ .chan = 0, ++ }, ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch1", ++ .chan = 1, ++ }, ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch2", ++ .chan = 2, ++ }, ++ { ++ .ops = &lcpll_chan_ops, ++ .parent = &clk_lcpll, ++ .type = CLK_DIV, ++ .name = "lcpll_ch3", ++ .chan = 3, ++ }, ++}; ++ ++/* ++ * Get PLL running status and update output frequency ++ */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++static int genpll_status(struct clk * clk) ++{ ++ u32 reg; ++ u64 x; ++ unsigned pdiv; ++ unsigned ndiv_int; ++ unsigned ndiv_frac; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ /* Offset of the PLL status register */ ++ reg = readl(clk->regs_base + 0x20); ++ ++ /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ ++ if((reg & (1 << 12)) == 0) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* Update PLL frequency */ ++ ++ /* get PLL feedback divider values from control5 */ ++ reg = readl(clk->regs_base + 0x14); ++ ++ /* feedback divider integer and fraction parts */ ++ ndiv_int = reg >> 20; ++ ndiv_frac = reg & ((1 << 20) - 1); ++ ++ /* get pdiv */ ++ reg = readl(clk->regs_base + 0x18); ++ pdiv = (reg >> 24) & 7; ++ ++ if (pdiv == 0) ++ return -EIO; ++ ++ x = clk->parent->rate / pdiv; ++ ++ x = x * ((u64) ndiv_int << 20 | ndiv_frac); ++ ++ clk->rate = x >> 20; ++ ++ return 0; ++} ++#endif ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++static int genpll_status(struct clk * clk) ++{ ++ u32 reg; ++ u64 x; ++ unsigned pdiv; ++ unsigned ndiv_int; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ /* Offset of the PLL status register */ ++ reg = readl(clk->regs_base + 0x18); ++ ++ /* bit 12 is "lock" signal, has to be "1" for proper PLL operation */ ++ if((reg & (1 << IPROC_WRAP_GEN_PLL_STATUS__GEN_PLL_LOCK)) == 0) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* Update PLL frequency */ ++ ++ /* get PLL feedback divider values from control5 */ ++ reg = readl(clk->regs_base + 0x04); ++ ++ /* feedback divider integer and fraction parts */ ++ ndiv_int = (reg >> IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_R) & ((1 << IPROC_WRAP_GEN_PLL_CTRL1__NDIV_INT_WIDTH) -1); ++ ++ /* get pdiv */ ++ pdiv = (reg >> IPROC_WRAP_GEN_PLL_CTRL1__PDIV_R) & ((1 << IPROC_WRAP_GEN_PLL_CTRL1__PDIV_WIDTH) -1); ++ ++ if (pdiv == 0) ++ return -EIO; ++ ++ x = clk->parent->rate / pdiv; ++ ++ x = x * ((u64) ndiv_int); ++ ++ clk->rate = x; ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_KT2) ++static int genpll_status(struct clk * clk) ++{ ++ clk->rate = 2475000000; ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_CYGNUS) //chandra: todo ++static int genpll_status(struct clk * clk) ++{ ++ ++} ++#endif ++static const struct clk_ops genpll_ops = { ++ .status = genpll_status, ++}; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++static int genpll_chan_status(struct clk * clk) ++{ ++ void * __iomem base; ++ u32 reg; ++ unsigned enable; ++ unsigned mdiv; ++ unsigned off, shift; ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* Register address is only stored in PLL structure */ ++ base = clk->parent->regs_base; ++ ++ BUG_ON (base == NULL); ++ ++ /* enable bit is in enableb_ch[0..5] inversed */ ++ enable = ((readl(base + 0x04) >> 12) & 0x3f) ^ 0x3f ; ++ ++ if (0 == (enable & (1 << clk->chan))) { ++ clk->rate = 0; ++ return -EIO; ++ } ++ ++ /* GENPLL has the 6 channels spread over two regs */ ++ switch (clk->chan) { ++ case 0: ++ off = 0x18; shift = 16; ++ break; ++ ++ case 1: ++ off = 0x18; shift = 8; ++ break; ++ ++ case 2: ++ off = 0x18; shift = 0; ++ break; ++ ++ case 3: ++ off = 0x1c; shift = 16; ++ break; ++ ++ case 4: ++ off = 0x1c; shift = 8; ++ break; ++ ++ case 5: ++ off = 0x1c; shift = 16; /* Set to AXI clock */ ++ break; ++ ++ default: ++ BUG_ON(clk->chan); ++ off = shift = 0; /* fend off warnings */ ++ } ++ ++ reg = readl(base + off); ++ ++ mdiv = 0xff & (reg >> shift); ++ /* APB clock is always AXIclock/4 */ ++ if(clk->chan == 5) ++ mdiv = mdiv * 4; ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("GENPLL[%d] mdiv=%u rate=%lu\n", ++ clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = clk->parent->rate / mdiv; ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++static int genpll_chan_status(struct clk * clk) ++{ ++ void * __iomem base; ++ u32 reg; ++ unsigned enable; ++ unsigned mdiv = 0; ++ unsigned off, shift; ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* Register address is only stored in PLL structure */ ++ base = clk->parent->regs_base; ++ ++ BUG_ON (base == NULL); ++ /* GENPLL has the 6 channels spread over two regs */ ++ switch (clk->chan) { ++ case 0: ++ off = 0x04; shift = IPROC_WRAP_GEN_PLL_CTRL1__CH0_MDIV_R; ++ break; ++ ++ case 1: ++ off = 0x04; shift = IPROC_WRAP_GEN_PLL_CTRL1__CH1_MDIV_R; ++ break; ++ ++ case 2: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH2_MDIV_R; ++ break; ++ ++ case 3: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R; ++ break; ++ ++ case 4: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH4_MDIV_R; ++ break; ++ ++ case 5: ++ off = 0x08; shift = IPROC_WRAP_GEN_PLL_CTRL2__CH3_MDIV_R; ++ break; ++ ++ default: ++ BUG_ON(clk->chan); ++ off = shift = 0; /* fend off warnings */ ++ } ++ ++ reg = readl(base + off); ++ ++ mdiv = 0xff & (reg >> shift); ++ if(clk->chan == 5) ++ mdiv *= 4; ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("GENPLL[%d] mdiv=%u rate=%lu\n", ++ clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = clk->parent->rate / mdiv; ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_KT2) ++static int genpll_chan_status(struct clk * clk) ++{ ++ unsigned mdiv = 0; ++ ++ ++ if (clk->parent == NULL || clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ /* GENPLL has the 6 channels spread over two regs */ ++ switch (clk->chan) { ++ case 0: ++ mdiv = 10; ++ break; ++ ++ case 3: ++ mdiv = 5; ++ break; ++ ++ case 4: ++ mdiv = 10; ++ break; ++ ++ case 5: ++ mdiv = 5; ++ break; ++ ++ default: ++ BUG_ON(clk->chan); ++ } ++ ++ if(clk->chan == 5) ++ mdiv *= 4; ++ ++ /* when divisor is 0, it behaves as max+1 */ ++ if (mdiv == 0) ++ mdiv = 1 << 8; ++ ++ printk("GENPLL[%d] mdiv=%u rate=%lu\n", ++ clk->chan, mdiv, clk->parent->rate); ++ ++ clk->rate = clk->parent->rate / mdiv; ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_MACH_CYGNUS) //chandra: todo ++static int genpll_chan_status(struct clk * clk) ++{ ++ ++} ++#endif ++ ++static const struct clk_ops genpll_chan_ops = { ++ .status = genpll_chan_status, ++}; ++ ++ ++/* ++ * GENPLL has 6 output channels ++ */ ++static struct clk clk_genpll = { ++ .ops = &genpll_ops, ++ .name = "GENPLL", ++ .type = CLK_PLL, ++ .chan = 6, ++}; ++ ++/* ++ * chan 0 - Ethernet switch and MAC, RGMII, need 250 MHz ++ * chan 1 - Ethernet switch slow clock, 150 Mhz ++ * chan 2 - USB PHY clock, need 30 MHz ++ * chan 3 - iProc N MHz clock, set from OTP ++ * chan 4 - iProc N/2 MHz clock, set from OTP ++ * chan 5 - iProc N/4 MHz clock, set from OTP ++ * ++ * To Do: which clock goes to MPCORE PERIPHCLOCK? ++ */ ++#ifdef CONFIG_MACH_CYGNUS_EMULATION //chandra:emul ++ static struct clk clk_genpll_ch[6] = { ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .type = CLK_DIV, ++ .name = "genpll_ch0", ++ .chan = 0, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .type = CLK_DIV, ++ .name = "genpll_ch1", ++ .chan = 1, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .type = CLK_DIV, ++ .name = "genpll_ch2", ++ .chan = 2, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .rate = 992000, ++ .type = CLK_DIV, ++ .name = "genpll_ch3", ++ .chan = 3, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .rate = 644800, ++ .type = CLK_DIV, ++ .name = "genpll_ch4", ++ .chan = 4, ++ }, ++ { ++ .ops = NULL, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_CLK_125,//25000000, ++ .type = CLK_DIV, ++ .name = "genpll_ch5", ++ .chan = 5, ++ }, ++ }; ++ ++#else ++static struct clk clk_genpll_ch[6] = { ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch0", ++ .chan = 0, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch1", ++ .chan = 1, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch2", ++ .chan = 2, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch3", ++ .chan = 3, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch4", ++ .chan = 4, ++ }, ++ { ++ .ops = &genpll_chan_ops, ++ .parent = &clk_genpll, ++ .type = CLK_DIV, ++ .name = "genpll_ch5", ++ .chan = 5, ++ }, ++}; ++#endif ++ ++/* ++ * This table is used to locate clock sources ++ * from device drivers ++ */ ++ ++static struct clk_lookup ns_clk_lookups[] = { ++ { ++ .dev_id = "pcie", ++ .con_id = "c_clk100", ++ .clk = &clk_lcpll_ch[0], ++ },{ ++ .dev_id = "sdio", ++ .con_id = "c_clk200", ++ .clk = &clk_lcpll_ch[1], ++ },{ ++ .dev_id = "ddr", ++ .con_id = "c_clk400", ++ .clk = &clk_lcpll_ch[2], ++ },{ ++ .dev_id = "tbd", ++ .con_id = "c_clk120", ++ .clk = &clk_lcpll_ch[3], ++ },{ ++ .dev_id = "en_phy", ++ .con_id = "c_clk250", ++ .clk = &clk_genpll_ch[0], ++ },{ ++ .dev_id = "en", ++ .con_id = "c_clk150", ++ .clk = &clk_genpll_ch[1], ++ },{ ++ .dev_id = "usb_phy", ++ .con_id = "c_clk30", ++ .clk = &clk_genpll_ch[2], ++ },{ ++ .dev_id = "iproc_fast", ++ .con_id = "c_clk500", ++ .clk = &clk_genpll_ch[3], ++ },{ ++ .dev_id = "iproc_med", ++ .con_id = "c_clk250", ++ .clk = &clk_genpll_ch[4], ++ },{ ++ .dev_id = "iproc_slow", ++ .con_id = "c_clk125", ++ .clk = &clk_genpll_ch[5], ++ } ++#ifdef CONFIG_ARM_AMBA ++ ,{ ++ .con_id = "apb_pclk", ++ .clk = &clk_genpll_ch[5], ++ } ++#if defined (CONFIG_ARM_SP805_WATCHDOG) || defined(CONFIG_ARM_SP805_WATCHDOG_MODULE) ++ ,{ ++ .dev_id = "sp805-wdt", ++ .clk = &clk_genpll_ch[5], ++ } ++#endif ++#endif ++}; ++ ++/* ++ * Install above clocks into clock lookup table ++ * and initialize the register base address for each ++*/ ++static void __init northstar_clocks_init(void *__iomem cru_regs_base, ++ struct clk * clk_ref) ++{ ++ /* ++ * Registers are already mapped with the rest of DMU block ++ * Update register base address ++ */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ clk_lcpll.regs_base = cru_regs_base + 0x00 ; ++ clk_genpll.regs_base = cru_regs_base + 0x40 ; ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ clk_lcpll.regs_base = cru_regs_base + 0x1c ; ++ clk_genpll.regs_base = cru_regs_base + 0x00 ; ++#endif ++ ++ /* Set parent as reference ckock */ ++ clk_lcpll.parent = clk_ref; ++ clk_genpll.parent = clk_ref; ++ ++ /* Install clock sources into the lookup table */ ++ clkdev_add_table(ns_clk_lookups, ++ ARRAY_SIZE(ns_clk_lookups)); ++} ++ ++void __init northstar_dmu_init(struct clk *clk_ref) ++{ ++ void * __iomem reg_base; ++ ++ if (IS_ERR_OR_NULL(clk_ref )) { ++ printk(KERN_ERR "CRU no clock source - skip init\n"); ++ return; ++ } ++ ++ BUG_ON (request_resource(&iomem_resource, &dmu_regs)); ++ ++ /* DMU regs are mapped as part of the fixed mapping with CCA+CCB */ ++ reg_base = (void * __iomem) dmu_regs.start; ++ ++ BUG_ON (IS_ERR_OR_NULL(reg_base)); ++ ++ /* Initialize clocks */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ northstar_clocks_init(reg_base + 0x100, clk_ref); /* CRU LCPLL control0 */ ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || \ ++ defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ northstar_clocks_init(reg_base + 0xc00, clk_ref); /* IPROC_WRAP_GEN_PLL_CTRL0 */ ++#elif defined(CONFIG_MACH_KT2) ++ northstar_clocks_init(NULL, clk_ref); /* IPROC_WRAP_GEN_PLL_CTRL0 */ ++#endif ++} ++ ++void (*cpld_system_reset)(void); ++EXPORT_SYMBOL(cpld_system_reset); /* used in dni_3448p_cpld.c module */ ++ ++/* ++ * Reset the system ++ */ ++void northstar_restart(char mode, const char *cmd) ++{ ++ void * __iomem reg_addr; ++ u32 reg; ++ ++ if (cpld_system_reset) { ++ printk( KERN_INFO "Using CPLD reset\n"); ++ cpld_system_reset(); ++ } ++ ++ /* CRU_RESET register */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ reg_addr = (void * __iomem) dmu_regs.start + 0x184 ; ++ /* set iproc_reset_n to 0, it may come back or not ... TBD */ ++ reg = readl_relaxed(reg_addr); ++ reg &= ~((u32) 1 << 1); ++ writel_relaxed(reg, reg_addr); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_KT2) \ ++ || defined(CONFIG_MACH_GH) || defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++ reg_addr = (void * __iomem) dmu_regs.start + DMU_CRU_RESET_BASE ; ++ /* Reset iproc and cmicd/switch */ ++ writel_relaxed(0, reg_addr); ++#endif ++ ++ ++} ++ ++ ++ ++ ++ ++ ++ ++void northstar_clocks_show( void ) ++{ ++ unsigned i; ++// struct clk * clk ; ++ ++ printk("=========== CLOCKS =================\n"); ++ ++ printk( "DMU Clocks:\n" ); ++ for (i = 0; i < ARRAY_SIZE( ns_clk_lookups); i++) { ++ printk("%s, %s: (%s) %lu\n", ++ ns_clk_lookups[i].con_id, ++ ns_clk_lookups[i].dev_id, ++ ns_clk_lookups[i].clk->name, ++ clk_get_rate( ns_clk_lookups[i].clk)); ++ } ++ printk( "DMU Clocks# %u\n", i ); ++} +diff --git a/arch/arm/mach-iproc/pm.c b/arch/arm/mach-iproc/pm.c +new file mode 100644 +index 0000000..ca2eef4 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch new file mode 100644 index 00000000..8c902f15 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mach-iproc_pm.c.patch @@ -0,0 +1,45 @@ +--- /dev/null ++++ b/arch/arm/mach-iproc/pm.c +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++int iproc_arm_cpu_do_idle(void) ++{ ++ return cpu_do_idle(); ++} ++EXPORT_SYMBOL(iproc_arm_cpu_do_idle); ++ ++inline void iproc_arm_cpu_resume(void) ++{ ++ cpu_resume(); ++} ++EXPORT_SYMBOL(iproc_arm_cpu_resume); ++ ++int iproc_arm_cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ++{ ++ return cpu_suspend(arg, fn); ++} ++EXPORT_SYMBOL(iproc_arm_cpu_suspend); +diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h +index ffb9d6a..6ec5258 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch new file mode 100644 index 00000000..d29ac419 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_Kconfig.patch @@ -0,0 +1,14 @@ +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -821,7 +821,8 @@ config CACHE_L2X0 + REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \ + ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \ + ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \ +- ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK ++ ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK || \ ++ ARCH_IPROC + default y + select OUTER_CACHE + select OUTER_CACHE_SYNC +diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c +index cc3f35d..ee3a9f1 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch new file mode 100644 index 00000000..0be49e07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_init.c.patch @@ -0,0 +1,13 @@ +--- a/arch/arm/mm/init.c ++++ b/arch/arm/mm/init.c +@@ -406,8 +406,6 @@ void __init bootmem_init(void) + */ + arm_bootmem_free(min, max_low, max_high); + +- high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1; +- + /* + * This doesn't seem to be used by the Linux memory manager any + * more, but is used by ll_rw_block. If we can get rid of it, we +diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c +index bdb248c..0bf7e90 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch new file mode 100644 index 00000000..c3e4590f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_ioremap.c.patch @@ -0,0 +1,131 @@ +--- a/arch/arm/mm/ioremap.c ++++ b/arch/arm/mm/ioremap.c +@@ -36,12 +36,6 @@ + #include + #include "mm.h" + +-/* +- * Used by ioremap() and iounmap() code to mark (super)section-mapped +- * I/O regions in vm_struct->flags field. +- */ +-#define VM_ARM_SECTION_MAPPING 0x80000000 +- + int ioremap_page(unsigned long virt, unsigned long phys, + const struct mem_type *mtype) + { +@@ -201,12 +195,6 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, + if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) + return NULL; + +- /* +- * Don't allow RAM to be mapped - this causes problems with ARMv6+ +- */ +- if (WARN_ON(pfn_valid(pfn))) +- return NULL; +- + type = get_mem_type(mtype); + if (!type) + return NULL; +@@ -216,6 +204,38 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, + */ + size = PAGE_ALIGN(offset + size); + ++ /* ++ * Try to reuse one of the static mapping whenever possible. ++ */ ++ read_lock(&vmlist_lock); ++ for (area = vmlist; area; area = area->next) { ++ if (!size || (sizeof(phys_addr_t) == 4 && pfn >= 0x100000)) ++ break; ++ if (!(area->flags & VM_ARM_STATIC_MAPPING)) ++ continue; ++ if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype)) ++ continue; ++ if (__phys_to_pfn(area->phys_addr) > pfn || ++ __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1) ++ continue; ++ /* we can drop the lock here as we know *area is static */ ++ read_unlock(&vmlist_lock); ++ addr = (unsigned long)area->addr; ++ addr += __pfn_to_phys(pfn) - area->phys_addr; ++ return (void __iomem *) (offset + addr); ++ } ++ read_unlock(&vmlist_lock); ++ ++ /* ++ * Don't allow RAM to be mapped - this causes problems with ARMv6+ ++ */ ++#ifdef CONFIG_ARCH_IPROC ++#warning "ioremap test for remapping RAM has been disabled for IPROC" ++#else ++ if (WARN_ON(pfn_valid(pfn))) ++ return NULL; ++#endif ++ + area = get_vm_area_caller(size, VM_IOREMAP, caller); + if (!area) + return NULL; +@@ -313,29 +333,43 @@ __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached) + void __iounmap(volatile void __iomem *io_addr) + { + void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); +-#ifndef CONFIG_SMP +- struct vm_struct **p, *tmp; ++ struct vm_struct *vm; + +- /* +- * If this is a section based mapping we need to handle it +- * specially as the VM subsystem does not know how to handle +- * such a beast. We need the lock here b/c we need to clear +- * all the mappings before the area can be reclaimed +- * by someone else. +- */ +- write_lock(&vmlist_lock); +- for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { +- if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { +- if (tmp->flags & VM_ARM_SECTION_MAPPING) { +- unmap_area_sections((unsigned long)tmp->addr, +- tmp->size); +- } ++ read_lock(&vmlist_lock); ++ for (vm = vmlist; vm; vm = vm->next) { ++ if (vm->addr > addr) ++ break; ++ if (!(vm->flags & VM_IOREMAP)) ++ continue; ++ /* If this is a static mapping we must leave it alone */ ++ if ((vm->flags & VM_ARM_STATIC_MAPPING) && ++ (vm->addr <= addr) && (vm->addr + vm->size > addr)) { ++ read_unlock(&vmlist_lock); ++ return; ++ } ++#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) ++ /* ++ * If this is a section based mapping we need to handle it ++ * specially as the VM subsystem does not know how to handle ++ * such a beast. ++ */ ++ if ((vm->addr == addr) && ++ (vm->flags & VM_ARM_SECTION_MAPPING)) { ++ unmap_area_sections((unsigned long)vm->addr, vm->size); + break; + } +- } +- write_unlock(&vmlist_lock); + #endif ++ } ++ read_unlock(&vmlist_lock); + + vunmap(addr); + } ++ ++void (*arch_iounmap)(volatile void __iomem *) = __iounmap; ++ ++void __arm_iounmap(volatile void __iomem *io_addr) ++{ ++ arch_iounmap(io_addr); ++} + EXPORT_SYMBOL(__iounmap); ++EXPORT_SYMBOL(__arm_iounmap); +diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h +index ad7cce3..70f6d3ea 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch new file mode 100644 index 00000000..df2243fa --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mm.h.patch @@ -0,0 +1,25 @@ +--- a/arch/arm/mm/mm.h ++++ b/arch/arm/mm/mm.h +@@ -21,6 +21,20 @@ const struct mem_type *get_mem_type(unsigned int type); + + extern void __flush_dcache_page(struct address_space *mapping, struct page *page); + ++/* ++ * ARM specific vm_struct->flags bits. ++ */ ++ ++/* (super)section-mapped I/O regions used by ioremap()/iounmap() */ ++#define VM_ARM_SECTION_MAPPING 0x80000000 ++ ++/* permanent static mappings from iotable_init() */ ++#define VM_ARM_STATIC_MAPPING 0x40000000 ++ ++/* mapping type (attributes) for permanent static mappings */ ++#define VM_ARM_MTYPE(mt) ((mt) << 20) ++#define VM_ARM_MTYPE_MASK (0x1f << 20) ++ + #endif + + #ifdef CONFIG_ZONE_DMA +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 44b628e..ce8cb19 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch new file mode 100644 index 00000000..dbb38afa --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmap.c.patch @@ -0,0 +1,204 @@ +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -11,10 +11,49 @@ + #include + #include + ++static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr, ++ unsigned long pgoff) ++{ ++ unsigned long base = addr & ~(SHMLBA-1); ++ unsigned long off = (pgoff << PAGE_SHIFT) & (SHMLBA-1); ++ ++ if (base + off <= addr) ++ return base + off; ++ ++ return base - off; ++} ++ + #define COLOUR_ALIGN(addr,pgoff) \ + ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ + (((pgoff)<personality & ADDR_COMPAT_LAYOUT) ++ return 1; ++ ++ if (rlimit(RLIMIT_STACK) == RLIM_INFINITY) ++ return 1; ++ ++ return sysctl_legacy_va_layout; ++} ++ ++static unsigned long mmap_base(unsigned long rnd) ++{ ++ unsigned long gap = rlimit(RLIMIT_STACK); ++ ++ if (gap < MIN_GAP) ++ gap = MIN_GAP; ++ else if (gap > MAX_GAP) ++ gap = MAX_GAP; ++ ++ return PAGE_ALIGN(TASK_SIZE - gap - rnd); ++} ++ + /* + * We need to ensure that shared mappings are correctly aligned to + * avoid aliasing issues with VIPT caches. We need to ensure that +@@ -68,13 +107,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + if (len > mm->cached_hole_size) { + start_addr = addr = mm->free_area_cache; + } else { +- start_addr = addr = TASK_UNMAPPED_BASE; ++ start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; + } +- /* 8 bits of randomness in 20 address space bits */ +- if ((current->flags & PF_RANDOMIZE) && +- !(current->personality & ADDR_NO_RANDOMIZE)) +- addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT; + + full_search: + if (do_align) +@@ -111,6 +146,134 @@ full_search: + } + } + ++unsigned long ++arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, ++ const unsigned long len, const unsigned long pgoff, ++ const unsigned long flags) ++{ ++ struct vm_area_struct *vma; ++ struct mm_struct *mm = current->mm; ++ unsigned long addr = addr0; ++ int do_align = 0; ++ int aliasing = cache_is_vipt_aliasing(); ++ ++ /* ++ * We only need to do colour alignment if either the I or D ++ * caches alias. ++ */ ++ if (aliasing) ++ do_align = filp || (flags & MAP_SHARED); ++ ++ /* requested length too big for entire address space */ ++ if (len > TASK_SIZE) ++ return -ENOMEM; ++ ++ if (flags & MAP_FIXED) { ++ if (aliasing && flags & MAP_SHARED && ++ (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) ++ return -EINVAL; ++ return addr; ++ } ++ ++ /* requesting a specific address */ ++ if (addr) { ++ if (do_align) ++ addr = COLOUR_ALIGN(addr, pgoff); ++ else ++ addr = PAGE_ALIGN(addr); ++ vma = find_vma(mm, addr); ++ if (TASK_SIZE - len >= addr && ++ (!vma || addr + len <= vma->vm_start)) ++ return addr; ++ } ++ ++ /* check if free_area_cache is useful for us */ ++ if (len <= mm->cached_hole_size) { ++ mm->cached_hole_size = 0; ++ mm->free_area_cache = mm->mmap_base; ++ } ++ ++ /* either no address requested or can't fit in requested address hole */ ++ addr = mm->free_area_cache; ++ if (do_align) { ++ unsigned long base = COLOUR_ALIGN_DOWN(addr - len, pgoff); ++ addr = base + len; ++ } ++ ++ /* make sure it can fit in the remaining address space */ ++ if (addr > len) { ++ vma = find_vma(mm, addr-len); ++ if (!vma || addr <= vma->vm_start) ++ /* remember the address as a hint for next time */ ++ return (mm->free_area_cache = addr-len); ++ } ++ ++ if (mm->mmap_base < len) ++ goto bottomup; ++ ++ addr = mm->mmap_base - len; ++ if (do_align) ++ addr = COLOUR_ALIGN_DOWN(addr, pgoff); ++ ++ do { ++ /* ++ * Lookup failure means no vma is above this address, ++ * else if new region fits below vma->vm_start, ++ * return with success: ++ */ ++ vma = find_vma(mm, addr); ++ if (!vma || addr+len <= vma->vm_start) ++ /* remember the address as a hint for next time */ ++ return (mm->free_area_cache = addr); ++ ++ /* remember the largest hole we saw so far */ ++ if (addr + mm->cached_hole_size < vma->vm_start) ++ mm->cached_hole_size = vma->vm_start - addr; ++ ++ /* try just below the current vma->vm_start */ ++ addr = vma->vm_start - len; ++ if (do_align) ++ addr = COLOUR_ALIGN_DOWN(addr, pgoff); ++ } while (len < vma->vm_start); ++ ++bottomup: ++ /* ++ * A failed mmap() very likely causes application failure, ++ * so fall back to the bottom-up function here. This scenario ++ * can happen with large stack limits and large mmap() ++ * allocations. ++ */ ++ mm->cached_hole_size = ~0UL; ++ mm->free_area_cache = TASK_UNMAPPED_BASE; ++ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); ++ /* ++ * Restore the topdown base: ++ */ ++ mm->free_area_cache = mm->mmap_base; ++ mm->cached_hole_size = ~0UL; ++ ++ return addr; ++} ++ ++void arch_pick_mmap_layout(struct mm_struct *mm) ++{ ++ unsigned long random_factor = 0UL; ++ ++ /* 8 bits of randomness in 20 address space bits */ ++ if ((current->flags & PF_RANDOMIZE) && ++ !(current->personality & ADDR_NO_RANDOMIZE)) ++ random_factor = (get_random_int() % (1 << 8)) << PAGE_SHIFT; ++ ++ if (mmap_is_legacy()) { ++ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; ++ mm->get_unmapped_area = arch_get_unmapped_area; ++ mm->unmap_area = arch_unmap_area; ++ } else { ++ mm->mmap_base = mmap_base(random_factor); ++ mm->get_unmapped_area = arch_get_unmapped_area_topdown; ++ mm->unmap_area = arch_unmap_area_topdown; ++ } ++} + + /* + * You really shouldn't be using read() or write() on /dev/mem. This +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index 082fa18..704031c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch new file mode 100644 index 00000000..fe6390cd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_mmu.c.patch @@ -0,0 +1,110 @@ +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -537,13 +538,18 @@ EXPORT_SYMBOL(phys_mem_access_prot); + + #define vectors_base() (vectors_high() ? 0xffff0000 : 0) + +-static void __init *early_alloc(unsigned long sz) ++static void __init *early_alloc_aligned(unsigned long sz, unsigned long align) + { +- void *ptr = __va(memblock_alloc(sz, sz)); ++ void *ptr = __va(memblock_alloc(sz, align)); + memset(ptr, 0, sz); + return ptr; + } + ++static void __init *early_alloc(unsigned long sz) ++{ ++ return early_alloc_aligned(sz, sz); ++} ++ + static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) + { + if (pmd_none(*pmd)) { +@@ -693,9 +699,10 @@ static void __init create_mapping(struct map_desc *md) + } + + if ((md->type == MT_DEVICE || md->type == MT_ROM) && +- md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { ++ md->virtual >= PAGE_OFFSET && ++ (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { + printk(KERN_WARNING "BUG: mapping for 0x%08llx" +- " at 0x%08lx overlaps vmalloc space\n", ++ " at 0x%08lx out of vmalloc space\n", + (long long)__pfn_to_phys((u64)md->pfn), md->virtual); + } + +@@ -737,18 +744,34 @@ static void __init create_mapping(struct map_desc *md) + */ + void __init iotable_init(struct map_desc *io_desc, int nr) + { +- int i; +- +- for (i = 0; i < nr; i++) +- create_mapping(io_desc + i); ++ struct map_desc *md; ++ struct vm_struct *vm; ++ ++ if (!nr) ++ return; ++ ++ vm = early_alloc_aligned(sizeof(*vm) * nr, __alignof__(*vm)); ++ ++ for (md = io_desc; nr; md++, nr--) { ++ create_mapping(md); ++ vm->addr = (void *)(md->virtual & PAGE_MASK); ++ vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); ++ vm->phys_addr = __pfn_to_phys(md->pfn); ++ vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; ++ vm->flags |= VM_ARM_MTYPE(md->type); ++ vm->caller = iotable_init; ++ vm_area_add_early(vm++); ++ } + } + +-static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M); ++ ++static void * __initdata vmalloc_min = ++ (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); + + /* + * vmalloc=size forces the vmalloc area to be exactly 'size' + * bytes. This can be used to increase (or decrease) the vmalloc +- * area - the default is 128m. ++ * area - the default is 240m. + */ + static int __init early_vmalloc(char *arg) + { +@@ -868,7 +891,8 @@ void __init sanity_check_meminfo(void) + } + #endif + meminfo.nr_banks = j; +- memblock_set_current_limit(lowmem_limit); ++ high_memory = __va(lowmem_limit - 1) + 1; ++ memblock_set_current_limit(lowmem_limit); + } + + static inline void prepare_page_table(void) +@@ -898,10 +922,10 @@ static inline void prepare_page_table(void) + + /* + * Clear out all the kernel space mappings, except for the first +- * memory bank, up to the end of the vmalloc region. ++ * memory bank, up to the vmalloc region. + */ + for (addr = __phys_to_virt(end); +- addr < VMALLOC_END; addr += PMD_SIZE) ++ addr < VMALLOC_START; addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); + } + +diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c +index a5018fb..13d8194 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch new file mode 100644 index 00000000..0c54ffdd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_mm_nommu.c.patch @@ -0,0 +1,14 @@ +--- a/arch/arm/mm/nommu.c ++++ b/arch/arm/mm/nommu.c +@@ -29,6 +29,8 @@ void __init arm_mm_memblock_reserve(void) + + void __init sanity_check_meminfo(void) + { ++ phys_addr_t end = bank_phys_end(&meminfo.bank[meminfo.nr_banks - 1]); ++ high_memory = __va(end - 1) + 1; + } + + /* +diff --git a/arch/arm/net/Makefile b/arch/arm/net/Makefile +new file mode 100644 +index 0000000..c2c1084 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch new file mode 100644 index 00000000..655fb068 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/arch/arm/net/Makefile +@@ -0,0 +1,3 @@ ++# ARM-specific networking code ++ ++obj-$(CONFIG_BPF_JIT) += bpf_jit_32.o +diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c +new file mode 100644 +index 0000000..62135849 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch new file mode 100644 index 00000000..8b475d7f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.c.patch @@ -0,0 +1,921 @@ +--- /dev/null ++++ b/arch/arm/net/bpf_jit_32.c +@@ -0,0 +1,915 @@ ++/* ++ * Just-In-Time compiler for BPF filters on 32bit ARM ++ * ++ * Copyright (c) 2011 Mircea Gherzan ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bpf_jit_32.h" ++ ++/* ++ * ABI: ++ * ++ * r0 scratch register ++ * r4 BPF register A ++ * r5 BPF register X ++ * r6 pointer to the skb ++ * r7 skb->data ++ * r8 skb_headlen(skb) ++ */ ++ ++#define r_scratch ARM_R0 ++/* r1-r3 are (also) used for the unaligned loads on the non-ARMv7 slowpath */ ++#define r_off ARM_R1 ++#define r_A ARM_R4 ++#define r_X ARM_R5 ++#define r_skb ARM_R6 ++#define r_skb_data ARM_R7 ++#define r_skb_hl ARM_R8 ++ ++#define SCRATCH_SP_OFFSET 0 ++#define SCRATCH_OFF(k) (SCRATCH_SP_OFFSET + (k)) ++ ++#define SEEN_MEM ((1 << BPF_MEMWORDS) - 1) ++#define SEEN_MEM_WORD(k) (1 << (k)) ++#define SEEN_X (1 << BPF_MEMWORDS) ++#define SEEN_CALL (1 << (BPF_MEMWORDS + 1)) ++#define SEEN_SKB (1 << (BPF_MEMWORDS + 2)) ++#define SEEN_DATA (1 << (BPF_MEMWORDS + 3)) ++ ++#define FLAG_NEED_X_RESET (1 << 0) ++ ++struct jit_ctx { ++ const struct sk_filter *skf; ++ unsigned idx; ++ unsigned prologue_bytes; ++ int ret0_fp_idx; ++ u32 seen; ++ u32 flags; ++ u32 *offsets; ++ u32 *target; ++#if __LINUX_ARM_ARCH__ < 7 ++ u16 epilogue_bytes; ++ u16 imm_count; ++ u32 *imms; ++#endif ++}; ++ ++int bpf_jit_enable __read_mostly; ++ ++static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) ++{ ++ u8 ret; ++ int err; ++ ++ err = skb_copy_bits(skb, offset, &ret, 1); ++ ++ return (u64)err << 32 | ret; ++} ++ ++static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) ++{ ++ u16 ret; ++ int err; ++ ++ err = skb_copy_bits(skb, offset, &ret, 2); ++ ++ return (u64)err << 32 | ntohs(ret); ++} ++ ++static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) ++{ ++ u32 ret; ++ int err; ++ ++ err = skb_copy_bits(skb, offset, &ret, 4); ++ ++ return (u64)err << 32 | ntohl(ret); ++} ++ ++/* ++ * Wrapper that handles both OABI and EABI and assures Thumb2 interworking ++ * (where the assembly routines like __aeabi_uidiv could cause problems). ++ */ ++static u32 jit_udiv(u32 dividend, u32 divisor) ++{ ++ return dividend / divisor; ++} ++ ++static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx) ++{ ++ if (ctx->target != NULL) ++ ctx->target[ctx->idx] = inst | (cond << 28); ++ ++ ctx->idx++; ++} ++ ++/* ++ * Emit an instruction that will be executed unconditionally. ++ */ ++static inline void emit(u32 inst, struct jit_ctx *ctx) ++{ ++ _emit(ARM_COND_AL, inst, ctx); ++} ++ ++static u16 saved_regs(struct jit_ctx *ctx) ++{ ++ u16 ret = 0; ++ ++ if ((ctx->skf->len > 1) || ++ (ctx->skf->insns[0].code == BPF_S_RET_A)) ++ ret |= 1 << r_A; ++ ++#ifdef CONFIG_FRAME_POINTER ++ ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC); ++#else ++ if (ctx->seen & SEEN_CALL) ++ ret |= 1 << ARM_LR; ++#endif ++ if (ctx->seen & (SEEN_DATA | SEEN_SKB)) ++ ret |= 1 << r_skb; ++ if (ctx->seen & SEEN_DATA) ++ ret |= (1 << r_skb_data) | (1 << r_skb_hl); ++ if (ctx->seen & SEEN_X) ++ ret |= 1 << r_X; ++ ++ return ret; ++} ++ ++static inline int mem_words_used(struct jit_ctx *ctx) ++{ ++ /* yes, we do waste some stack space IF there are "holes" in the set" */ ++ return fls(ctx->seen & SEEN_MEM); ++} ++ ++static inline bool is_load_to_a(u16 inst) ++{ ++ switch (inst) { ++ case BPF_S_LD_W_LEN: ++ case BPF_S_LD_W_ABS: ++ case BPF_S_LD_H_ABS: ++ case BPF_S_LD_B_ABS: ++ case BPF_S_ANC_CPU: ++ case BPF_S_ANC_IFINDEX: ++ case BPF_S_ANC_MARK: ++ case BPF_S_ANC_PROTOCOL: ++ case BPF_S_ANC_RXHASH: ++ case BPF_S_ANC_QUEUE: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static void build_prologue(struct jit_ctx *ctx) ++{ ++ u16 reg_set = saved_regs(ctx); ++ u16 first_inst = ctx->skf->insns[0].code; ++ u16 off; ++ ++#ifdef CONFIG_FRAME_POINTER ++ emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx); ++ emit(ARM_PUSH(reg_set), ctx); ++ emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx); ++#else ++ if (reg_set) ++ emit(ARM_PUSH(reg_set), ctx); ++#endif ++ ++ if (ctx->seen & (SEEN_DATA | SEEN_SKB)) ++ emit(ARM_MOV_R(r_skb, ARM_R0), ctx); ++ ++ if (ctx->seen & SEEN_DATA) { ++ off = offsetof(struct sk_buff, data); ++ emit(ARM_LDR_I(r_skb_data, r_skb, off), ctx); ++ /* headlen = len - data_len */ ++ off = offsetof(struct sk_buff, len); ++ emit(ARM_LDR_I(r_skb_hl, r_skb, off), ctx); ++ off = offsetof(struct sk_buff, data_len); ++ emit(ARM_LDR_I(r_scratch, r_skb, off), ctx); ++ emit(ARM_SUB_R(r_skb_hl, r_skb_hl, r_scratch), ctx); ++ } ++ ++ if (ctx->flags & FLAG_NEED_X_RESET) ++ emit(ARM_MOV_I(r_X, 0), ctx); ++ ++ /* do not leak kernel data to userspace */ ++ if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst))) ++ emit(ARM_MOV_I(r_A, 0), ctx); ++ ++ /* stack space for the BPF_MEM words */ ++ if (ctx->seen & SEEN_MEM) ++ emit(ARM_SUB_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx); ++} ++ ++static void build_epilogue(struct jit_ctx *ctx) ++{ ++ u16 reg_set = saved_regs(ctx); ++ ++ if (ctx->seen & SEEN_MEM) ++ emit(ARM_ADD_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx); ++ ++ reg_set &= ~(1 << ARM_LR); ++ ++#ifdef CONFIG_FRAME_POINTER ++ /* the first instruction of the prologue was: mov ip, sp */ ++ reg_set &= ~(1 << ARM_IP); ++ reg_set |= (1 << ARM_SP); ++ emit(ARM_LDM(ARM_SP, reg_set), ctx); ++#else ++ if (reg_set) { ++ if (ctx->seen & SEEN_CALL) ++ reg_set |= 1 << ARM_PC; ++ emit(ARM_POP(reg_set), ctx); ++ } ++ ++ if (!(ctx->seen & SEEN_CALL)) ++ emit(ARM_BX(ARM_LR), ctx); ++#endif ++} ++ ++static int16_t imm8m(u32 x) ++{ ++ u32 rot; ++ ++ for (rot = 0; rot < 16; rot++) ++ if ((x & ~ror32(0xff, 2 * rot)) == 0) ++ return rol32(x, 2 * rot) | (rot << 8); ++ ++ return -1; ++} ++ ++#if __LINUX_ARM_ARCH__ < 7 ++ ++static u16 imm_offset(u32 k, struct jit_ctx *ctx) ++{ ++ unsigned i = 0, offset; ++ u16 imm; ++ ++ /* on the "fake" run we just count them (duplicates included) */ ++ if (ctx->target == NULL) { ++ ctx->imm_count++; ++ return 0; ++ } ++ ++ while ((i < ctx->imm_count) && ctx->imms[i]) { ++ if (ctx->imms[i] == k) ++ break; ++ i++; ++ } ++ ++ if (ctx->imms[i] == 0) ++ ctx->imms[i] = k; ++ ++ /* constants go just after the epilogue */ ++ offset = ctx->offsets[ctx->skf->len]; ++ offset += ctx->prologue_bytes; ++ offset += ctx->epilogue_bytes; ++ offset += i * 4; ++ ++ ctx->target[offset / 4] = k; ++ ++ /* PC in ARM mode == address of the instruction + 8 */ ++ imm = offset - (8 + ctx->idx * 4); ++ ++ return imm; ++} ++ ++#endif /* __LINUX_ARM_ARCH__ */ ++ ++/* ++ * Move an immediate that's not an imm8m to a core register. ++ */ ++static inline void emit_mov_i_no8m(int rd, u32 val, struct jit_ctx *ctx) ++{ ++#if __LINUX_ARM_ARCH__ < 7 ++ emit(ARM_LDR_I(rd, ARM_PC, imm_offset(val, ctx)), ctx); ++#else ++ emit(ARM_MOVW(rd, val & 0xffff), ctx); ++ if (val > 0xffff) ++ emit(ARM_MOVT(rd, val >> 16), ctx); ++#endif ++} ++ ++static inline void emit_mov_i(int rd, u32 val, struct jit_ctx *ctx) ++{ ++ int imm12 = imm8m(val); ++ ++ if (imm12 >= 0) ++ emit(ARM_MOV_I(rd, imm12), ctx); ++ else ++ emit_mov_i_no8m(rd, val, ctx); ++} ++ ++#if __LINUX_ARM_ARCH__ < 6 ++ ++static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDRB_I(ARM_R3, r_addr, 1), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 3), ctx); ++ _emit(cond, ARM_LSL_I(ARM_R3, ARM_R3, 16), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R0, r_addr, 2), ctx); ++ _emit(cond, ARM_ORR_S(ARM_R3, ARM_R3, ARM_R1, SRTYPE_LSL, 24), ctx); ++ _emit(cond, ARM_ORR_R(ARM_R3, ARM_R3, ARM_R2), ctx); ++ _emit(cond, ARM_ORR_S(r_res, ARM_R3, ARM_R0, SRTYPE_LSL, 8), ctx); ++} ++ ++static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx); ++ _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 1), ctx); ++ _emit(cond, ARM_ORR_S(r_res, ARM_R2, ARM_R1, SRTYPE_LSL, 8), ctx); ++} ++ ++static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx) ++{ ++ emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx); ++ emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx); ++ emit(ARM_LSL_I(r_dst, r_dst, 8), ctx); ++ emit(ARM_LSL_R(r_dst, r_dst, 8), ctx); ++} ++ ++#else /* ARMv6+ */ ++ ++static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDR_I(r_res, r_addr, 0), ctx); ++#ifdef __LITTLE_ENDIAN ++ _emit(cond, ARM_REV(r_res, r_res), ctx); ++#endif ++} ++ ++static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx) ++{ ++ _emit(cond, ARM_LDRH_I(r_res, r_addr, 0), ctx); ++#ifdef __LITTLE_ENDIAN ++ _emit(cond, ARM_REV16(r_res, r_res), ctx); ++#endif ++} ++ ++static inline void emit_swap16(u8 r_dst __maybe_unused, ++ u8 r_src __maybe_unused, ++ struct jit_ctx *ctx __maybe_unused) ++{ ++#ifdef __LITTLE_ENDIAN ++ emit(ARM_REV16(r_dst, r_src), ctx); ++#endif ++} ++ ++#endif /* __LINUX_ARM_ARCH__ < 6 */ ++ ++ ++/* Compute the immediate value for a PC-relative branch. */ ++static inline u32 b_imm(unsigned tgt, struct jit_ctx *ctx) ++{ ++ u32 imm; ++ ++ if (ctx->target == NULL) ++ return 0; ++ /* ++ * BPF allows only forward jumps and the offset of the target is ++ * still the one computed during the first pass. ++ */ ++ imm = ctx->offsets[tgt] + ctx->prologue_bytes - (ctx->idx * 4 + 8); ++ ++ return imm >> 2; ++} ++ ++#define OP_IMM3(op, r1, r2, imm_val, ctx) \ ++ do { \ ++ imm12 = imm8m(imm_val); \ ++ if (imm12 < 0) { \ ++ emit_mov_i_no8m(r_scratch, imm_val, ctx); \ ++ emit(op ## _R((r1), (r2), r_scratch), ctx); \ ++ } else { \ ++ emit(op ## _I((r1), (r2), imm12), ctx); \ ++ } \ ++ } while (0) ++ ++static inline void emit_err_ret(u8 cond, struct jit_ctx *ctx) ++{ ++ if (ctx->ret0_fp_idx >= 0) { ++ _emit(cond, ARM_B(b_imm(ctx->ret0_fp_idx, ctx)), ctx); ++ /* NOP to keep the size constant between passes */ ++ emit(ARM_MOV_R(ARM_R0, ARM_R0), ctx); ++ } else { ++ _emit(cond, ARM_MOV_I(ARM_R0, 0), ctx); ++ _emit(cond, ARM_B(b_imm(ctx->skf->len, ctx)), ctx); ++ } ++} ++ ++static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx) ++{ ++#if __LINUX_ARM_ARCH__ < 5 ++ emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx); ++ ++ if (elf_hwcap & HWCAP_THUMB) ++ emit(ARM_BX(tgt_reg), ctx); ++ else ++ emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx); ++#else ++ emit(ARM_BLX_R(tgt_reg), ctx); ++#endif ++} ++ ++static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx) ++{ ++#if __LINUX_ARM_ARCH__ == 7 ++ if (elf_hwcap & HWCAP_IDIVA) { ++ emit(ARM_UDIV(rd, rm, rn), ctx); ++ return; ++ } ++#endif ++ if (rm != ARM_R0) ++ emit(ARM_MOV_R(ARM_R0, rm), ctx); ++ if (rn != ARM_R1) ++ emit(ARM_MOV_R(ARM_R1, rn), ctx); ++ ++ ctx->seen |= SEEN_CALL; ++ emit_mov_i(ARM_R3, (u32)jit_udiv, ctx); ++ emit_blx_r(ARM_R3, ctx); ++ ++ if (rd != ARM_R0) ++ emit(ARM_MOV_R(rd, ARM_R0), ctx); ++} ++ ++static inline void update_on_xread(struct jit_ctx *ctx) ++{ ++ if (!(ctx->seen & SEEN_X)) ++ ctx->flags |= FLAG_NEED_X_RESET; ++ ++ ctx->seen |= SEEN_X; ++} ++ ++static int build_body(struct jit_ctx *ctx) ++{ ++ void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w}; ++ const struct sk_filter *prog = ctx->skf; ++ const struct sock_filter *inst; ++ unsigned i, load_order, off, condt; ++ int imm12; ++ u32 k; ++ ++ for (i = 0; i < prog->len; i++) { ++ inst = &(prog->insns[i]); ++ /* K as an immediate value operand */ ++ k = inst->k; ++ ++ /* compute offsets only in the fake pass */ ++ if (ctx->target == NULL) ++ ctx->offsets[i] = ctx->idx * 4; ++ ++ switch (inst->code) { ++ case BPF_S_LD_IMM: ++ emit_mov_i(r_A, k, ctx); ++ break; ++ case BPF_S_LD_W_LEN: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); ++ emit(ARM_LDR_I(r_A, r_skb, ++ offsetof(struct sk_buff, len)), ctx); ++ break; ++ case BPF_S_LD_MEM: ++ /* A = scratch[k] */ ++ ctx->seen |= SEEN_MEM_WORD(k); ++ emit(ARM_LDR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_LD_W_ABS: ++ load_order = 2; ++ goto load; ++ case BPF_S_LD_H_ABS: ++ load_order = 1; ++ goto load; ++ case BPF_S_LD_B_ABS: ++ load_order = 0; ++load: ++ /* the interpreter will deal with the negative K */ ++ if ((int)k < 0) ++ return -ENOTSUPP; ++ emit_mov_i(r_off, k, ctx); ++load_common: ++ ctx->seen |= SEEN_DATA | SEEN_CALL; ++ ++ if (load_order > 0) { ++ emit(ARM_SUB_I(r_scratch, r_skb_hl, ++ 1 << load_order), ctx); ++ emit(ARM_CMP_R(r_scratch, r_off), ctx); ++ condt = ARM_COND_HS; ++ } else { ++ emit(ARM_CMP_R(r_skb_hl, r_off), ctx); ++ condt = ARM_COND_HI; ++ } ++ ++ _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data), ++ ctx); ++ ++ if (load_order == 0) ++ _emit(condt, ARM_LDRB_I(r_A, r_scratch, 0), ++ ctx); ++ else if (load_order == 1) ++ emit_load_be16(condt, r_A, r_scratch, ctx); ++ else if (load_order == 2) ++ emit_load_be32(condt, r_A, r_scratch, ctx); ++ ++ _emit(condt, ARM_B(b_imm(i + 1, ctx)), ctx); ++ ++ /* the slowpath */ ++ emit_mov_i(ARM_R3, (u32)load_func[load_order], ctx); ++ emit(ARM_MOV_R(ARM_R0, r_skb), ctx); ++ /* the offset is already in R1 */ ++ emit_blx_r(ARM_R3, ctx); ++ /* check the result of skb_copy_bits */ ++ emit(ARM_CMP_I(ARM_R1, 0), ctx); ++ emit_err_ret(ARM_COND_NE, ctx); ++ emit(ARM_MOV_R(r_A, ARM_R0), ctx); ++ break; ++ case BPF_S_LD_W_IND: ++ load_order = 2; ++ goto load_ind; ++ case BPF_S_LD_H_IND: ++ load_order = 1; ++ goto load_ind; ++ case BPF_S_LD_B_IND: ++ load_order = 0; ++load_ind: ++ OP_IMM3(ARM_ADD, r_off, r_X, k, ctx); ++ goto load_common; ++ case BPF_S_LDX_IMM: ++ ctx->seen |= SEEN_X; ++ emit_mov_i(r_X, k, ctx); ++ break; ++ case BPF_S_LDX_W_LEN: ++ ctx->seen |= SEEN_X | SEEN_SKB; ++ emit(ARM_LDR_I(r_X, r_skb, ++ offsetof(struct sk_buff, len)), ctx); ++ break; ++ case BPF_S_LDX_MEM: ++ ctx->seen |= SEEN_X | SEEN_MEM_WORD(k); ++ emit(ARM_LDR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_LDX_B_MSH: ++ /* x = ((*(frame + k)) & 0xf) << 2; */ ++ ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL; ++ /* the interpreter should deal with the negative K */ ++ if (k < 0) ++ return -1; ++ /* offset in r1: we might have to take the slow path */ ++ emit_mov_i(r_off, k, ctx); ++ emit(ARM_CMP_R(r_skb_hl, r_off), ctx); ++ ++ /* load in r0: common with the slowpath */ ++ _emit(ARM_COND_HI, ARM_LDRB_R(ARM_R0, r_skb_data, ++ ARM_R1), ctx); ++ /* ++ * emit_mov_i() might generate one or two instructions, ++ * the same holds for emit_blx_r() ++ */ ++ _emit(ARM_COND_HI, ARM_B(b_imm(i + 1, ctx) - 2), ctx); ++ ++ emit(ARM_MOV_R(ARM_R0, r_skb), ctx); ++ /* r_off is r1 */ ++ emit_mov_i(ARM_R3, (u32)jit_get_skb_b, ctx); ++ emit_blx_r(ARM_R3, ctx); ++ /* check the return value of skb_copy_bits */ ++ emit(ARM_CMP_I(ARM_R1, 0), ctx); ++ emit_err_ret(ARM_COND_NE, ctx); ++ ++ emit(ARM_AND_I(r_X, ARM_R0, 0x00f), ctx); ++ emit(ARM_LSL_I(r_X, r_X, 2), ctx); ++ break; ++ case BPF_S_ST: ++ ctx->seen |= SEEN_MEM_WORD(k); ++ emit(ARM_STR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_STX: ++ update_on_xread(ctx); ++ ctx->seen |= SEEN_MEM_WORD(k); ++ emit(ARM_STR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx); ++ break; ++ case BPF_S_ALU_ADD_K: ++ /* A += K */ ++ OP_IMM3(ARM_ADD, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_ADD_X: ++ update_on_xread(ctx); ++ emit(ARM_ADD_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_SUB_K: ++ /* A -= K */ ++ OP_IMM3(ARM_SUB, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_SUB_X: ++ update_on_xread(ctx); ++ emit(ARM_SUB_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_MUL_K: ++ /* A *= K */ ++ emit_mov_i(r_scratch, k, ctx); ++ emit(ARM_MUL(r_A, r_A, r_scratch), ctx); ++ break; ++ case BPF_S_ALU_MUL_X: ++ update_on_xread(ctx); ++ emit(ARM_MUL(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_DIV_K: ++ /* current k == reciprocal_value(userspace k) */ ++ emit_mov_i(r_scratch, k, ctx); ++ /* A = top 32 bits of the product */ ++ emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx); ++ break; ++ case BPF_S_ALU_DIV_X: ++ update_on_xread(ctx); ++ emit(ARM_CMP_I(r_X, 0), ctx); ++ emit_err_ret(ARM_COND_EQ, ctx); ++ emit_udiv(r_A, r_A, r_X, ctx); ++ break; ++ case BPF_S_ALU_OR_K: ++ /* A |= K */ ++ OP_IMM3(ARM_ORR, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_OR_X: ++ update_on_xread(ctx); ++ emit(ARM_ORR_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_AND_K: ++ /* A &= K */ ++ OP_IMM3(ARM_AND, r_A, r_A, k, ctx); ++ break; ++ case BPF_S_ALU_AND_X: ++ update_on_xread(ctx); ++ emit(ARM_AND_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_LSH_K: ++ if (unlikely(k > 31)) ++ return -1; ++ emit(ARM_LSL_I(r_A, r_A, k), ctx); ++ break; ++ case BPF_S_ALU_LSH_X: ++ update_on_xread(ctx); ++ emit(ARM_LSL_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_RSH_K: ++ if (unlikely(k > 31)) ++ return -1; ++ emit(ARM_LSR_I(r_A, r_A, k), ctx); ++ break; ++ case BPF_S_ALU_RSH_X: ++ update_on_xread(ctx); ++ emit(ARM_LSR_R(r_A, r_A, r_X), ctx); ++ break; ++ case BPF_S_ALU_NEG: ++ /* A = -A */ ++ emit(ARM_RSB_I(r_A, r_A, 0), ctx); ++ break; ++ case BPF_S_JMP_JA: ++ /* pc += K */ ++ emit(ARM_B(b_imm(i + k + 1, ctx)), ctx); ++ break; ++ case BPF_S_JMP_JEQ_K: ++ /* pc += (A == K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_EQ; ++ goto cmp_imm; ++ case BPF_S_JMP_JGT_K: ++ /* pc += (A > K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_HI; ++ goto cmp_imm; ++ case BPF_S_JMP_JGE_K: ++ /* pc += (A >= K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_HS; ++cmp_imm: ++ imm12 = imm8m(k); ++ if (imm12 < 0) { ++ emit_mov_i_no8m(r_scratch, k, ctx); ++ emit(ARM_CMP_R(r_A, r_scratch), ctx); ++ } else { ++ emit(ARM_CMP_I(r_A, imm12), ctx); ++ } ++cond_jump: ++ if (inst->jt) ++ _emit(condt, ARM_B(b_imm(i + inst->jt + 1, ++ ctx)), ctx); ++ if (inst->jf) ++ _emit(condt ^ 1, ARM_B(b_imm(i + inst->jf + 1, ++ ctx)), ctx); ++ break; ++ case BPF_S_JMP_JEQ_X: ++ /* pc += (A == X) ? pc->jt : pc->jf */ ++ condt = ARM_COND_EQ; ++ goto cmp_x; ++ case BPF_S_JMP_JGT_X: ++ /* pc += (A > X) ? pc->jt : pc->jf */ ++ condt = ARM_COND_HI; ++ goto cmp_x; ++ case BPF_S_JMP_JGE_X: ++ /* pc += (A >= X) ? pc->jt : pc->jf */ ++ condt = ARM_COND_CS; ++cmp_x: ++ update_on_xread(ctx); ++ emit(ARM_CMP_R(r_A, r_X), ctx); ++ goto cond_jump; ++ case BPF_S_JMP_JSET_K: ++ /* pc += (A & K) ? pc->jt : pc->jf */ ++ condt = ARM_COND_NE; ++ /* not set iff all zeroes iff Z==1 iff EQ */ ++ ++ imm12 = imm8m(k); ++ if (imm12 < 0) { ++ emit_mov_i_no8m(r_scratch, k, ctx); ++ emit(ARM_TST_R(r_A, r_scratch), ctx); ++ } else { ++ emit(ARM_TST_I(r_A, imm12), ctx); ++ } ++ goto cond_jump; ++ case BPF_S_JMP_JSET_X: ++ /* pc += (A & X) ? pc->jt : pc->jf */ ++ update_on_xread(ctx); ++ condt = ARM_COND_NE; ++ emit(ARM_TST_R(r_A, r_X), ctx); ++ goto cond_jump; ++ case BPF_S_RET_A: ++ emit(ARM_MOV_R(ARM_R0, r_A), ctx); ++ goto b_epilogue; ++ case BPF_S_RET_K: ++ if ((k == 0) && (ctx->ret0_fp_idx < 0)) ++ ctx->ret0_fp_idx = i; ++ emit_mov_i(ARM_R0, k, ctx); ++b_epilogue: ++ if (i != ctx->skf->len - 1) ++ emit(ARM_B(b_imm(prog->len, ctx)), ctx); ++ break; ++ case BPF_S_MISC_TAX: ++ /* X = A */ ++ ctx->seen |= SEEN_X; ++ emit(ARM_MOV_R(r_X, r_A), ctx); ++ break; ++ case BPF_S_MISC_TXA: ++ /* A = X */ ++ update_on_xread(ctx); ++ emit(ARM_MOV_R(r_A, r_X), ctx); ++ break; ++ case BPF_S_ANC_PROTOCOL: ++ /* A = ntohs(skb->protocol) */ ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, ++ protocol) != 2); ++ off = offsetof(struct sk_buff, protocol); ++ emit(ARM_LDRH_I(r_scratch, r_skb, off), ctx); ++ emit_swap16(r_A, r_scratch, ctx); ++ break; ++ case BPF_S_ANC_CPU: ++ /* r_scratch = current_thread_info() */ ++ OP_IMM3(ARM_BIC, r_scratch, ARM_SP, THREAD_SIZE - 1, ctx); ++ /* A = current_thread_info()->cpu */ ++ BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4); ++ off = offsetof(struct thread_info, cpu); ++ emit(ARM_LDR_I(r_A, r_scratch, off), ctx); ++ break; ++ case BPF_S_ANC_IFINDEX: ++ /* A = skb->dev->ifindex */ ++ ctx->seen |= SEEN_SKB; ++ off = offsetof(struct sk_buff, dev); ++ emit(ARM_LDR_I(r_scratch, r_skb, off), ctx); ++ ++ emit(ARM_CMP_I(r_scratch, 0), ctx); ++ emit_err_ret(ARM_COND_EQ, ctx); ++ ++ BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ++ ifindex) != 4); ++ off = offsetof(struct net_device, ifindex); ++ emit(ARM_LDR_I(r_A, r_scratch, off), ctx); ++ break; ++ case BPF_S_ANC_MARK: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); ++ off = offsetof(struct sk_buff, mark); ++ emit(ARM_LDR_I(r_A, r_skb, off), ctx); ++ break; ++ case BPF_S_ANC_RXHASH: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4); ++ off = offsetof(struct sk_buff, rxhash); ++ emit(ARM_LDR_I(r_A, r_skb, off), ctx); ++ break; ++ case BPF_S_ANC_QUEUE: ++ ctx->seen |= SEEN_SKB; ++ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, ++ queue_mapping) != 2); ++ BUILD_BUG_ON(offsetof(struct sk_buff, ++ queue_mapping) > 0xff); ++ off = offsetof(struct sk_buff, queue_mapping); ++ emit(ARM_LDRH_I(r_A, r_skb, off), ctx); ++ break; ++ default: ++ return -1; ++ } ++ } ++ ++ /* compute offsets only during the first pass */ ++ if (ctx->target == NULL) ++ ctx->offsets[i] = ctx->idx * 4; ++ ++ return 0; ++} ++ ++ ++void bpf_jit_compile(struct sk_filter *fp) ++{ ++ struct jit_ctx ctx; ++ unsigned tmp_idx; ++ unsigned alloc_size; ++ ++ if (!bpf_jit_enable) ++ return; ++ ++ memset(&ctx, 0, sizeof(ctx)); ++ ctx.skf = fp; ++ ctx.ret0_fp_idx = -1; ++ ++ ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1)); ++ if (ctx.offsets == NULL) ++ return; ++ ++ /* fake pass to fill in the ctx->seen */ ++ if (unlikely(build_body(&ctx))) ++ goto out; ++ ++ tmp_idx = ctx.idx; ++ build_prologue(&ctx); ++ ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4; ++ ++#if __LINUX_ARM_ARCH__ < 7 ++ tmp_idx = ctx.idx; ++ build_epilogue(&ctx); ++ ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4; ++ ++ ctx.idx += ctx.imm_count; ++ if (ctx.imm_count) { ++ ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count); ++ if (ctx.imms == NULL) ++ goto out; ++ } ++#else ++ /* there's nothing after the epilogue on ARMv7 */ ++ build_epilogue(&ctx); ++#endif ++ ++ alloc_size = 4 * ctx.idx; ++ ctx.target = module_alloc(max(sizeof(struct work_struct), ++ alloc_size)); ++ if (unlikely(ctx.target == NULL)) ++ goto out; ++ ++ ctx.idx = 0; ++ build_prologue(&ctx); ++ build_body(&ctx); ++ build_epilogue(&ctx); ++ ++ flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx)); ++ ++#if __LINUX_ARM_ARCH__ < 7 ++ if (ctx.imm_count) ++ kfree(ctx.imms); ++#endif ++ ++ if (bpf_jit_enable > 1) ++ print_hex_dump(KERN_INFO, "BPF JIT code: ", ++ DUMP_PREFIX_ADDRESS, 16, 4, ctx.target, ++ alloc_size, false); ++ ++ fp->bpf_func = (void *)ctx.target; ++out: ++ kfree(ctx.offsets); ++ return; ++} ++ ++static void bpf_jit_free_worker(struct work_struct *work) ++{ ++ module_free(NULL, work); ++} ++ ++void bpf_jit_free(struct sk_filter *fp) ++{ ++ struct work_struct *work; ++ ++ if (fp->bpf_func != sk_run_filter) { ++ work = (struct work_struct *)fp->bpf_func; ++ ++ INIT_WORK(work, bpf_jit_free_worker); ++ schedule_work(work); ++ } ++} +diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h +new file mode 100644 +index 0000000..99ae5e3 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch new file mode 100644 index 00000000..eaadc907 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_net_bpf_jit_32.h.patch @@ -0,0 +1,196 @@ +--- /dev/null ++++ b/arch/arm/net/bpf_jit_32.h +@@ -0,0 +1,190 @@ ++/* ++ * Just-In-Time compiler for BPF filters on 32bit ARM ++ * ++ * Copyright (c) 2011 Mircea Gherzan ++ * ++ * 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. ++ */ ++ ++#ifndef PFILTER_OPCODES_ARM_H ++#define PFILTER_OPCODES_ARM_H ++ ++#define ARM_R0 0 ++#define ARM_R1 1 ++#define ARM_R2 2 ++#define ARM_R3 3 ++#define ARM_R4 4 ++#define ARM_R5 5 ++#define ARM_R6 6 ++#define ARM_R7 7 ++#define ARM_R8 8 ++#define ARM_R9 9 ++#define ARM_R10 10 ++#define ARM_FP 11 ++#define ARM_IP 12 ++#define ARM_SP 13 ++#define ARM_LR 14 ++#define ARM_PC 15 ++ ++#define ARM_COND_EQ 0x0 ++#define ARM_COND_NE 0x1 ++#define ARM_COND_CS 0x2 ++#define ARM_COND_HS ARM_COND_CS ++#define ARM_COND_CC 0x3 ++#define ARM_COND_LO ARM_COND_CC ++#define ARM_COND_MI 0x4 ++#define ARM_COND_PL 0x5 ++#define ARM_COND_VS 0x6 ++#define ARM_COND_VC 0x7 ++#define ARM_COND_HI 0x8 ++#define ARM_COND_LS 0x9 ++#define ARM_COND_GE 0xa ++#define ARM_COND_LT 0xb ++#define ARM_COND_GT 0xc ++#define ARM_COND_LE 0xd ++#define ARM_COND_AL 0xe ++ ++/* register shift types */ ++#define SRTYPE_LSL 0 ++#define SRTYPE_LSR 1 ++#define SRTYPE_ASR 2 ++#define SRTYPE_ROR 3 ++ ++#define ARM_INST_ADD_R 0x00800000 ++#define ARM_INST_ADD_I 0x02800000 ++ ++#define ARM_INST_AND_R 0x00000000 ++#define ARM_INST_AND_I 0x02000000 ++ ++#define ARM_INST_BIC_R 0x01c00000 ++#define ARM_INST_BIC_I 0x03c00000 ++ ++#define ARM_INST_B 0x0a000000 ++#define ARM_INST_BX 0x012FFF10 ++#define ARM_INST_BLX_R 0x012fff30 ++ ++#define ARM_INST_CMP_R 0x01500000 ++#define ARM_INST_CMP_I 0x03500000 ++ ++#define ARM_INST_LDRB_I 0x05d00000 ++#define ARM_INST_LDRB_R 0x07d00000 ++#define ARM_INST_LDRH_I 0x01d000b0 ++#define ARM_INST_LDR_I 0x05900000 ++ ++#define ARM_INST_LDM 0x08900000 ++ ++#define ARM_INST_LSL_I 0x01a00000 ++#define ARM_INST_LSL_R 0x01a00010 ++ ++#define ARM_INST_LSR_I 0x01a00020 ++#define ARM_INST_LSR_R 0x01a00030 ++ ++#define ARM_INST_MOV_R 0x01a00000 ++#define ARM_INST_MOV_I 0x03a00000 ++#define ARM_INST_MOVW 0x03000000 ++#define ARM_INST_MOVT 0x03400000 ++ ++#define ARM_INST_MUL 0x00000090 ++ ++#define ARM_INST_POP 0x08bd0000 ++#define ARM_INST_PUSH 0x092d0000 ++ ++#define ARM_INST_ORR_R 0x01800000 ++#define ARM_INST_ORR_I 0x03800000 ++ ++#define ARM_INST_REV 0x06bf0f30 ++#define ARM_INST_REV16 0x06bf0fb0 ++ ++#define ARM_INST_RSB_I 0x02600000 ++ ++#define ARM_INST_SUB_R 0x00400000 ++#define ARM_INST_SUB_I 0x02400000 ++ ++#define ARM_INST_STR_I 0x05800000 ++ ++#define ARM_INST_TST_R 0x01100000 ++#define ARM_INST_TST_I 0x03100000 ++ ++#define ARM_INST_UDIV 0x0730f010 ++ ++#define ARM_INST_UMULL 0x00800090 ++ ++/* register */ ++#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm)) ++/* immediate */ ++#define _AL3_I(op, rd, rn, imm) ((op ## _I) | (rd) << 12 | (rn) << 16 | (imm)) ++ ++#define ARM_ADD_R(rd, rn, rm) _AL3_R(ARM_INST_ADD, rd, rn, rm) ++#define ARM_ADD_I(rd, rn, imm) _AL3_I(ARM_INST_ADD, rd, rn, imm) ++ ++#define ARM_AND_R(rd, rn, rm) _AL3_R(ARM_INST_AND, rd, rn, rm) ++#define ARM_AND_I(rd, rn, imm) _AL3_I(ARM_INST_AND, rd, rn, imm) ++ ++#define ARM_BIC_R(rd, rn, rm) _AL3_R(ARM_INST_BIC, rd, rn, rm) ++#define ARM_BIC_I(rd, rn, imm) _AL3_I(ARM_INST_BIC, rd, rn, imm) ++ ++#define ARM_B(imm24) (ARM_INST_B | ((imm24) & 0xffffff)) ++#define ARM_BX(rm) (ARM_INST_BX | (rm)) ++#define ARM_BLX_R(rm) (ARM_INST_BLX_R | (rm)) ++ ++#define ARM_CMP_R(rn, rm) _AL3_R(ARM_INST_CMP, 0, rn, rm) ++#define ARM_CMP_I(rn, imm) _AL3_I(ARM_INST_CMP, 0, rn, imm) ++ ++#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \ ++ | (off)) ++#define ARM_LDRB_I(rt, rn, off) (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \ ++ | (off)) ++#define ARM_LDRB_R(rt, rn, rm) (ARM_INST_LDRB_R | (rt) << 12 | (rn) << 16 \ ++ | (rm)) ++#define ARM_LDRH_I(rt, rn, off) (ARM_INST_LDRH_I | (rt) << 12 | (rn) << 16 \ ++ | (((off) & 0xf0) << 4) | ((off) & 0xf)) ++ ++#define ARM_LDM(rn, regs) (ARM_INST_LDM | (rn) << 16 | (regs)) ++ ++#define ARM_LSL_R(rd, rn, rm) (_AL3_R(ARM_INST_LSL, rd, 0, rn) | (rm) << 8) ++#define ARM_LSL_I(rd, rn, imm) (_AL3_I(ARM_INST_LSL, rd, 0, rn) | (imm) << 7) ++ ++#define ARM_LSR_R(rd, rn, rm) (_AL3_R(ARM_INST_LSR, rd, 0, rn) | (rm) << 8) ++#define ARM_LSR_I(rd, rn, imm) (_AL3_I(ARM_INST_LSR, rd, 0, rn) | (imm) << 7) ++ ++#define ARM_MOV_R(rd, rm) _AL3_R(ARM_INST_MOV, rd, 0, rm) ++#define ARM_MOV_I(rd, imm) _AL3_I(ARM_INST_MOV, rd, 0, imm) ++ ++#define ARM_MOVW(rd, imm) \ ++ (ARM_INST_MOVW | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff)) ++ ++#define ARM_MOVT(rd, imm) \ ++ (ARM_INST_MOVT | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff)) ++ ++#define ARM_MUL(rd, rm, rn) (ARM_INST_MUL | (rd) << 16 | (rm) << 8 | (rn)) ++ ++#define ARM_POP(regs) (ARM_INST_POP | (regs)) ++#define ARM_PUSH(regs) (ARM_INST_PUSH | (regs)) ++ ++#define ARM_ORR_R(rd, rn, rm) _AL3_R(ARM_INST_ORR, rd, rn, rm) ++#define ARM_ORR_I(rd, rn, imm) _AL3_I(ARM_INST_ORR, rd, rn, imm) ++#define ARM_ORR_S(rd, rn, rm, type, rs) \ ++ (ARM_ORR_R(rd, rn, rm) | (type) << 5 | (rs) << 7) ++ ++#define ARM_REV(rd, rm) (ARM_INST_REV | (rd) << 12 | (rm)) ++#define ARM_REV16(rd, rm) (ARM_INST_REV16 | (rd) << 12 | (rm)) ++ ++#define ARM_RSB_I(rd, rn, imm) _AL3_I(ARM_INST_RSB, rd, rn, imm) ++ ++#define ARM_SUB_R(rd, rn, rm) _AL3_R(ARM_INST_SUB, rd, rn, rm) ++#define ARM_SUB_I(rd, rn, imm) _AL3_I(ARM_INST_SUB, rd, rn, imm) ++ ++#define ARM_STR_I(rt, rn, off) (ARM_INST_STR_I | (rt) << 12 | (rn) << 16 \ ++ | (off)) ++ ++#define ARM_TST_R(rn, rm) _AL3_R(ARM_INST_TST, 0, rn, rm) ++#define ARM_TST_I(rn, imm) _AL3_I(ARM_INST_TST, 0, rn, imm) ++ ++#define ARM_UDIV(rd, rn, rm) (ARM_INST_UDIV | (rd) << 16 | (rn) | (rm) << 8) ++ ++#define ARM_UMULL(rd_lo, rd_hi, rn, rm) (ARM_INST_UMULL | (rd_hi) << 16 \ ++ | (rd_lo) << 12 | (rm) << 8 | rn) ++ ++#endif /* PFILTER_OPCODES_ARM_H */ +diff --git a/arch/arm/plat-iproc/Kconfig b/arch/arm/plat-iproc/Kconfig +new file mode 100644 +index 0000000..5b8675f diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch new file mode 100644 index 00000000..f72b82cb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Kconfig.patch @@ -0,0 +1,102 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/Kconfig +@@ -0,0 +1,96 @@ ++# Kernel configuration for Broadcom iProc based boards ++ ++menu "Broadcom IPROC architecture based implementations" ++ depends on ARCH_IPROC ++ ++choice ++ prompt "Broadcom iProc SoC Type" ++ default ARCH_NORTHSTAR ++ ++config ARCH_NORTHSTAR ++ bool "BROADCOM Northstar SoC" ++ help ++ Support for the Broadcom Northstar SoC platform. ++ ++config MACH_IPROC ++ bool "BROADCOM Generic IPROC SoC" ++ help ++ Support for the Broadcom IPROC SoC platform. ++ ++endchoice ++ ++config IPROC_64K_PAGE ++ bool "64K page support" ++ depends on ARCH_IPROC ++ help ++ ++config GP_TIMER_CLOCK_OFF_FIX ++ bool "Enable the fix for general purpose timer clock off issue." ++ depends on ARCH_RHEA || ARCH_SAMOA ++ help ++ Say Y if you want to enable the general purpose timer clock off fix ++ ++config GP_TIMER_COMPARATOR_LOAD_DELAY ++ bool "Enable the delay after loading general purpose timer compare register" ++ depends on ARCH_RHEA || ARCH_ISLAND || ARCH_SAMOA || ARCH_HANA || ARCH_NORTHSTAR || MACH_IPROC ++ default y ++ ++config IPROC_DCACHE_INVALIDATION ++ bool "Have Linux invalidate D-Cache" ++ default y ++ help ++ Say Y if you want Linux to invalidate primary core D-Cache during Linux ++ decompression and boot. ++ ++config IPROC_TIMER_UNIT_TESTS ++ bool "Include iProc Timer unit test code" ++ help ++ Say Y if you want to test the AON,Peripheral Timer modules using the sysfs interface ++ ++config IPROC_SW_RESET_RECORD ++ bool "Include Software Reset Records" ++ help ++ Say Y if you want to enable interface to access Software Reset Record. ++ Software Reset Record is a set of variables whose value could be retained ++ after reset (but will be cleared if powered off). ++ ++config BRCM_PROP_MODULES ++ bool "Include Broadcom proprietary modules" ++ default n ++ help ++ Say Y if you want to include the Broadcom proprietary modules. ++ ++config BCM_STM ++ bool "Enable System Trace Module" ++ default n ++ help ++ Say Y if you want to enable the Broadcom System Trace Module ++ ++config DMAC_PL330 ++ bool "PL330 DMAC driver support for Kona architecture" ++ depends on ARCH_RHEA ++ select PL330 ++ help ++ Support for PL330 DMA Controller driver for Rhea SOC/KONA architecture ++ ++config BCM_ZRELADDR ++ hex "Compressed ZREL address" ++ ++config BCM_PARAMS_PHYS ++ hex "Address where tagged parameters are to be found" ++ ++config BCM_RAM_BASE ++ hex "RAM base address" ++ help ++ Set the physical base address of RAM ++ ++config BCM_RAM_START_RESERVED_SIZE ++ hex "RAM start reserved memory size in bytes" ++ default 0 ++ help ++ Reserve memory at the start of RAM. This memory ++ may be used for LCD frame buffer, DSP, modem, etc. ++ ++#source "drivers/bcmdrivers/Kconfig" ++ ++endmenu +diff --git a/arch/arm/plat-iproc/Makefile b/arch/arm/plat-iproc/Makefile +new file mode 100644 +index 0000000..2474a9d diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch new file mode 100644 index 00000000..3d8ae55f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_Makefile.patch @@ -0,0 +1,23 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/Makefile +@@ -0,0 +1,17 @@ ++ ++ ++# obj-y := irq.o iproc_timer.o timer.o sysfs.o ++obj-y := irq.o timer-sp.o sysfs.o bcm5301x.o iproc-cache.o headsmp.o shm.o ++obj-$(CONFIG_SMP) += platsmp.o ++ ++ ++obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o ++obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o ++obj-$(CONFIG_USB_GADGET_DWC_OTG) += lm.o ++obj-$(CONFIG_HAVE_CLK) += clock.o ++obj-$(CONFIG_ARCH_IPROC) += iproc_cru.o ++obj-$(CONFIG_IPROC_SW_RESET_RECORD) += swreset_rec.o ++ ++export DRIVERS_MMC_HOST_DIR := drivers/mmc/host/ ++export DRIVERS_MTD_DIR := drivers/mtd/ ++# obj-y+=../../../../../bcmdrivers/ +diff --git a/arch/arm/plat-iproc/bcm5301x.c b/arch/arm/plat-iproc/bcm5301x.c +new file mode 100644 +index 0000000..87ae083 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch new file mode 100644 index 00000000..c17f2d9c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_bcm5301x.c.patch @@ -0,0 +1,90 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/bcm5301x.c +@@ -0,0 +1,84 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++void __init iproc_map_io(void) ++{ ++ struct map_desc desc ; ++ phys_addr_t base_addr; ++ ++ /* ++ * Cortex A9 Architecture Manual specifies this as a way to get ++ * MPCORE PERHIPHBASE address at run-time ++ */ ++ asm( "mrc p15,4,%0,c15,c0,0 @ Read Configuration Base Address Register" ++ : "=&r" (base_addr) : : "cc" ); ++ ++ printk(KERN_INFO "MPCORE found at %p\n", (void *)base_addr); ++ ++ /* Fix-map the entire PERIPHBASE 2*4K register block */ ++ desc.virtual = IPROC_PERIPH_VA; ++ desc.pfn = __phys_to_pfn(base_addr); ++ desc.length = SZ_8K; ++ desc.type = MT_DEVICE ; ++ ++ iotable_init(&desc, 1); ++} ++ ++static int iproc_data_abort_handler(unsigned long addr, unsigned int fsr, ++ struct pt_regs *regs) ++{ ++ /* ++ * These happen for no good reason ++ */ ++// printk(KERN_WARNING "Data abort at addr=%#lx, fsr=%#x ignored.\n", addr, fsr); ++ return 0; ++} ++ ++void __init iproc_enable_data_prefetch_aborts(void) ++{ ++ u32 x; ++ ++ /* Install our hook */ ++ hook_fault_code(16 + 6, iproc_data_abort_handler, SIGBUS, 0, ++ "imprecise external data abort"); ++ ++ /* Enable external aborts - clear "A" bit in CPSR */ ++ ++ /* Read CPSR */ ++// asm("mrs %0,cpsr": "=&r" (x) : : ); ++ asm("mrs %0,cpsr": "=&r" (x) ); ++ ++ x &= ~ PSR_A_BIT; ++ ++ /* Update CPSR, affect bits 8-15 */ ++ asm("msr cpsr_x,%0; nop; nop": : "r" (x) : "cc"); ++ ++} +diff --git a/arch/arm/plat-iproc/clock.c b/arch/arm/plat-iproc/clock.c +new file mode 100644 +index 0000000..98da8f5 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch new file mode 100644 index 00000000..de6a28ae --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_clock.c.patch @@ -0,0 +1,171 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/clock.c +@@ -0,0 +1,165 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++int clk_enable(struct clk *clk) ++{ ++ int ret ; ++ ++ ret = atomic_inc_return(&clk->ena_cnt); ++ if (ret > 1) ++ return 0; ++ /* Continue of count was moved from 0 to 1 - reentrant */ ++ if (clk->parent) ++ ret = clk_enable( clk->parent ); ++ else ++ ret = 0; ++ ++ if (ret == 0) { ++ if (!clk->ops || !clk->ops->enable) { ++ if (clk->rate) ++ ret = 0 ; ++ else { ++ if (clk_get_rate(clk)) ++ ret = 0; ++ else ++ ret = -EIO; ++ } ++ } else { ++ ret = clk->ops->enable(clk); ++ } ++ } ++ ++ if (ret != 0) ++ atomic_dec(&clk->ena_cnt); ++ ++ return ret ; ++} ++ ++EXPORT_SYMBOL(clk_enable); ++ ++void clk_disable(struct clk *clk) ++{ ++ int ret ; ++ ++ ret = atomic_dec_return(&clk->ena_cnt); ++ ++ /* Continue if this is the last client to disable - reentrant */ ++ if (ret > 0) ++ return ; ++ BUG_ON(ret < 0); ++ ++ if (!clk->ops || !clk->ops->disable) ++ return; ++ ++ clk->ops->disable(clk); ++ ++ if (clk->parent) ++ clk_disable(clk->parent); ++ ++ return ; ++} ++ ++EXPORT_SYMBOL(clk_disable); ++ ++unsigned long clk_get_rate(struct clk *clk) ++{ ++#ifndef CONFIG_MACH_CYGNUS ++ /* Recurse to update parent's frequency */ ++ if (clk->parent) ++ clk_get_rate(clk->parent); ++ ++ /* Read hardware registers if needed */ ++ if (clk->ops && clk->ops->status) ++ clk->ops->status(clk); ++#endif ++ ++#ifdef CONFIG_MACH_CYGNUS ++ printk(KERN_INFO "INFO-Cygnus:%d:%s() clk->name= %s clk->rate= %d\n", __LINE__, __func__, clk->name, clk->rate); ++#endif ++ return clk->rate; ++ ++} ++ ++EXPORT_SYMBOL(clk_get_rate); ++ ++long clk_round_rate(struct clk *clk, unsigned long rate) ++{ ++ long ret = -EIO; ++ ++ if (clk->ops && clk->ops->round) ++ ret = clk->ops->round(clk, rate); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(clk_round_rate); ++ ++int clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ int ret = -EIO; ++ ++ if (rate == clk->rate) ++ return 0; ++ ++ if (clk->ops && clk->ops->setrate) ++ ret = clk->ops->setrate(clk, rate); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(clk_set_rate); ++ ++/* ++ * clk_get(), clk_put() are implemented in arch/arm/common/clock.c ++ * but it needs these two stub functions for platform-specific operations. ++ * Reeturn 1 on success 0 on failure. ++ */ ++ ++int __clk_get(struct clk *clk) ++{ ++ int ret ; ++ ++ ret = atomic_inc_return( &clk->use_cnt ); ++ if (ret > 1) ++ return 1; ++ ++ if (clk->parent) ++ return __clk_get( clk->parent ); ++ ++ return 1; ++} ++ ++void __clk_put(struct clk *clk) ++{ ++ int ret; ++ ++ ret = atomic_dec_return( &clk->use_cnt); ++ if (ret > 0) ++ return; ++ ++ BUG_ON(ret < 0); ++ ++ if (clk->parent) ++ __clk_put(clk->parent); ++} +diff --git a/arch/arm/plat-iproc/headsmp.S b/arch/arm/plat-iproc/headsmp.S +new file mode 100644 +index 0000000..4cf0efa diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch new file mode 100644 index 00000000..fb9d8c07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_headsmp.S.patch @@ -0,0 +1,112 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/headsmp.S +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* Based on arch/arm/mach-realview/headsmp.S */ ++/* ++ * linux/arch/arm/mach-realview/headsmp.S ++ * ++ * Copyright (c) 2003 ARM Limited ++ * All Rights Reserved ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++/* ++ * This is called from head.S to fix the u-boot not initializing ++ * MMU and cache the way Linux likes it to be. I have talked to ++ * u-boot developer to fix it in u-boot. This will remain as a ++ * safety. Don't use r1 and r2 as u-boot/CFE may pass some parameters ++ * for the kernel. ++ * When this code completes execution, we expect the following: ++ * MMU = OFF ++ * D-Cache = OFF ++ * I-Cache = Don't Care ++ * regs r0 = 0 r1 = machine id and r2 = atags pointer or 0 ++ */ ++ __HEAD ++ENTRY(__iproc_head_fixup) ++ mov r12, lr @ Save the return address ++ mrc p15, 0, r8, c1, c0, 0 @ Read SCTLR ++ mrc p15, 0, r9, c1, c0, 1 @ Read ACTLR ++ mrc p15, 0, r10, c2, c0, 0 @ Read TTBR0 ++ mrc p15, 0, r11, c2, c0, 1 @ Read TTBR1 ++ mrc p15, 0, r7, c2, c0, 2 @ Read TTBCR ++ mov r0, r8 ++ bic r0, #CR_C||CR_M ++ mcr p15, 0, r0, c1, c0, 0 @ Write the control register ++ nop ++ mrc p15, 0, r0, c1, c0, 0 @ Read the control register ++ bic r0, #CR_C|CR_A|CR_M|CR_W ++ bic r0, #CR_I|CR_Z ++ mcr p15, 0, r0, c1, c0, 0 @ Write the control register ++ nop ++ mov r0, #0 ++ @ L2 cache controller control register ++ ldr r3, =IPROC_L2CC_REG_BASE ++ str r0, [r3, #0x100] @ Disable L2 cache ++ bl __v7_invalidate_dcache_all ++ ++ mov r0, #0 ++ mov pc, r12 @ Return for regular boot ++ nop ++ENDPROC(__iproc_head_fixup) ++ ++/* ++ * iProc specific entry point for secondary CPUs. This provides ++ * a "holding pen" into which all secondary cores are held until we're ++ * ready for them to initialise. ++ */ ++#ifdef CONFIG_SMP ++ENTRY(iproc_secondary_startup) ++#ifdef CONFIG_CPU_ENDIAN_BE8 ++ setend be ++#endif ++ bl v7_invalidate_l1 ++ bl v7_flush_dcache_all ++ mrc p15, 0, r0, c0, c0, 5 ++ and r0, r0, #15 ++ adr r4, 1f ++ ldmia r4, {r5, r6} ++ sub r4, r4, r5 ++ add r6, r6, r4 ++pen: ldr r7, [r6] ++ cmp r7, r0 ++ bne pen ++ ++ /* ++ * we've been released from the holding pen: secondary_stack ++ * should now contain the SVC stack for this core ++ */ ++ b secondary_startup ++ ++1: .long . ++ .long pen_release ++ ++ENDPROC(iproc_secondary_startup) ++#endif +diff --git a/arch/arm/plat-iproc/hotplug.c b/arch/arm/plat-iproc/hotplug.c +new file mode 100644 +index 0000000..94dd062 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch new file mode 100644 index 00000000..775242dd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_hotplug.c.patch @@ -0,0 +1,153 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/hotplug.c +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++extern volatile int pen_release; ++ ++static DECLARE_COMPLETION(cpu_killed); ++ ++static inline void cpu_enter_lowpower(void) ++{ ++ unsigned int v; ++ ++ flush_cache_all(); ++ asm volatile( ++ " mcr p15, 0, %1, c7, c5, 0\n" ++ " mcr p15, 0, %1, c7, c10, 4\n" ++ /* ++ * Turn off coherency ++ */ ++ " mrc p15, 0, %0, c1, c0, 1\n" ++ " bic %0, %0, #0x20\n" ++ " mcr p15, 0, %0, c1, c0, 1\n" ++ " mrc p15, 0, %0, c1, c0, 0\n" ++ " bic %0, %0, #0x04\n" ++ " mcr p15, 0, %0, c1, c0, 0\n" ++ : "=&r" (v) ++ : "r" (0) ++ : "cc"); ++} ++ ++static inline void cpu_leave_lowpower(void) ++{ ++ unsigned int v; ++ ++ asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" ++ " orr %0, %0, #0x04\n" ++ " mcr p15, 0, %0, c1, c0, 0\n" ++ " mrc p15, 0, %0, c1, c0, 1\n" ++ " orr %0, %0, #0x20\n" ++ " mcr p15, 0, %0, c1, c0, 1\n" ++ : "=&r" (v) ++ : ++ : "cc"); ++} ++ ++static inline void platform_do_lowpower(unsigned int cpu) ++{ ++ /* ++ * there is no power-control hardware on this platform, so all ++ * we can do is put the core into WFI; this is safe as the calling ++ * code will have already disabled interrupts ++ */ ++ for (;;) { ++ /* ++ * here's the WFI ++ */ ++ asm(".inst 0xe320f003\n" ++ : ++ : ++ : "memory", "cc"); ++ ++ if (pen_release == cpu) { ++ /* ++ * OK, proper wakeup, we're done ++ */ ++ break; ++ } ++ ++ /* ++ * getting here, means that we have come out of WFI without ++ * having been woken up - this shouldn't happen ++ * ++ * The trouble is, letting people know about this is not really ++ * possible, since we are currently running incoherently, and ++ * therefore cannot safely call printk() or anything else ++ */ ++#ifdef DEBUG ++ printk("CPU%u: spurious wakeup call\n", cpu); ++#endif ++ } ++} ++ ++int platform_cpu_kill(unsigned int cpu) ++{ ++ return wait_for_completion_timeout(&cpu_killed, 5000); ++} ++ ++/* ++ * platform-specific code to shutdown a CPU ++ * ++ * Called with IRQs disabled ++ */ ++void platform_cpu_die(unsigned int cpu) ++{ ++#ifdef DEBUG ++ unsigned int this_cpu = hard_smp_processor_id(); ++ ++ if (cpu != this_cpu) { ++ printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", ++ this_cpu, cpu); ++ BUG(); ++ } ++#endif ++ ++ printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); ++ complete(&cpu_killed); ++ ++ /* ++ * we're ready for shutdown now, so do it ++ */ ++ cpu_enter_lowpower(); ++ platform_do_lowpower(cpu); ++ ++ /* ++ * bring this CPU back into the world of cache ++ * coherency, and then restore interrupts ++ */ ++ cpu_leave_lowpower(); ++} ++ ++int platform_cpu_disable(unsigned int cpu) ++{ ++ /* ++ * we don't allow CPU 0 to be shutdown (it is still too special ++ * e.g. clock tick interrupts) ++ */ ++ return cpu == 0 ? -EPERM : 0; ++} +diff --git a/arch/arm/plat-iproc/include/mach/brcm_rdb_rng.h b/arch/arm/plat-iproc/include/mach/brcm_rdb_rng.h +new file mode 100644 +index 0000000..c17e951 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch new file mode 100644 index 00000000..38227ca9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch @@ -0,0 +1,70 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/brcm_rdb_rng.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __BRCM_RDB_RNG_H__ ++#define __BRCM_RDB_RNG_H__ ++ ++#define RNG_CTRL_OFFSET 0x00000000 ++#define RNG_CTRL_TYPE UInt32 ++#define RNG_CTRL_RESERVED_MASK 0xF00000CC ++#define RNG_CTRL_RNG_COMBLK2_OSC_DIS_SHIFT 22 ++#define RNG_CTRL_RNG_COMBLK2_OSC_DIS_MASK 0x0FC00000 ++#define RNG_CTRL_RNG_COMBLK1_OSC_DIS_SHIFT 16 ++#define RNG_CTRL_RNG_COMBLK1_OSC_DIS_MASK 0x003F0000 ++#define RNG_CTRL_RNG_JCLK_BYP_DIV_CNT_SHIFT 8 ++#define RNG_CTRL_RNG_JCLK_BYP_DIV_CNT_MASK 0x0000FF00 ++#define RNG_CTRL_RNG_JCLK_BYP_SRC_SHIFT 5 ++#define RNG_CTRL_RNG_JCLK_BYP_SRC_MASK 0x00000020 ++#define RNG_CTRL_RNG_JCLK_BYP_SEL_SHIFT 4 ++#define RNG_CTRL_RNG_JCLK_BYP_SEL_MASK 0x00000010 ++#define RNG_CTRL_RNG_RBG2X_SHIFT 1 ++#define RNG_CTRL_RNG_RBG2X_MASK 0x00000002 ++#define RNG_CTRL_RNG_RBGEN_SHIFT 0 ++#define RNG_CTRL_RNG_RBGEN_MASK 0x00000001 ++ ++#define RNG_STATUS_OFFSET 0x00000004 ++#define RNG_STATUS_TYPE UInt32 ++#define RNG_STATUS_RESERVED_MASK 0x00F00000 ++#define RNG_STATUS_RND_VAL_SHIFT 24 ++#define RNG_STATUS_RND_VAL_MASK 0xFF000000 ++#define RNG_STATUS_RNG_WARM_CNT_SHIFT 0 ++#define RNG_STATUS_RNG_WARM_CNT_MASK 0x000FFFFF ++ ++#define RNG_DATA_OFFSET 0x00000008 ++#define RNG_DATA_TYPE UInt32 ++#define RNG_DATA_RESERVED_MASK 0x00000000 ++#define RNG_DATA_RNG_NUM_SHIFT 0 ++#define RNG_DATA_RNG_NUM_MASK 0xFFFFFFFF ++ ++#define RNG_FF_THRES_OFFSET 0x0000000C ++#define RNG_FF_THRES_TYPE UInt32 ++#define RNG_FF_THRES_RESERVED_MASK 0xFFFFFFE0 ++#define RNG_FF_THRES_RNG_FF_THRESH_SHIFT 0 ++#define RNG_FF_THRES_RNG_FF_THRESH_MASK 0x0000001F ++ ++#define RNG_INT_MASK_OFFSET 0x00000010 ++#define RNG_INT_MASK_TYPE UInt32 ++#define RNG_INT_MASK_RESERVED_MASK 0xFFFFFFFE ++#define RNG_INT_MASK_RNG_INT_OFF_SHIFT 0 ++#define RNG_INT_MASK_RNG_INT_OFF_MASK 0x00000001 ++ ++#endif /* __BRCM_RDB_RNG_H__ */ +diff --git a/arch/arm/plat-iproc/include/mach/bridge-regs.h b/arch/arm/plat-iproc/include/mach/bridge-regs.h +new file mode 100644 +index 0000000..1d2299b diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch new file mode 100644 index 00000000..7b6375ab --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_bridge-regs.h.patch @@ -0,0 +1,74 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/bridge-regs.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Mbus-L to Mbus Bridge Registers ++ * ++ */ ++ ++#ifndef __ASM_ARCH_BRIDGE_REGS_H ++#define __ASM_ARCH_BRIDGE_REGS_H ++ ++#include ++ ++#define CPU_CONFIG (BRIDGE_VIRT_BASE | 0x0000) ++ ++#define CPU_CONTROL (BRIDGE_VIRT_BASE | 0x0104) ++#define CPU_CTRL_PCIE0_LINK 0x00000001 ++#define CPU_RESET 0x00000002 ++#define CPU_CTRL_PCIE1_LINK 0x00000008 ++ ++#define RSTOUTn_MASK (BRIDGE_VIRT_BASE | 0x0108) ++#define SOFT_RESET_OUT_EN 0x00000004 ++ ++#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE | 0x010c) ++#define SOFT_RESET 0x00000001 ++ ++#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE | 0x0110) ++#define BRIDGE_MASK (BRIDGE_VIRT_BASE | 0x0114) ++#define BRIDGE_INT_TIMER0 0x0002 ++#define BRIDGE_INT_TIMER1 0x0004 ++#define BRIDGE_INT_TIMER1_CLR (~0x0004) ++ ++#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0200) ++#define IRQ_CAUSE_LOW_OFF 0x0000 ++#define IRQ_MASK_LOW_OFF 0x0004 ++#define FIQ_MASK_LOW_OFF 0x0008 ++#define ENDPOINT_MASK_LOW_OFF 0x000c ++#define IRQ_CAUSE_HIGH_OFF 0x0010 ++#define IRQ_MASK_HIGH_OFF 0x0014 ++#define FIQ_MASK_HIGH_OFF 0x0018 ++#define ENDPOINT_MASK_HIGH_OFF 0x001c ++#define PCIE_INTERRUPT_MASK_OFF 0x0020 ++ ++#define IRQ_MASK_LOW (IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF) ++#define FIQ_MASK_LOW (IRQ_VIRT_BASE + FIQ_MASK_LOW_OFF) ++#define ENDPOINT_MASK_LOW (IRQ_VIRT_BASE + ENDPOINT_MASK_LOW_OFF) ++#define IRQ_MASK_HIGH (IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF) ++#define FIQ_MASK_HIGH (IRQ_VIRT_BASE + FIQ_MASK_HIGH_OFF) ++#define ENDPOINT_MASK_HIGH (IRQ_VIRT_BASE + ENDPOINT_MASK_HIGH_OFF) ++#define PCIE_INTERRUPT_MASK (IRQ_VIRT_BASE + PCIE_INTERRUPT_MASK_OFF) ++ ++#define POWER_MANAGEMENT (BRIDGE_VIRT_BASE | 0x011c) ++ ++#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/clkdev.h b/arch/arm/plat-iproc/include/mach/clkdev.h +new file mode 100644 +index 0000000..d77f186 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch new file mode 100644 index 00000000..6ea65748 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clkdev.h.patch @@ -0,0 +1,49 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/clkdev.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __MACH_CLKDEV_H ++#define __MACH_CLKDEV_H ++ ++#include ++#include ++ ++struct clk { ++ const struct clk_ops *ops; ++ const char *name; ++ atomic_t ena_cnt; ++ atomic_t use_cnt; ++ unsigned long rate; ++ unsigned gated :1; ++ unsigned fixed :1; ++ unsigned chan :6; ++ void __iomem *regs_base; ++ struct clk *parent; ++ /* TBD: could it have multiple parents to select from ? */ ++ enum { ++ CLK_XTAL, CLK_GATE, CLK_PLL, CLK_DIV, CLK_PHA ++ } type; ++}; ++ ++extern int __clk_get(struct clk *); ++extern void __clk_put(struct clk *); ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/clock.h b/arch/arm/plat-iproc/include/mach/clock.h +new file mode 100644 +index 0000000..3ad8a76 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch new file mode 100644 index 00000000..5018d5fc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_clock.h.patch @@ -0,0 +1,41 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/clock.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef CLOCK_H ++#define CLOCK_H ++ ++#include ++ ++/* ++ * Operations on clocks - ++ * See for description ++ */ ++struct clk_ops { ++ int (* enable)(struct clk *); ++ void (* disable)(struct clk *); ++ long (* round)(struct clk *, unsigned long); ++ int (* setrate)(struct clk *, unsigned long); ++ /* Update current rate and return running status */ ++ int (* status)(struct clk *); ++}; ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/common.h b/arch/arm/plat-iproc/include/mach/common.h +new file mode 100644 +index 0000000..69f8f95 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch new file mode 100644 index 00000000..0a644892 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_common.h.patch @@ -0,0 +1,57 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/common.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * ++ * Core functions for Broadcom Northstar SoC Chip ++ */ ++ ++#ifndef __ARCH_IPROC_COMMON_H ++#define __ARCH_IPROC_COMMON_H ++ ++struct mv643xx_eth_platform_data; ++struct mv_sata_platform_data; ++ ++extern struct sys_timer IPROC_timer; ++extern struct mbus_dram_target_info iproc_mbus_dram_info; ++ ++/* ++ * Basic IPROC init functions used early by machine-setup. ++ */ ++void IPROC_map_io(void); ++void IPROC_init(void); ++void IPROC_init_irq(void); ++void IPROC_setup_cpu_mbus(void); ++void IPROC_ge00_init(struct mv643xx_eth_platform_data *eth_data); ++void IPROC_sata_init(struct mv_sata_platform_data *sata_data); ++void IPROC_pcie_init(int init_port0, int init_port1); ++void IPROC_ehci0_init(void); ++void IPROC_ehci1_init(void); ++void IPROC_uart0_init(void); ++void IPROC_uart1_init(void); ++void IPROC_uart2_init(void); ++void IPROC_uart3_init(void); ++void IPROC_spi0_init(void); ++void IPROC_spi1_init(void); ++void IPROC_i2c_init(void); ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/debug-macro.S b/arch/arm/plat-iproc/include/mach/debug-macro.S +new file mode 100644 +index 0000000..6c963a4 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch new file mode 100644 index 00000000..dbb5963a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_debug-macro.S.patch @@ -0,0 +1,41 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/debug-macro.S +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Debugging macro include header ++ */ ++#include ++#include ++#include ++ ++ .macro addruart, tmp, tmp2, rx ++ ldr \tmp, =IPROC_UART_LLDEBUG_PA @ MMU off, Physical ++ ldr \tmp2, =IPROC_UART_LLDEBUG_VA @ MMU on, Virtual ++ .endm ++ ++#chandra: ++#ifdef CONFIG_MACH_CYGNUS ++ #define UART_SHIFT 2 //for synopsysUart has 4 byte addressing ++#else ++ #define UART_SHIFT 0 //for CCA_UART has 1 byte addressing ++#endif ++ ++#include +diff --git a/arch/arm/plat-iproc/include/mach/entry-macro.S b/arch/arm/plat-iproc/include/mach/entry-macro.S +new file mode 100644 +index 0000000..d859b49 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch new file mode 100644 index 00000000..e16ade85 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_entry-macro.S.patch @@ -0,0 +1,105 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/entry-macro.S +@@ -0,0 +1,99 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++ ++ .macro disable_fiq ++ .endm ++ ++ /* ++ * This is the interrupt handling part of the GIC code - ++ * the base_va exists in a variable, but here is defined ++ * at compile time for effeciency (?) ++ */ ++ ++ .macro get_irqnr_preamble, base, tmp ++ ldr \base, =IPROC_GICCPU_VA ++ .endm ++ ++ /* ++ * Interrupts 0-15 are IPI ++ * 16-31 are local ++ * 32-1020 are global ++ * 1021-1022 are reserved ++ * 1023 is "spurious" (no interrupt) ++ * ++ * Spurious interrupt must be ignored in all events. ++ * When in SMP mode, then IPI interrupts must be ignored here, ++ * amd picked up later with the test_for_ipi macro. ++ * When in SMP mode and local timers are enabled, ++ * the private timer/watchdog interrupt must be ignored here ++ * so it can be handled later in test_for_ltirq routine. ++ * ++ * A simple read from the controller will tell us the number of the ++ * highest priority enabled interrupt. We then just need to check ++ * whether it is in the range that must be handled. ++ * ++ * Upon return, Z=1 tells to ignore this interrupt ++ */ ++ ++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ++ ++ /* bits 12-10 = src CPU, 9-0 = int # */ ++ ldr \irqstat, [\base, #GIC_CPU_INTACK] ++ ldr \tmp, =1021 ++ ++ bic \irqnr, \irqstat, #0x1c00 ++ ++ /* Private timers to call do_local_timer() */ ++ cmp \irqnr, #29 ++ beq 29f ++ ++ /* SPI to call asm_do_IRQ(); IPI to call do_IPI() */ ++ cmp \irqnr, #15 ++ cmpcc \irqnr, \irqnr ++ cmpne \irqnr, \tmp ++ cmpcs \irqnr, \irqnr ++ ++ /* SPI if NE; IPI (0-15) or private timer (29) if EQ */ ++29: ++ .endm ++ ++ @code taken from realview/entry-macro.S ++ /* We assume that irqstat (the raw value of the IRQ acknowledge ++ * register) is preserved from the macro above. ++ * If there is an IPI, we immediately signal end of interrupt on the ++ * controller, since this requires the original irqstat value which ++ * we won't easily be able to recreate later. ++ */ ++ .macro test_for_ipi, irqnr, irqstat, base, tmp ++ bic \irqnr, \irqstat, #0x1c00 ++ cmp \irqnr, #16 ++ strcc \irqstat, [\base, #GIC_CPU_EOI] ++ cmpcs \irqnr, \irqnr ++ .endm ++ ++ .macro test_for_ltirq, irqnr, irqstat, base,tmp ++ bic \irqnr, \irqstat, #0x1c00 ++ mov \tmp, #0 ++ cmp \irqnr, #29 ++ moveq \tmp, #1 ++ streq \irqstat, [\base, #GIC_CPU_EOI] ++ cmp \tmp, #0 ++ .endm ++ ++ .macro arch_ret_to_user, tmp1, tmp2 ++ .endm +diff --git a/arch/arm/plat-iproc/include/mach/gpio.h b/arch/arm/plat-iproc/include/mach/gpio.h +new file mode 100644 +index 0000000..326b73c diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch new file mode 100644 index 00000000..811aa9ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_gpio.h.patch @@ -0,0 +1,36 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/gpio.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_GPIO_H ++#define __PLAT_GPIO_H ++ ++#include ++#include ++ ++#include ++ ++ ++#define gpio_to_irq(gpio) __gpio_to_irq(gpio) ++//#define gpio_get_value(gpio) __gpio_get_value(gpio) ++//#define gpio_set_value(gpio,value) __gpio_set_value(gpio,value) ++//#define gpio_cansleep(gpio) __gpio_cansleep(gpio) ++ ++#endif +diff --git a/arch/arm/plat-iproc/include/mach/hardware.h b/arch/arm/plat-iproc/include/mach/hardware.h +new file mode 100644 +index 0000000..b373b58 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch new file mode 100644 index 00000000..9baa1080 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_hardware.h.patch @@ -0,0 +1,49 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/hardware.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_HARDWARE_H ++#define __PLAT_IPROC_HARDWARE_H ++ ++#include ++#include ++#include ++ ++/* Hardware addresses of major areas. ++ * *_START is the physical address ++ * *_SIZE is the size of the region ++ * *_BASE is the virtual address ++ */ ++#define RAM_START PHYS_OFFSET ++ ++#define RAM_BASE PAGE_OFFSET ++ ++#define IO_START IO_START_PA ++#define IO_BASE IO_START_VA ++ ++/* In case we use physical addresses */ ++#define IO_ADDRESS(x) (x) ++ ++#define pcibios_assign_all_busses() 1 ++ ++#define PCIBIOS_MIN_IO 0x1000 ++#define PCIBIOS_MIN_MEM 0x01000000 ++ ++#endif /* __PLAT_IPROC_HARDWARE_H */ +diff --git a/arch/arm/plat-iproc/include/mach/io.h b/arch/arm/plat-iproc/include/mach/io.h +new file mode 100644 +index 0000000..b980406 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch new file mode 100644 index 00000000..51ae7c3f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_io.h.patch @@ -0,0 +1,41 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/io.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_IO_H ++#define __PLAT_IPROC_IO_H ++ ++#define IO_SPACE_LIMIT (0xffffffff) ++ ++#define __io(a) __typesafe_io(a) ++#define __mem_pci(a) (a) ++ ++#ifdef __ASSEMBLER__ ++#define IOMEM(x) (x) ++#else ++#define IOMEM(x) ((void __force __iomem *)(x)) ++#endif ++ ++#define VC_DIRECT_ACCESS_BASE 0xC0000000UL ++#define ARM_VC_PHYS_ADDR_BASE 0x40000000UL ++#define __VC_BUS_TO_ARM_PHYS_ADDR(x) ((x) - (VC_DIRECT_ACCESS_BASE) + \ ++ (ARM_VC_PHYS_ADDR_BASE)) ++ ++#endif /*__PLAT_IPROC_IO_H */ +diff --git a/arch/arm/plat-iproc/include/mach/iproc.h b/arch/arm/plat-iproc/include/mach/iproc.h +new file mode 100644 +index 0000000..bf01f6e diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch new file mode 100644 index 00000000..1d561ecd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc.h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/iproc.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_H ++#define __PLAT_IPROC_H ++ ++#include ++ ++extern struct sys_timer iproc_timer; ++ ++extern void __init iproc_init_irq(void); ++//static void __init gic_dist_init(struct gic_chip_data *gic); ++ ++#endif /* __PLAT_IPROC_H */ +diff --git a/arch/arm/plat-iproc/include/mach/iproc_timer.h b/arch/arm/plat-iproc/include/mach/iproc_timer.h +new file mode 100644 +index 0000000..5809403 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch new file mode 100644 index 00000000..609e8db9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_iproc_timer.h.patch @@ -0,0 +1,154 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/iproc_timer.h +@@ -0,0 +1,148 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_TIMER_H ++#define __PLAT_IPROC_TIMER_H ++ ++/* Timer module specific data structures */ ++enum timer_rate { ++ KHZ_32 = 0, ++ MHZ_1, ++ MHZ_19_5, ++}; ++ ++struct iproc_timer; ++ ++/* Channel specific data structures */ ++typedef int (*intr_callback)(void *data); ++ ++enum timer_mode { ++ MODE_PERIODIC=0, ++ MODE_ONESHOT, ++}; ++ ++struct timer_ch_cfg { ++ void *arg; ++ enum timer_mode mode; ++ intr_callback cb; ++ unsigned long reload; /* Holds the reload value in ++ * case of periodic timers ++ */ ++}; ++ ++/* Timer Module related APIs */ ++ ++/* ++ * USAGE OF THIS APIs ++ * ------------------ ++ * From the board specific file, the iproc_timer_modules_init will be called ++ * After that it will call the init function of timer.c and will pass the ++ * following information in a platform structure ++ * 1) Timer name to be used as system timer ++ * 2) Frequency to be configured for system timer ++ * 3) The channel of the timer to use as clock source (optional) ++ * 4) The channel of the timer to use as clock event (optional) ++ * ++ * from the init function of timer.c iproc_timer_modules_set_rate will be called ++ * to set the system timer frequency. ++ * Then the appropriate channels would be setup for clock source/event by ++ * calling iproc_timer_request() ++ */ ++ ++/* ++ * iproc_timer_modules_init - Initialize the data structures ++ * that depcits the iProc timer modules ++ */ ++void iproc_timer_modules_init (void); ++ ++/* ++ * iproc_timer_module_set_rate - Set the speed in which a timer module should count ++ * name - Name of the Timer to configure ++ * rate - Speed ++ */ ++int iproc_timer_module_set_rate(char* name, enum timer_rate); ++ ++/* ++ * iproc_timer_module_get_rate - Get the speed in which a timer module is running ++ * name - Name of the Timer module ++ */ ++int iproc_timer_module_get_rate (char* name); ++ ++ ++/* Channel/Timer related APIs */ ++/* ++ * iproc_timer_request - Get access to a channel in the given timer ++ * name - Name of the Timer module ++ * channel - Channel number requested. If this is -1 then by default ++ * the next available channel will be returned ++ */ ++struct iproc_timer* iproc_timer_request(char* name, int channel); ++ ++/* ++ * iproc_timer_config - Configure the following parameters of the timer ++ * 1) mode of the timer - periodic/one shot ++ * 2) call back function that will be called from the ISR context ++ * 3) context to be passed back in the call back function ++ * ++ * pit - iProc timer context (returned by iproc_timer_request()) ++ * pcfg - pointer to the configuration structure ++ */ ++int iproc_timer_config (struct iproc_timer *pit, struct timer_ch_cfg *pcfg); ++ ++/* ++ * iproc_timer_set_match_start - Set the match register for the timer and start ++ * counting ++ * ++ * pit - iProc timer context (returned by iproc_timer_request()) ++ * load - The load value to be programmed. This function will internally ++ * add this value to the current counter and program the resultant in the ++ * match register. Once the timer is started when the counter ++ * reaches this value an interrupt will be raised ++ */ ++int iproc_timer_set_match_start (struct iproc_timer* pit, unsigned int load); ++ ++/* ++ * iproc_timer_free - Read the counter register of the timer ++ * ++ * pit - Timer context to be freed. ++ * msw - pointer to the Most Significant Word (32 bits) ++ * lsw - pointer to the Leas Significant Word (32 bits) ++ */ ++int iproc_timer_get_counter(struct iproc_timer* pit, ++ unsigned long *msw, unsigned long *lsw); ++/* ++ * iproc_timer_disable_and_clear - Disable the timer and clear the ++ * interrupt ++ * ++ * pit - Timer context to be freed. ++ */ ++int iproc_timer_disable_and_clear(struct iproc_timer *pit); ++ ++/* ++ * iproc_timer_stop - Stop the timer. ++ * ++ * pit - The timer context to be stopped. ++ */ ++int iproc_timer_stop (struct iproc_timer* pit); ++ ++/* ++ * iproc_timer_free - Release the timer, after this call the timer can be used ++ * again by others. ++ * ++ * pit - Timer context to be freed. ++ */ ++int iproc_timer_free (struct iproc_timer* pit); ++ ++#endif /* __PLAT_IPROC_TIMER_H */ +diff --git a/arch/arm/plat-iproc/include/mach/irqs.h b/arch/arm/plat-iproc/include/mach/irqs.h +new file mode 100644 +index 0000000..4078b05 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch new file mode 100644 index 00000000..6b781664 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_irqs.h.patch @@ -0,0 +1,255 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/irqs.h +@@ -0,0 +1,249 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_IRQS_H ++#define __PLAT_IPROC_IRQS_H ++ ++#define IRQ_LOCALTIMER BCM_INT_ID_PPI13 ++#define BCM_INT_PRIORITY_MAX 32 /* there are only 32 priority are supported */ ++#define BCM_INT_SPI_MAX 128 /* there are 128 shared peripheral interrupt*/ ++/*=====================================================================*/ ++/* Software Trigger Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_STI0 0 ++#define BCM_INT_ID_STI1 1 ++#define BCM_INT_ID_STI2 2 ++#define BCM_INT_ID_STI3 3 ++#define BCM_INT_ID_STI4 4 ++#define BCM_INT_ID_STI5 5 ++#define BCM_INT_ID_STI6 6 ++#define BCM_INT_ID_STI7 7 ++#define BCM_INT_ID_STI8 8 ++#define BCM_INT_ID_STI9 9 ++#define BCM_INT_ID_STI10 10 ++#define BCM_INT_ID_STI11 11 ++#define BCM_INT_ID_STI12 12 ++#define BCM_INT_ID_STI13 13 ++#define BCM_INT_ID_STI14 14 ++#define BCM_INT_ID_STI15 15 ++#define BCM_INT_ID_STI_MAX 16 /* terminating ID */ ++ ++/*=====================================================================*/ ++/* Private Peripheral Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_PPI0 ( 0 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI1 ( 1 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI2 ( 2 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI3 ( 3 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI4 ( 4 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI5 ( 5 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI6 ( 6 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI7 ( 7 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI8 ( 8 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI9 ( 9 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI10 (10 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI11 (11 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI12 (12 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI13 (13 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI14 (14 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI15 (15 + BCM_INT_ID_STI_MAX) ++#define BCM_INT_ID_PPI_MAX (16 + BCM_INT_ID_STI_MAX) /* terminating ID */ ++ ++/*=====================================================================*/ ++/* iHost Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_IHOST_L2CC 32 ++#define BCM_INT_ID_IHOST_PWRWDOG 33 ++#define BCM_INT_ID_IHOST_TRAP8 34 ++#define BCM_INT_ID_IHOST_TRAP1 35 ++#define BCM_INT_ID_IHOST_COMMTX 36 ++#define BCM_INT_ID_IHOST_COMMRX 38 ++#define BCM_INT_ID_IHOST_PMU 40 ++#define BCM_INT_ID_IHOST_CT 42 ++#define BCM_INT_ID_IHOST_DEFFLG_CPU0 44 ++#define BCM_INT_ID_IHOST_DEFFLG_CPU1 45 ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define BCM_INT_ID_IHOST_CPU0_PAR 46 ++#define BCM_INT_ID_IHOST_CPU1_PAR 47 ++#define BCM_INT_ID_IHOST_SCU0_PAR 48 ++#define BCM_INT_ID_IHOST_SCU1_PAR 49 ++#define BCM_INT_ID_IHOST_I2_SEC 50 ++#define BCM_INT_ID_IHOST_MAX 51 /* terminating ID */ ++#else ++#define BCM_INT_ID_IHOST_MAX 46 /* terminating ID */ ++#endif ++ ++ ++/*=====================================================================*/ ++/* IDM Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_IHOST_M1 ( 0 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE0_M0 ( 1 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE1_M0 ( 2 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE2_M0 ( 3 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DMA_M0 ( 4 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M0 ( 5 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M1 ( 6 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M2 ( 7 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_AMAC_M3 ( 8 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_USBH_M0 ( 9 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_USBH_M1 (10 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_SDIO_M0 (11 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_I2S_M0 (12 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_A9JTAG_M0 (13 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_INIT_SEQ_M0 (14 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_JTAG_M0 (15 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IHOST_ACP (16 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IHOST_S0 (17 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DDR_S1 (18 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DDR_S2 (19 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE0_S0 (20 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE1_S0 (21 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_PCIE2_S0 (22 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_ROM_S0 (23 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_NAND_S0 (24 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_QPSI_S0 (25 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_A9JTAG_S0 (26 + BCM_INT_ID_IHOST_MAX) ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define BCM_INT_ID_SATA_S0 (27 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_SRAM_S0 (28+ BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBW (29 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBX (30 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBY (31 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_APBZ (32 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_0 (33 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_1 (34 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_2 (35 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_3 (36 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_4 (37 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IDM_MAX (38 + BCM_INT_ID_IHOST_MAX) ++#elif defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++#define BCM_INT_ID_APBX (27 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_0 (28 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_1 (29 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_2 (30 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_3 (31 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_DS_4 (32 + BCM_INT_ID_IHOST_MAX) ++#define BCM_INT_ID_IDM_MAX (33 + BCM_INT_ID_IHOST_MAX) ++#endif ++ ++/*=====================================================================*/ ++/* DDR Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_DDR_CONT (0 + BCM_INT_ID_IDM_MAX) ++#define BCM_INT_ID_DDR_MAX (1 + BCM_INT_ID_IDM_MAX) ++ ++/*=====================================================================*/ ++/* DMAC Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_DMAC (0 + BCM_INT_ID_DDR_MAX) ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define BCM_INT_ID_DMAC_ABORT (16 + BCM_INT_ID_DDR_MAX) ++#define BCM_INT_ID_DMAC_MAX (17 + BCM_INT_ID_DDR_MAX) ++#elif defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++#define BCM_INT_ID_DMAC_MAX (16 + BCM_INT_ID_DDR_MAX) ++#endif ++ ++/*=====================================================================*/ ++/* NAND Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_NAND2CORE_RD_MISS ( 0 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ER_COMP ( 1 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_CB_COMP ( 2 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_PP_COMP ( 3 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ROCTL_RDY ( 4 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_NAND_RBB ( 5 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ECC_MIPS_UNCOR ( 6 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_ECC_MIPS_COR ( 7 + BCM_INT_ID_DMAC_MAX) ++#define BCM_INT_ID_NAND2CORE_MAX ( 8 + BCM_INT_ID_DMAC_MAX) ++ ++/*=====================================================================*/ ++/* QPSI Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_QPSI2CORE_FULL_RCHD ( 0 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_TRUNCATED ( 1 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_IMAPTIENT ( 2 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_SES_DONE ( 3 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_OVERREAD ( 4 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_MPSI_DONE ( 5 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_MPSI_HLT_SET ( 6 + BCM_INT_ID_NAND2CORE_MAX) ++#define BCM_INT_ID_QPSI2CORE_MAX ( 7 + BCM_INT_ID_NAND2CORE_MAX) ++ ++/*=====================================================================*/ ++/* USB2 Host Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_USB2H2CORE_USB2_INT (0 + BCM_INT_ID_QPSI2CORE_MAX) ++#define BCM_INT_ID_USB2H2CORE_MAX (1 + BCM_INT_ID_QPSI2CORE_MAX) ++ ++/*=====================================================================*/ ++/* USB3 Host Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_USB3H2CORE_USB2_INT0 (0 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_INT1 (1 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_INT2 (2 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_INT3 (3 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_USB2_HSE (4 + BCM_INT_ID_USB2H2CORE_MAX) ++#define BCM_INT_ID_USB3H2CORE_MAX (5 + BCM_INT_ID_USB2H2CORE_MAX) ++ ++/*=====================================================================*/ ++/* CCA Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_CCA_INT (0 + BCM_INT_ID_USB3H2CORE_MAX) ++#define BCM_INT_ID_CCA_MAX (1 + BCM_INT_ID_USB3H2CORE_MAX) ++ ++/*=====================================================================*/ ++/* CCB Interrupt IDs */ ++/*=====================================================================*/ ++#define BCM_INT_ID_CCB_UART0 (0 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GPIO (1 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_I2S (2 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_SMBUS (3 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM0_INT1 (4 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM0_INT2 (5 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM1_INT1 (6 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_TIM1_INT2 (7 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_RNG (8 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_SW_SOC (9 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_PCIE_INT0 (10 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_PCIE_INT1 (11 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_PCIE_INT2 (12 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_SDIO2CORE (13 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_CTF (14 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT0 (15 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT1 (16 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT2 (17 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_GMAC_INT3 (18 + BCM_INT_ID_CCA_MAX) ++#define BCM_INT_ID_CCB_MAX (19 + BCM_INT_ID_CCA_MAX) ++ ++#define BCM_INT_ID_FA 178 ++ ++ ++#ifdef CONFIG_ARCH_REQUIRE_GPIOLIB ++#define IPROC_NR_IRQS (256) ++#define IPROC_IRQ_GPIO_0 (IPROC_NR_IRQS) ++#define IPROC_NR_GPIO_IRQS (32 + 4) ++#ifdef CONFIG_MACH_CYGNUS ++ #define NR_IRQS 256 ++#else ++#define NR_IRQS (IPROC_NR_IRQS + IPROC_NR_GPIO_IRQS) ++#endif ++#else ++#define NR_IRQS 256 ++#endif ++ ++#endif /* __PLAT_IPROC_IRQS_H */ +diff --git a/arch/arm/plat-iproc/include/mach/lm.h b/arch/arm/plat-iproc/include/mach/lm.h +new file mode 100644 +index 0000000..5c550a8 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch new file mode 100644 index 00000000..5fe5c287 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_lm.h.patch @@ -0,0 +1,54 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/lm.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _LM_DEVICE_H_ ++#define _LM_DEVICE_H_ ++ ++#include ++#include ++ ++ ++struct lm_device { ++ struct device dev; ++ struct resource resource; ++ unsigned int irq; ++ unsigned int id; ++}; ++ ++struct lm_driver { ++ struct device_driver drv; ++ int (*probe) (struct lm_device *); ++ void (*remove) (struct lm_device *); ++ int (*suspend) (struct lm_device *, pm_message_t); ++ int (*resume) (struct lm_device *); ++}; ++ ++int lm_driver_register(struct lm_driver *drv); ++void lm_driver_unregister(struct lm_driver *drv); ++ ++int lm_device_register(struct lm_device *dev); ++void lm_device_unregister(struct lm_device *dev); ++ ++#define lm_get_drvdata(lm) dev_get_drvdata(&(lm)->dev) ++#define lm_set_drvdata(lm,d) dev_set_drvdata(&(lm)->dev, d) ++ ++#endif /* _LM_DEVICE_H_ */ +diff --git a/arch/arm/plat-iproc/include/mach/memory.h b/arch/arm/plat-iproc/include/mach/memory.h +new file mode 100644 +index 0000000..87bee64 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch new file mode 100644 index 00000000..eadc8b6b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_memory.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/memory.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __PLAT_IPROC_MEMORY_H ++#define __PLAT_IPROC_MEMORY_H ++ ++#include ++ ++//#define PHYS_OFFSET (CONFIG_BCM_RAM_BASE+CONFIG_BCM_RAM_START_RESERVED_SIZE) ++ ++/* BCM5301x Reference Guide (Section 3) defines three regions of IO memory, ++ * CORE, IDM, and ARMCORE. The CORE and IDM regions are contiguous, so they ++ * are combined into a single region for mapping and translation purposes ++ */ ++ ++#define IO_CORE_IDM_PA 0x18000000 ++#define IO_CORE_IDM_SIZE 0x200000 ++#define IO_ARMCORE_PA 0x19000000 ++#define IO_ARMCORE_SIZE 0x100000 ++#define IO_SMAU_IDM_PA 0xf8100000 ++#define IO_SMAU_IDM_SIZE 0x100000 ++ ++#define IO_TOTAL_SIZE (IO_CORE_IDM_SIZE + \ ++ IO_ARMCORE_SIZE + \ ++ IO_SMAU_IDM_SIZE) ++ ++/* VA should be in the range of VMALLOC_START ~ VMALLOC_END-1 */ ++#define IO_CORE_IDM_VA (VMALLOC_END - IO_TOTAL_SIZE) ++#define IO_ARMCORE_VA (IO_CORE_IDM_VA + IO_CORE_IDM_SIZE) ++#define IO_SMAU_IDM_VA (IO_ARMCORE_VA + IO_ARMCORE_SIZE) ++ ++#define IO_CORE_IDM_PV_DELTA (IO_CORE_IDM_VA - IO_CORE_IDM_PA) ++#define IO_ARMCORE_PV_DELTA (IO_ARMCORE_VA - IO_ARMCORE_PA) ++#define IO_SMAU_IDM_PV_DELTA (IO_SMAU_IDM_VA - IO_SMAU_IDM_PA) ++ ++#define HW_IO_VIRT_TO_PHYS(virt) \ ++ (((virt) < IO_ARMCORE_VA) ? \ ++ ((virt) - IO_CORE_IDM_PV_DELTA) : \ ++ (((virt) < IO_SMAU_IDM_VA) ? \ ++ ((virt) - IO_ARMCORE_PV_DELTA) : \ ++ ((virt) - IO_SMAU_IDM_PV_DELTA))) ++ ++/* ++ * HW_IO_PHYS_TO_VIRT used in asm, so the macro that performs this conversion ++ * is written using only simple math so that the assembler's constant folding ++ * can produce the correct result. ++ ++ #define HW_IO_PHYS_TO_VIRT(phys) \ ++ (((phys) < IO_ARMCORE_PA) ? \ ++ ((phys) + IO_CORE_IDM_PV_DELTA) : \ ++ ((phys) + IO_ARMCORE_PV_DELTA)) ++ */ ++ ++#define HW_IO_PHYS_TO_VIRT(phys) \ ++ (((phys) + IO_CORE_IDM_PV_DELTA) + \ ++ (((phys) >= IO_ARMCORE_PA) * (IO_ARMCORE_PV_DELTA - IO_CORE_IDM_PV_DELTA)) + \ ++ (((phys) >= IO_SMAU_IDM_PA) * (IO_SMAU_IDM_PV_DELTA - IO_ARMCORE_PV_DELTA))) ++ ++#define CONSISTENT_DMA_SIZE SZ_128M ++ ++#ifndef PHYS_RAM_SIZE ++#define PHYS_RAM_SIZE 0x08000000 ++#endif ++ ++#endif /* __PLAT_IPROC_MEMORY_H */ +diff --git a/arch/arm/plat-iproc/include/mach/sdio_platform.h b/arch/arm/plat-iproc/include/mach/sdio_platform.h +new file mode 100644 +index 0000000..f8f17e1 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch new file mode 100644 index 00000000..c65d3a3e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_sdio_platform.h.patch @@ -0,0 +1,73 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/sdio_platform.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _SDIO_PLATFORM_H ++#define _SDIO_PLATFORM_H ++ ++/* ++ * SDIO device type ++ */ ++enum sdio_devtype { ++ SDIO_DEV_TYPE_SDMMC = 0, ++ SDIO_DEV_TYPE_WIFI, ++ SDIO_DEV_TYPE_EMMC, ++ ++ /* used for internal array indexing, DO NOT modify */ ++ SDIO_DEV_TYPE_MAX, ++}; ++ ++/* ++ * SDIO WiFi GPIO configuration ++ */ ++struct sdio_wifi_gpio_cfg { ++ int reset; ++ int shutdown; ++ int reg; ++ int host_wake; ++}; ++ ++struct sdio_platform_cfg { ++ /* specify which SDIO device */ ++ unsigned id; ++ ++ /* ++ * For boards without the SDIO pullup registers, data_pullup needs to set ++ * to 1 ++ */ ++ unsigned int data_pullup; ++ ++ /* for devices with 8-bit lines */ ++ int is_8bit; ++ ++ /* card detection GPIO, required for SD/MMC */ ++ int cd_gpio; ++ enum sdio_devtype devtype; ++ ++ /* clocks */ ++ char *peri_clk_name; ++ char *ahb_clk_name; ++ char *sleep_clk_name; ++ unsigned long peri_clk_rate; ++ ++ struct sdio_wifi_gpio_cfg wifi_gpio; ++}; ++ ++#endif /* SDIO_PLATFORM_H */ +diff --git a/arch/arm/plat-iproc/include/mach/smp.h b/arch/arm/plat-iproc/include/mach/smp.h +new file mode 100644 +index 0000000..5a4b1f4 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch new file mode 100644 index 00000000..16cfc53f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_smp.h.patch @@ -0,0 +1,48 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/smp.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * derived from arch/arm/mach-realview/include/mach/smp.h ++ */ ++ ++#ifndef __ASM_ARCH_SMP_H ++#define __ASM_ARCH_SMP_H __FILE__ ++ ++#include ++ ++/* ++ * set_event() is used to wake up secondary core from wfe using sev. ROM ++ * code puts the second core into wfe(standby). ++ * ++ */ ++#define set_event() __asm__ __volatile__ ("sev" : : : "memory") ++ ++extern void iproc_secondary_startup(void); ++ ++#define hard_smp_processor_id() \ ++ ({ \ ++ unsigned int cpunum; \ ++ __asm__("mrc p15, 0, %0, c0, c0, 5" \ ++ : "=r" (cpunum)); \ ++ cpunum &= 0x0F; \ ++ }) ++ ++#endif /* __ASM_ARCH_SMP_H */ +diff --git a/arch/arm/plat-iproc/include/mach/system.h b/arch/arm/plat-iproc/include/mach/system.h +new file mode 100644 +index 0000000..bdabd06 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch new file mode 100644 index 00000000..5e307d63 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_system.h.patch @@ -0,0 +1,42 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/system.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_IPROC_SYSTEM_H ++#define __PLAT_IPROC_SYSTEM_H ++ ++#include ++#include ++ ++ ++static void arch_idle(void) ++{ ++ /* ++ * This should do all the clock switching ++ * and wait for interrupt tricks ++ */ ++ cpu_do_idle(); ++} ++ ++static inline void arch_reset(char mode, const char *cmd) ++{ ++} ++ ++#endif /*__PLAT_IPROC_SYSTEM_H */ +diff --git a/arch/arm/plat-iproc/include/mach/timer.h b/arch/arm/plat-iproc/include/mach/timer.h +new file mode 100644 +index 0000000..1b28414 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch new file mode 100644 index 00000000..d9cf6991 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timer.h.patch @@ -0,0 +1,55 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/timer.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_TIMER_H ++#define __PLAT_TIMER_H ++ ++#ifdef __KERNEL__ ++ ++typedef unsigned int timer_tick_count_t; ++typedef unsigned int timer_tick_rate_t; ++typedef unsigned int timer_msec_t; ++ ++ ++enum gp_timer_rate { ++ GPT_KHZ_32 = 0, ++ GPT_MHZ_1, ++}; ++ ++/** ++ * timer configuration identifying the timer to use ++ * as system timer (GP Timer) ++ */ ++ struct gp_timer_setup { ++ char *name; ++ int ch_num; ++ enum gp_timer_rate rate; ++ }; ++ ++void iproc_timer_init (struct gp_timer_setup *gpt); ++ ++timer_tick_count_t timer_get_tick_count(void); ++timer_tick_rate_t timer_get_tick_rate(void); ++timer_msec_t timer_get_msec(void); ++timer_msec_t timer_ticks_to_msec(timer_tick_count_t ticks); ++ ++#endif /* __KERNEL__ */ ++#endif /* __PLAT_TIMER_H */ +diff --git a/arch/arm/plat-iproc/include/mach/timex.h b/arch/arm/plat-iproc/include/mach/timex.h +new file mode 100644 +index 0000000..265c48b diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch new file mode 100644 index 00000000..62f00537 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_timex.h.patch @@ -0,0 +1,31 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/timex.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __PLAT_IPROC_TIMEX_H ++#define __PLAT_IPROC_TIMEX_H ++ ++/* ++ * Not very sure what the clock rate is. Revisit later ++*/ ++#define CLOCK_TICK_RATE (351875) ++ ++#endif /* __PLAT_IPROC_TIMEX_H */ +diff --git a/arch/arm/plat-iproc/include/mach/uncompress.h b/arch/arm/plat-iproc/include/mach/uncompress.h +new file mode 100644 +index 0000000..19002a6 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch new file mode 100644 index 00000000..957a06da --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_mach_uncompress.h.patch @@ -0,0 +1,60 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/mach/uncompress.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __ASM_ARCH_UNCOMPRESS_H ++#define __ASM_ARCH_UNCOMPRESS_H ++ ++#include ++#include ++ ++#define IPROC_UART0_PA IPROC_CCA_UART0_REG_BASE ++#define UART0_LSR_OFFSET 0x14 ++#define UART0_RBR_THR_DLL_OFFSET 0x00 ++#define UART0_LSR_THRE_MASK 0x60 ++#define UART0_LSR_TEMT_MASK 0x40 ++ ++static inline void putc(int c) ++{ ++ /* ++ * data should be written to THR register only ++ * if THRE (LSR bit5) is set) ++ */ ++ while (0 == (__raw_readl(IPROC_UART0_PA + ++ UART0_LSR_OFFSET) & UART0_LSR_THRE_MASK )) ++ { ++ } ++ ++ __raw_writel((unsigned long)c, IPROC_UART0_PA + UART0_RBR_THR_DLL_OFFSET); ++} ++ ++static inline void flush(void) ++{ ++ /* Wait for the tx fifo to be empty and last char to be sent */ ++ while (0 == (__raw_readl(IPROC_UART0_PA + ++ UART0_LSR_OFFSET) & UART0_LSR_TEMT_MASK )) ++ { ++ } ++} ++ ++#define arch_decomp_setup() ++#define arch_decomp_wdog() ++ ++#endif /* __ASM_ARCH_UNCOMPRESS_H */ +diff --git a/arch/arm/plat-iproc/include/plat/dma-pl330.h b/arch/arm/plat-iproc/include/plat/dma-pl330.h +new file mode 100644 +index 0000000..bf45e7b diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch new file mode 100644 index 00000000..b500b554 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma-pl330.h.patch @@ -0,0 +1,109 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/dma-pl330.h +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_DMA_H ++#define __PLAT_DMA_H ++ ++#include ++ ++#define MAX_CHAN_NAME_LENGTH 32 ++ ++/* DMA direction control */ ++enum dma_direction { ++ DMA_DIRECTION_MEM_TO_MEM = 0, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC = 1, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI = 2, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC = 3, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI = 4, ++ DMA_DIRECTION_DEV_TO_DEV = 5 /* Invalid, unsupported */ ++}; ++#define DMA_DIRECTION_MASK 0x7 ++ ++/* Channel configurations definition */ ++#define DMA_CFG_SRC_ADDR_FIXED (0x0 << 0) ++#define DMA_CFG_SRC_ADDR_INCREMENT (0x1 << 0) ++#define DMA_CFG_DST_ADDR_FIXED (0x0 << 14) ++#define DMA_CFG_DST_ADDR_INCREMENT (0x1 << 14) ++ ++#define DMA_CFG_BURST_SIZE_MASK (0x7 << 1) ++#define DMA_CFG_BURST_SIZE_1 (0x0 << 1) ++#define DMA_CFG_BURST_SIZE_2 (0x1 << 1) ++#define DMA_CFG_BURST_SIZE_4 (0x2 << 1) ++#define DMA_CFG_BURST_SIZE_8 (0x3 << 1) ++#define DMA_CFG_BURST_SIZE_16 (0x4 << 1) ++#define DMA_CFG_BURST_SIZE_32 (0x5 << 1) ++#define DMA_CFG_BURST_SIZE_64 (0x6 << 1) ++#define DMA_CFG_BURST_SIZE_128 (0x7 << 1) ++ ++#define DMA_CFG_BURST_LENGTH_MASK (0xF << 4) ++#define DMA_CFG_BURST_LENGTH_1 (0x0 << 4) ++#define DMA_CFG_BURST_LENGTH_2 (0x1 << 4) ++#define DMA_CFG_BURST_LENGTH_3 (0x2 << 4) ++#define DMA_CFG_BURST_LENGTH_4 (0x3 << 4) ++#define DMA_CFG_BURST_LENGTH_5 (0x4 << 4) ++#define DMA_CFG_BURST_LENGTH_6 (0x5 << 4) ++#define DMA_CFG_BURST_LENGTH_7 (0x6 << 4) ++#define DMA_CFG_BURST_LENGTH_8 (0x7 << 4) ++#define DMA_CFG_BURST_LENGTH_9 (0x8 << 4) ++#define DMA_CFG_BURST_LENGTH_10 (0x9 << 4) ++#define DMA_CFG_BURST_LENGTH_11 (0xA << 4) ++#define DMA_CFG_BURST_LENGTH_12 (0xB << 4) ++#define DMA_CFG_BURST_LENGTH_13 (0xC << 4) ++#define DMA_CFG_BURST_LENGTH_14 (0xD << 4) ++#define DMA_CFG_BURST_LENGTH_15 (0xE << 4) ++#define DMA_CFG_BURST_LENGTH_16 (0xF << 4) ++ ++#define DMA_CFG_BURST_LEN(x) (((x - 1) & 0xF) << 4) ++ ++/* src and dest burst size and burst length are assumed to be same */ ++ ++enum pl330_xfer_status { ++ DMA_PL330_XFER_OK, ++ DMA_PL330_XFER_ERR, ++ DMA_PL330_XFER_ABORT, ++}; ++ ++struct dma_transfer_list { ++ dma_addr_t srcaddr; /* src address */ ++ dma_addr_t dstaddr; /* dst address */ ++ unsigned int xfer_size; /* In bytes */ ++ struct list_head next; /* Next item */ ++}; ++ ++typedef void (*pl330_xfer_callback_t) (void *private_data, ++ enum pl330_xfer_status status); ++ ++int dma_request_chan(unsigned int *chan, const char *name); ++int dma_free_chan(unsigned int chan); ++int dma_map_peripheral(unsigned int chan, const char *peri_name); ++int dma_unmap_peripheral(unsigned int chan); ++int dma_setup_transfer(unsigned int chan, dma_addr_t s, dma_addr_t d, ++ unsigned int xfer_size, int ctrl, int cfg); ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int ctrl, int cfg); ++int dma_start_transfer(unsigned int chan); ++int dma_stop_transfer(unsigned int chan); ++int dma_shutdown_all_chan(void); ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t cb, void *pri); ++int dma_free_callback(unsigned int chan); ++ ++#endif /* __PLAT_DMA_H */ +diff --git a/arch/arm/plat-iproc/include/plat/dma_drv.h b/arch/arm/plat-iproc/include/plat/dma_drv.h +new file mode 100644 +index 0000000..a7f8631 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch new file mode 100644 index 00000000..b1db4e8d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dma_drv.h.patch @@ -0,0 +1,609 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/dma_drv.h +@@ -0,0 +1,603 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/** ++* ++* @file dma_drv.h ++* ++* @brief DMA device driver defines and prototypes. ++* ++****************************************************************************/ ++/** ++* ++* @defgroup DMAGroup Direct Memory Access ++* @ingroup CSLGroup ++* @brief This group defines the APIs for DMA driver ++ ++Click here to navigate back to the Chip Support Library Overview page: \ref CSLOverview. \n ++*****************************************************************************/ ++#ifndef _DMA_DRV_H_ ++#define _DMA_DRV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @addtogroup DMAGroup ++ * @{ ++ */ ++ ++/** ++* ++* DMA driver status definition ++* ++*****************************************************************************/ ++#define DMADRV_STATUS_t DMADRV_STATUS ++typedef enum ++{ ++ DMADRV_STATUS_CLOSED, ++ DMADRV_STATUS_OPEN, ++ DMADRV_STATUS_OK, ++ DMADRV_STATUS_FAIL ++}DMADRV_STATUS_t; ++ ++/** ++* ++* DMA driver callback status definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_STATUS_t DMADRV_CALLBACK_STATUS ++typedef enum ++{ ++ DMADRV_CALLBACK_OK = 0, ++ DMADRV_CALLBACK_FAIL ++} DMADRV_CALLBACK_STATUS_t; ++ ++/** ++* ++* DMA driver channel descriptor definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 src; ++ UInt32 dest; ++ UInt32 next; ++ UInt32 control; ++ UInt32 size; ++ UInt32 owner; ++} Dma_Chan_Desc; ++ ++/** ++* ++* DMA driver data buffer feature definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 srcAddr; ++ UInt32 destAddr; ++ UInt32 length; ++ UInt32 bRepeat; ++ UInt32 interrupt; ++} Dma_Buffer; ++ ++/** ++* ++* DMA driver data buffer definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ Dma_Buffer buffers[1]; ++} Dma_Buffer_List; ++ ++/** ++* ++* DMA driver data buffer list definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 numBuffer; ++ Dma_Buffer_List *pBufList; ++} Dma_Data; ++ ++ ++/** ++* ++* DMA data transfer width definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_DATA_SIZE_8BIT = 0x00, ++ DMA_DATA_SIZE_16BIT = 0x01, ++ DMA_DATA_SIZE_32BIT = 0x02 ++} DMA_DWIDTH; ++ ++/** ++* ++* DMA data transfer type definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_FCTRL_MEM_TO_MEM = 0, ++ DMA_FCTRL_MEM_TO_PERI = 1, ++ DMA_FCTRL_PERI_TO_MEM = 2, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI = 3, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_DESTPERI = 4, ++ DMA_FCTRL_MEM_TO_PERI_CTRL_PERI = 5, ++ DMA_FCTRL_PERI_TO_MEM_CTRL_PERI = 6, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_SRCPERI = 7 ++} DMA_CHAN_TYPE; ++ ++/** ++* ++* DMA burst length definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_BURST_LEN_1 = 0x00, ///< ++ DMA_BURST_LEN_2 = 0x01, ///< ++ DMA_BURST_LEN_3 = 0x02, ///< ++ DMA_BURST_LEN_4 = 0x03, ///< ++ DMA_BURST_LEN_5 = 0x04, ///< ++ DMA_BURST_LEN_6 = 0x05, ///< ++ DMA_BURST_LEN_7 = 0x06, ///< ++ DMA_BURST_LEN_8 = 0x07, ///< ++ DMA_BURST_LEN_9 = 0x08, ///< ++ DMA_BURST_LEN_10 = 0x09, ///< ++ DMA_BURST_LEN_11 = 0x0A, ///< ++ DMA_BURST_LEN_12 = 0x0B, ///< ++ DMA_BURST_LEN_13 = 0x0C, ///< ++ DMA_BURST_LEN_14 = 0x0D, ///< ++ DMA_BURST_LEN_15 = 0x0E, ///< ++ DMA_BURST_LEN_16 = 0x0F ///< ++} DMADRV_BLENGTH; ++ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_2 = 0x01, ++ DMA_BURST_SIZE_4 = 0x02, ++ DMA_BURST_SIZE_8 = 0x03, ++ DMA_BURST_SIZE_16 = 0x04, ++ DMA_BURST_SIZE_32 = 0x05, ++ DMA_BURST_SIZE_64 = 0x06, ++ DMA_BURST_SIZE_128 = 0x07 ++} DMA_BSIZE; ++ ++#else ++/** ++* ++* DMA burst size definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_4 = 0x01, ++ DMA_BURST_SIZE_8 = 0x02, ++ DMA_BURST_SIZE_16 = 0x03, ++ DMA_BURST_SIZE_32 = 0x04, ++ DMA_BURST_SIZE_64 = 0x05, ++ DMA_BURST_SIZE_128 = 0x06, ++ DMA_BURST_SIZE_256 = 0x07 ++} DMA_BSIZE; ++#endif ++ ++/** ++* ++* DMA alignment definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_ALIGNMENT_8 = 8, ++ DMA_ALIGNMENT_16 = 16, ++ DMA_ALIGNMENT_32 = 32 ++} DMA_ALIGN; ++ ++/** ++* ++* DMA data transfer incremnet definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_INC_MODE_NONE = 0, ++ DMA_INC_MODE_SRC, ++ DMA_INC_MODE_DST, ++ DMA_INC_MODE_BOTH, ++} DMA_INC_MODE; ++ ++/** ++* ++* DMA driver client type definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_CLIENT_EP_INVALID = 0xff, ++ DMA_CLIENT_EP_UARTB_A = 8, ++ DMA_CLIENT_EP_UARTB_B = 9, ++ DMA_CLIENT_EP_UARTB2_A = 10, ++ DMA_CLIENT_EP_UARTB2_B = 11, ++ DMA_CLIENT_EP_UARTB3_A = 12, ++ DMA_CLIENT_EP_UARTB3_B = 13, ++ DMA_CLIENT_EP_SSP_0A_RX0 = 16, ++ DMA_CLIENT_EP_SSP_0B_TX0 = 17, ++ DMA_CLIENT_EP_SSP_0C_RX1 = 18, ++ DMA_CLIENT_EP_SSP_0D_TX1 = 19, ++ DMA_CLIENT_EP_SSP_1A_RX0 = 20, ++ DMA_CLIENT_EP_SSP_1B_TX0 = 21, ++ DMA_CLIENT_EP_SSP_1C_RX1 = 22, ++ DMA_CLIENT_EP_SSP_1D_TX1 = 23, ++ DMA_CLIENT_EP_HSIA = 32, ++ DMA_CLIENT_EP_HSIB = 33, ++ DMA_CLIENT_EP_HSIC = 34, ++ DMA_CLIENT_EP_HSID = 35, ++ DMA_CLIENT_EP_EANC = 40, ++ DMA_CLIENT_EP_STEREO = 41, ++ DMA_CLIENT_EP_NVIN = 42, ++ DMA_CLIENT_EP_VIN = 43, ++ DMA_CLIENT_EP_VIBRA = 44, ++ DMA_CLIENT_EP_IHF_0 = 45, ++ DMA_CLIENT_EP_VOUT = 46, ++ DMA_CLIENT_EP_SLIMA = 47, ++ DMA_CLIENT_EP_SLIMB = 48, ++ DMA_CLIENT_EP_SLIMC = 49, ++ DMA_CLIENT_EP_SLIMD = 50, ++ DMA_CLIENT_EP_SIM_A = 51, ++ DMA_CLIENT_EP_SIM_B = 52, ++ DMA_CLIENT_EP_SIM2_A = 53, ++ DMA_CLIENT_EP_SIM2_B = 54, ++ DMA_CLIENT_EP_IHF_1 = 55, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_3A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_3B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_3C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_3D_TX1 = 59, ++#else ++ DMA_CLIENT_EP_SSP_2A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_2B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_2C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_2D_TX1 = 59, ++#endif ++ DMA_CLIENT_EP_SPUM_SecureA = 65, ++ DMA_CLIENT_EP_SPUM_SecureB = 66, ++ DMA_CLIENT_EP_SPUM_OpenA = 67, ++ DMA_CLIENT_EP_SPUM_OpenB = 68, ++ DMA_CLIENT_MEMORY = 69, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_4A_RX0 = 76, ++ DMA_CLIENT_EP_SSP_4B_TX0 = 77, ++ DMA_CLIENT_EP_SSP_4C_RX1 = 78, ++ DMA_CLIENT_EP_SSP_4D_TX1 = 79, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#else ++typedef enum ++{ ++ DMA_CLIENT_BULK_CRYPT_OUT = 0, ++ DMA_CLIENT_CAM = 1, ++ DMA_CLIENT_I2S_TX = 2, ++ DMA_CLIENT_I2S_RX = 3, ++ DMA_CLIENT_SIM_RX = 4, ++ DMA_CLIENT_SIM_TX = 4, ++ DMA_CLIENT_CRC = 5, ++ DMA_CLIENT_SPI_RX = 6, ++ DMA_CLIENT_SPI_TX = 7, ++ DMA_CLIENT_UARTA_RX = 8, ++ DMA_CLIENT_UARTA_TX = 9, ++ DMA_CLIENT_UARTB_RX = 10, ++ DMA_CLIENT_UARTB_TX = 11, ++ DMA_CLIENT_DES_IN = 12, ++ DMA_CLIENT_DES_OUT = 13, ++ DMA_CLIENT_USB_RX = 14, ++ DMA_CLIENT_USB_TX = 15, ++ DMA_CLIENT_UARTC_RX = 16, ++ DMA_CLIENT_UARTC_TX = 17, ++ DMA_CLIENT_BULK_CRYPT_IN = 18, ++ DMA_CLIENT_LCD = 19, ++ DMA_CLIENT_MSPRO = 20, ++ DMA_CLIENT_DSI_CM = 21, ++ DMA_CLIENT_DSI_VM = 22, ++ DMA_CLIENT_TVENC1 = 23, ++ DMA_CLIENT_TVENC2 = 24, ++#if defined(_ATHENA_) ++ DMA_CLIENT_AUDIO_IN_FIFO = 25, ++ DMA_CLIENT_AUDIO_OUT_FIFO = 26, ++ DMA_CLIENT_POLYRING_OUT_FIFO = 27, ++ DMA_CLIENT_AUDIO_WB_MIXERTAP = 28, ++ DMA_CLIENT_MEMORY = 29, ++#else ++ DMA_CLIENT_MEMORY = 25, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#endif ++ ++/** ++* ++* DMA driver channel definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_CHANNEL_INVALID = 0xFF, ++ DMA_CHANNEL_0 = 0, ++ DMA_CHANNEL_1 = 1, ++ DMA_CHANNEL_2 = 2, ++ DMA_CHANNEL_3 = 3, ++#if !defined(_SAMOA_) ++ DMA_CHANNEL_4 = 4, ++ DMA_CHANNEL_5 = 5, ++ DMA_CHANNEL_6 = 6, ++ DMA_CHANNEL_7 = 7, ++#if defined(_ATHENA_) ++ DMA_CHANNEL_8 = 8, //used for DMA_CLIENT_AUDIO_OUT_FIFO ++ DMA_CHANNEL_9 = 9, //used for DMA_CLIENT_POLYRING_OUT_FIFO ++ DMA_CHANNEL_10 = 10, //used for DMA_CLIENT_AUDIO_WB_MIXERTAP ++ DMA_CHANNEL_11 = 11, //used for DMA_CLIENT_AUDIO_IN_FIFO ++#endif ++#endif ++ TOTAL_DMA_CHANNELS ++} DMA_CHANNEL; ++ ++/** ++* ++* DMA driver callback function definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_t DmaDrv_Callback ++typedef void (*DMADRV_CALLBACK_t)(DMADRV_CALLBACK_STATUS_t Err); ++ ++/** ++* ++* DMA driver channel info structure definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ DMA_CLIENT srcID; ++ DMA_CLIENT dstID; ++ DMA_CHAN_TYPE type; ++ DMA_ALIGN alignment; ++ DMA_BSIZE srcBstSize; ++ DMA_BSIZE dstBstSize; ++ DMA_DWIDTH srcDataWidth; ++ DMA_DWIDTH dstDataWidth; ++ UInt32 priority; ++ UInt32 chanNumber; ++ UInt32 dmaCfgReg; ++ UInt32 incMode; ++ DmaDrv_Callback xferCompleteCb; ++ UInt32 prot; ++ UInt32 dstMaster; ++ UInt32 srcMaster; ++ UInt32 dstIncrement; ++ UInt32 srcIncrement; ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++ DMADRV_BLENGTH srcBstLength; ++ DMADRV_BLENGTH dstBstLength; ++#endif ++ Boolean freeChan; ++ Boolean bCircular; ++} Dma_Chan_Info, *pChanInfo; ++ ++/** ++* ++* DMA driver LLI structure definition ++* ++*****************************************************************************/ ++typedef void *DMADRV_LLI_T; ++ ++/** ++* ++* This function initialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Init(void); ++ ++/** ++* ++* This function deinitialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_DeInit(void); ++ ++/** ++* ++* This function allocates dma channel ++* ++* @param srcID (in) source identification ++* @param dstID (in) destination identification ++* @param chanID (in) buffer to store channel number ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Obtain_Channel( ++ DMA_CLIENT srcID, ++ DMA_CLIENT dstID, ++ DMA_CHANNEL *chanID ++); ++ ++/** ++* ++* This function release dma channel ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Release_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function configure dma channel ++* ++* @param chanID (in) channel number ++* @param pChanInfo (in) pointer to dma channe info structure ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Config_Channel( ++ DMA_CHANNEL chanID, ++ Dma_Chan_Info *pChanInfo ++); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data(DMA_CHANNEL chanID, Dma_Data *pData); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* @param pLLI (in) buffer to store returned LLI table ++* identification info ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data_Ex( ++ DMA_CHANNEL chanID, ++ Dma_Data *pData, ++ DMADRV_LLI_T *pLLI ++); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* @param pLLI (in) one of the LLI tables needs to be used for DMA ++* transfer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer_Ex( ++ DMA_CHANNEL chanID, ++ DMADRV_LLI_T pLLI ++); ++ ++/** ++* ++* This function stop dma channel trnasfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Stop_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function stop dma channel trnasfer and lose all data in FIFO ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Force_Shutdown_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function register hisr for client usage ++* ++* @param client (in) client identification ++* @param hisr (in) registered hisr ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_Register_HISR(DMA_CLIENT client, void *hisr); ++ ++/** ++* ++* This function unregister hisr from client usage ++* ++* @param client (in) client identification ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_UnRegister_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get hisr for client usage ++* ++* @param client (in) client identification ++* ++* @return hisr (out) return registered client's hisr ++* ++*****************************************************************************/ ++void *DMADRV_Get_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get DMA driver version number ++* ++* @return driver version number ++* ++*****************************************************************************/ ++UInt32 DMADRV_Get_Version(void); ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DMA_DRV_H_ */ +diff --git a/arch/arm/plat-iproc/include/plat/dmux.h b/arch/arm/plat-iproc/include/plat/dmux.h +new file mode 100644 +index 0000000..575f783 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch new file mode 100644 index 00000000..03df92e2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_dmux.h.patch @@ -0,0 +1,82 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/dmux.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __MACH_DMUX_H ++#define __MACH_DMUX_H ++ ++enum dmac_mux { ++ KONA_DMUX_UARTB_A = 8, ++ KONA_DMUX_UARTB_B = 9, ++ KONA_DMUX_UARTB2_A = 10, ++ KONA_DMUX_UARTB2_B = 11, ++ KONA_DMUX_UARTB3_A = 12, ++ KONA_DMUX_UARTB3_B = 13, ++ KONA_DMUX_SSP_0A_RX0 = 16, ++ KONA_DMUX_SSP_0B_TX0 = 17, ++ KONA_DMUX_SSP_0C_RX1 = 18, ++ KONA_DMUX_SSP_0D_TX1 = 19, ++ KONA_DMUX_SSP_1A_RX0 = 20, ++ KONA_DMUX_SSP_1B_TX0 = 21, ++ KONA_DMUX_SSP_1C_RX1 = 22, ++ KONA_DMUX_SSP_1D_TX1 = 23, ++ KONA_DMUX_HSIA = 32, ++ KONA_DMUX_HSIB = 33, ++ KONA_DMUX_HSIC = 34, ++ KONA_DMUX_HSID = 35, ++ KONA_DMUX_EANC = 40, ++ KONA_DMUX_STEREO = 41, ++ KONA_DMUX_NVIN = 42, ++ KONA_DMUX_VIN = 43, ++ KONA_DMUX_VIBRA = 44, ++ KONA_DMUX_IHF_0 = 45, ++ KONA_DMUX_VOUT = 46, ++ KONA_DMUX_SLIMA = 47, ++ KONA_DMUX_SLIMB = 48, ++ KONA_DMUX_SLIMC = 49, ++ KONA_DMUX_SLIMD = 50, ++ KONA_DMUX_SIM_A = 51, ++ KONA_DMUX_SIM_B = 52, ++ KONA_DMUX_SIM2_A = 53, ++ KONA_DMUX_SIM2_B = 54, ++ KONA_DMUX_IHF_1 = 55, ++ KONA_DMUX_SSP_2A_RX0 = 56, ++ KONA_DMUX_SSP_2B_TX0 = 57, ++ KONA_DMUX_SSP_2C_RX1 = 58, ++ KONA_DMUX_SSP_2D_TX1 = 59, ++ KONA_DMUX_SPUM_SecureA = 65, ++ KONA_DMUX_SPUM_SecureB = 66, ++ KONA_DMUX_SPUM_OpenA = 67, ++ KONA_DMUX_SPUM_OpenB = 68, ++ KONA_DMUX_INVALID = 0x7f, ++}; ++ ++enum dma_peri dmux_name_to_id(const char *name); ++int dmux_id_to_name(enum dma_peri peri, char *pname); ++int dmux_sema_protect(void); ++int dmux_sema_unprotect(void); ++int dmux_alloc_channel(u32 * pchan); ++int dmux_release_channel(u32 channel); ++int dmux_alloc_peripheral(u32 channel, enum dma_peri peri, u8 * peri_req_id); ++int dmux_alloc_multi_peripheral(u32 channel, enum dma_peri a, enum dma_peri b, ++ u8 * src_id, u8 * dst_id); ++int dmux_dealloc_peripheral(u32 channel); ++ ++#endif /* __MACH_DMUX_H */ +diff --git a/arch/arm/plat-iproc/include/plat/osdal_os.h b/arch/arm/plat-iproc/include/plat/osdal_os.h +new file mode 100644 +index 0000000..76e61a6 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch new file mode 100644 index 00000000..0c8a55f3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_osdal_os.h.patch @@ -0,0 +1,66 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/osdal_os.h +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _OSDAL_OS_H_ ++#define _OSDAL_OS_H_ ++ ++#include ++#include "asm/posix_types.h" ++#include "asm/string.h" ++/* Heap memory */ ++#define OSDAL_ALLOCHEAPMEM(s) kzalloc((s), GFP_KERNEL) ++ ++#define OSDAL_FREEHEAPMEM(a) kfree((a)) ++ ++ ++/* IRQ */ ++#define OSDAL_IRQ_Enable(irq) enable_irq((irq)) ++#define OSDAL_IRQ_Disable(irq) disable_irq((irq)) ++#define OSDAL_IRQ_Clear(irq) ++#define OSDAL_IRQ_IsEnabled(irq) ++ ++ ++/* Synchronization */ ++#define OSDAL_SENDEVENT(e) complete((struct completion *)&(e)) ++ ++#define OSDAL_WAITEVENT(e) \ ++wait_for_completion((struct completion *)&(e)) ++ ++#define OSDAL_WAITEVENT_TIMEOUT(e, t) \ ++wait_for_completion_timeout((struct completion *)&(e), (t)) ++ ++#define OSDAL_CLEAREVENT(e) ++ ++ ++/* Time stamp in ms */ ++#define OSDAL_TIMEVAL() ++ ++ ++/* Delays */ ++#define OSDAL_MDELAY(x) mdelay(x) ++ ++#define OSDAL_UDELAY(x) udelay(x) ++ ++/* Debug Print */ ++//#define dprintf(prio, format, args...) pr_info("%s:%s"" format", __FILE__, __FUNCTION__) ++#define dprintf(prio, fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) ++ ++#endif /*_OSDAL_OS_H_*/ +diff --git a/arch/arm/plat-iproc/include/plat/shm.h b/arch/arm/plat-iproc/include/plat/shm.h +new file mode 100644 +index 0000000..59fcb83 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch new file mode 100644 index 00000000..04a1280f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_shm.h.patch @@ -0,0 +1,50 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/shm.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Header for declaring shim layer exports. ++ */ ++ ++#ifndef __SHM_DOT_H_INCLUDED__ ++#define __SHM_DOT_H_INCLUDED__ ++ ++#include ++#include ++ ++extern int iproc_platform_get_irq(struct platform_device *dev, unsigned int num); ++extern struct resource * ++iproc_platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name); ++extern struct resource * ++iproc_platform_get_resource(struct platform_device *dev, unsigned int type, ++ unsigned int num); ++extern int iproc_platform_device_register(struct platform_device * pdev); ++extern void iproc_platform_device_unregister(struct platform_device * pdev); ++extern int iproc_platform_driver_register(struct platform_driver *drv); ++extern void iproc_platform_driver_unregister(struct platform_driver *drv); ++ ++extern struct platform_device *iproc_platform_device_alloc(const char *name, int id); ++extern int iproc_platform_device_add(struct platform_device *pdev); ++extern void iproc_platform_device_put(struct platform_device *pdev); ++ ++extern int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); ++extern void iproc_sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp); ++ ++#endif /*#ifndef __SHM_DOT_H_INCLUDED__*/ +diff --git a/arch/arm/plat-iproc/include/plat/spi_iproc.h b/arch/arm/plat-iproc/include/plat/spi_iproc.h +new file mode 100644 +index 0000000..3258d69 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch new file mode 100644 index 00000000..8af39b07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_spi_iproc.h.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/spi_iproc.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/* ++ * Broadcom IPROC SSPI based SPI master controller ++ */ ++#ifndef __ARCH_PLAT_SPI_IPROC_H__ ++#define __ARCH_PLAT_SPI_IPROC_H__ ++ ++struct spi_iproc_platform_data { ++ u8 enable_dma; ++ u8 cs_line; ++ u8 mode; ++}; ++#endif /* __ARCH_PLAT_SPI_IPROC_H__ */ +diff --git a/arch/arm/plat-iproc/include/plat/swreset_rec.h b/arch/arm/plat-iproc/include/plat/swreset_rec.h +new file mode 100644 +index 0000000..924fa5a diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch new file mode 100644 index 00000000..58bb7484 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_swreset_rec.h.patch @@ -0,0 +1,46 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/swreset_rec.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _SWRESET_REC_H_ ++#define _SWRESET_REC_H_ ++ ++/* Handle to access Software Record Record */ ++typedef void *SWRR_HANDLE; ++ ++/* Get number of software reset records for the SoC; 0 if not suppprted */ ++extern unsigned int swreset_record_get_record_count(void); ++ ++/* Get number of bits per software reset record for the SoC */ ++extern unsigned int swreset_record_get_record_width(void); ++ ++/* Register to use one software reset record; return NULL if used out */ ++extern SWRR_HANDLE swreset_record_register(const char *name); ++ ++/* Unregister to return the record */ ++extern void swreset_record_unregister(SWRR_HANDLE handle); ++ ++/* Set value of the software reset record */ ++extern int swreset_record_set(SWRR_HANDLE handle, int value); ++ ++/* Get value of the software reset record */ ++extern int swreset_record_get(SWRR_HANDLE handle, int *value); ++ ++#endif /* _SWRESET_REC_H_ */ +diff --git a/arch/arm/plat-iproc/include/plat/timer-sp.h b/arch/arm/plat-iproc/include/plat/timer-sp.h +new file mode 100644 +index 0000000..b73ef9a diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch new file mode 100644 index 00000000..a3734f49 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_timer-sp.h.patch @@ -0,0 +1,24 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/timer-sp.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++void iproc_clocksource_init(void __iomem *); ++void iproc_clockevents_init(void __iomem *, unsigned int); +diff --git a/arch/arm/plat-iproc/include/plat/types.h b/arch/arm/plat-iproc/include/plat/types.h +new file mode 100644 +index 0000000..d03df1e diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch new file mode 100644 index 00000000..a48d719f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_include_plat_types.h.patch @@ -0,0 +1,26 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/include/plat/types.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _TYPES_H_ ++#define _TYPES_H_ ++ ++#include ++#endif +diff --git a/arch/arm/plat-iproc/iproc-cache.S b/arch/arm/plat-iproc/iproc-cache.S +new file mode 100644 +index 0000000..2a5e37d diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch new file mode 100644 index 00000000..01568c44 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_iproc-cache.S.patch @@ -0,0 +1,126 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/iproc-cache.S +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++ ++ __INIT ++ ++/* ++ * The secondary kernel init calls v7_flush_dcache_all before it enables ++ * the L1; however, the L1 comes out of reset in an undefined state, so ++ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch ++ * of cache lines with uninitialized data and uninitialized tags to get ++ * written out to memory, which does really unpleasant things to the main ++ * processor. We fix this by performing an invalidate, rather than a ++ * clean + invalidate, before jumping into the kernel. ++ */ ++ ++ENTRY(v7_invalidate_l1) ++ mov r0, #0 ++ mcr p15, 2, r0, c0, c0, 0 ++ mrc p15, 1, r0, c0, c0, 0 ++ ++ ldr r1, =0x7fff ++ and r2, r1, r0, lsr #13 ++ ++ ldr r1, =0x3ff ++ ++ and r3, r1, r0, lsr #3 @ NumWays - 1 ++ add r2, r2, #1 @ NumSets ++ ++ and r0, r0, #0x7 ++ add r0, r0, #4 @ SetShift ++ ++ clz r1, r3 @ WayShift ++ add r4, r3, #1 @ NumWays ++1: sub r2, r2, #1 @ NumSets-- ++ mov r3, r4 @ Temp = NumWays ++2: subs r3, r3, #1 @ Temp-- ++ mov r5, r3, lsl r1 ++ mov r6, r2, lsl r0 ++ orr r5, r5, r6 @ Reg = (Temp< ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static struct resource ccu_regs = { ++ .name = "cru_regs", ++ .start = IPROC_ROOT_CLK_VA, ++ .end = ((IPROC_ROOT_CLK_VA) + 0x0fff), ++ .flags = IORESOURCE_MEM, ++}; ++ ++/* ++ * Clock management scheme is a provisional implementation ++ * only intended to retreive the pre-set frequencies for each ++ * of the clocks. ++ */ ++ ++/* ++ * Get PLL running status and update output frequency ++ * for ARMPLL channel 0 ++ */ ++static int a9pll0_status (struct clk * clk) ++{ ++ u32 regA; ++ u32 regB; ++ u32 regC; ++ u32 pdiv; ++ u32 ndiv_int; ++ u32 ndiv_frac; ++ u32 mdiv; ++ u64 x; ++ ++ printk(KERN_DEBUG "a9pll0_status: clk 0x%x\n", (unsigned int)clk); ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ BUG_ON (!clk->regs_base); ++ BUG_ON (!clk->parent); ++ ++ /* read status register */ ++ regA = readl(clk->regs_base + 0x0c00);/* IHOST_PROC_CLK_PLLARMA */ ++ regB = readl(clk->regs_base + 0x0c04);/* IHOST_PROC_CLK_PLLARMB */ ++ regC = readl(clk->regs_base + 0x0c08);/* IHOST_PROC_CLK_PLLARMB */ ++ ++ /* reg C bit 8 is bypass mode - input frequency to output */ ++ if ((regC & (1 << 8)) == 1) { ++ clk->rate = clk->parent->rate; ++ return 0; ++ } ++ ++ /* reg A bit 28 is "lock" signal, has to be "1" for proper operation */ ++ if ((regA & (1 << 28)) == 0 ) { ++#if defined(CONFIG_MACH_IPROC_P7) && defined(CONFIG_MACH_IPROC_EMULATION) ++ printk(KERN_WARNING "a9pll0_status: ARM PLL not locked\n"); ++#else ++ clk->rate = 0; ++ return -EIO; ++#endif ++ } ++ ++ /* Update PLL frequency */ ++ ++ ++ /* pdiv in bits 24..27 (4 bits) */ ++ // pdiv = (regA >> 24 ) & 0xf; pavan 05092012 ++ pdiv = (regA >> 24 ) & 0x7; ++ if (pdiv == 0) ++ pdiv = 0x10; ++ ++ /* feedback divider (int) in bits 8..17 (10 bits) */ ++ ndiv_int = (regA >> 8) & ((1<<10) - 1); ++ if (ndiv_int == 0) ++ ndiv_int = 1 << 10; ++ ++ /* feedback divider fraction in reg B, bits 0..19 */ ++ ndiv_frac = regB & ((1<<20) - 1); ++ ++ x = ((u64) ndiv_int << 20) | ndiv_frac; ++ printk(KERN_DEBUG "parent rate %lu\n", clk->parent->rate); ++ x = (x * clk->parent->rate) >> 20; ++ (void) do_div(x, pdiv); ++ ++ /* post-divider is in reg C bits 0..7 */ ++ mdiv = regC & 0xff ; ++ if (mdiv == 0) ++ mdiv = 0x100; ++ ++ /* ++ * Here we need to divide the resulting clock by mdiv which we ++ * are not doing now? ++ */ ++ clk->rate = (u32)(x); ++ ++ return 0; ++} ++ ++ ++/* ++ * Get PLL running status and update output frequency ++ * for ARMPLL channel 1 ++ */ ++static int a9pll1_status(struct clk * clk) ++{ ++ u32 regA; ++ u32 regB; ++ u32 regC; ++ u32 regD; ++ unsigned pdiv; ++ unsigned ndiv_int; ++ unsigned ndiv_frac; ++ unsigned mdiv; ++ u64 x; ++ ++ if (clk->type != CLK_PLL) ++ return -EINVAL; ++ ++ BUG_ON(!clk->regs_base); ++ BUG_ON(!clk->parent); ++ ++ /* read status register */ ++ regA = readl(clk->regs_base+0xc00);/* IHOST_PROC_CLK_PLLARMB */ ++ regB = readl(clk->regs_base+0xc04);/* IHOST_PROC_CLK_PLLARMB */ ++ regC = readl(clk->regs_base+0xc20);/* IHOST_PROC_CLK_PLLARMCTRL5 */ ++ regD = readl(clk->regs_base+0xc24);/* IHOST_PROC_CLK_PLLARM_OFFSET*/ ++ ++ /* reg C bit 8 is bypass mode - input frequency to output */ ++ if ((regC & (1 << 8)) == 1) { ++ clk->rate = clk->parent->rate; ++ return 0; ++ } ++ ++ /* reg A bit 28 is "lock" signal, has to be "1" for proper operation */ ++ if ((regA & (1 << 28)) == 0) { ++#if defined(CONFIG_MACH_IPROC_P7) && defined(CONFIG_MACH_IPROC_EMULATION) ++ printk(KERN_WARNING "a9pll1_status: ARM PLL not locked\n"); ++#else ++ clk->rate = 0; ++ return -EIO; ++#endif ++ } ++ ++ /* Update PLL frequency */ ++ ++ ++ /* pdiv in bits 24..27 (4 bits) */ ++ pdiv = (regA >> 24 ) & 0xf; ++ if (pdiv == 0) ++ pdiv = 0x10; ++ ++ /* Check if offset mode is active */ ++ if (regD & (1 << 29)) { ++ /* pllarm_ndiv_int_offset bits 27:20 */ ++ ndiv_int = (regD >> 20 ) & 0xff; ++ if (ndiv_int == 0) ++ ndiv_int = 1 << 8; ++ ++ /* pllarm_ndiv_frac_offset bits 19:0 */ ++ ndiv_frac = regD & ((1 << 20) - 1); ++ } else { ++ /* If offset not active, channel 0 parameters are used */ ++ /* feedback divider (int) in bits 8..17 (10 bits) */ ++ ndiv_int = (regA >> 8) & ((1 << 10) - 1); ++ if (ndiv_int == 0) ++ ndiv_int = 1 << 10; ++ ++ /* feedback divider fraction in reg B, bits 0..19 */ ++ ndiv_frac = regB & ((1 << 20) - 1); ++ } ++ ++ x = ((u64) ndiv_int << 20) | ndiv_frac; ++ x = (x * clk->parent->rate) >> 20; ++ (void) do_div(x, pdiv); ++ ++ /* post-divider is in reg C bits 0..7 */ ++ mdiv = regC & 0xff ; ++ if (mdiv == 0) ++ mdiv = 0x100; ++ ++ (void) do_div(x, mdiv); ++ clk->rate = (u32)(x); ++ ++ return 0; ++} ++ ++ ++static const struct clk_ops a9pll0_ops = { ++ .status = a9pll0_status, ++}; ++ ++static const struct clk_ops a9pll1_ops = { ++ .status = a9pll1_status, ++}; ++ ++ ++/* ++ * iProc A9 PLL ++ * could be used as source for generated clocks ++ */ ++static struct clk clk_a9pll[2] = { ++ { ++ .ops = &a9pll0_ops, ++ .name = "A9_PLL", ++ .type = CLK_PLL, ++ .chan = 0xa, ++ }, ++ { ++ .ops = &a9pll1_ops, ++ .name = "A9_PLL", ++ .type = CLK_PLL, ++ .chan = 0xb, ++ }, ++}; ++ ++/* ++ * Decode the Frequency ID setting for arm_clk ++ */ ++static int iproc_cru_arm_freq_id(void * __iomem regs_base) ++{ ++ u32 reg_f, reg; ++ unsigned policy; ++ unsigned fid; ++ unsigned i; ++ u8 arm_clk_policy_mask = 0; ++ u8 apb0_clk_policy_mask = 0; ++ ++ /* ++ * bits 0..2 freq# for policy0, 8..10 for policy1, ++ * 16..18 policy2, 24..26 policy 3 ++ */ ++ reg_f = readl(regs_base + 0x008);/*IHOST_PROC_CLK_POLICY_FREQ*/ ++ ++ for(i = 0; i < 4; i++) { ++ /* ++ * Reg IHOST_PROC_CLK_POLICY_MASK ++ * bit 20 arm policy mask, bit 21 apb0 policy mask ++ */ ++ reg = readl(regs_base + 0x010 + i*4); ++ arm_clk_policy_mask |= (1 & ( reg >> 20)) << i; ++ apb0_clk_policy_mask |= (1 & ( reg >> 21)) << i; ++ } ++ ++ /* How to obtain hardware policy setting ? */ ++ policy = 0; ++ ++ /* Check for PLL policy software override */ ++ reg = readl(regs_base + 0xe00);/* IHOST_PROC_CLK_ARM_DIV */ ++ if (reg & (1 << 4 )) ++ policy = reg & 0xf; ++ ++ fid = (reg_f >> (8 * policy)) & 0xf; ++ ++ /* Verify freq_id from debug register */ ++ reg = readl( regs_base+0xec0 );/* IHOST_PROC_CLK_POLICY_DBG */ ++ /* Bits 12..14 contain active frequency_id */ ++ i = 0x7 & (reg >> 12); ++ ++ if (fid != i) { ++ printk(KERN_WARNING ++ "IPROC CRU clock frequency id override %d->%d\n", ++ fid, i); ++ fid = i; ++ } ++ ++ printk(KERN_DEBUG "Active frequency ID %d\n", fid); ++ ++ return fid; ++} ++ ++/* ++ * Get status of any of the ARMPLL output channels ++ */ ++static int a9pll_chan_status(struct clk * clk) ++{ ++ u32 reg; ++ unsigned div; ++ unsigned freq_id; ++ ++ if(clk->type != CLK_DIV) ++ return -EINVAL; ++ ++ BUG_ON(!clk->regs_base); ++ ++ reg = readl(clk->regs_base + 0xe00); /* IHOST_PROC_CLK_ARM_DIV */ ++ ++ /* arm_pll_select 3:0 */ ++ printk(KERN_DEBUG "Clock Div = %#x\n", reg); ++ ++ freq_id = iproc_cru_arm_freq_id(clk->regs_base); ++ ++ /* clk->parent = & clk_a9pll[0]; */ ++ ++ switch (clk->chan) { ++ case 0x0a: ++ /* apb0_free_div bits 10:8 */ ++ div = (reg >> 8) & 0x7; ++ if (div == 0) ++ div = 8; ++ break; ++ ++ case 0x0b: ++ /* arm_switch_div bits 6:5 */ ++ div = (reg >> 5) & 0x3; ++ if (div == 0) ++ div = 4; ++ break; ++ ++ case 0x1a: ++ /* IHOST_PROC_CLK_APB_DIV apb_clk_div bits 1:0 */ ++ reg = readl(clk->regs_base + 0xa10); ++ div = reg & 0x3; ++ if(div == 0) ++ div = 4; ++ break; ++ ++ case 0x3a: /* arm_clk */ ++ if( freq_id == 7 ) { ++ //clk->parent = &clk_a9pll[1]; /* arm_clk_h */ ++ clk->parent = &clk_a9pll[0]; /* arm_clk_h */ ++ div = 2; ++ } else if( freq_id == 6 ) { ++ clk->parent = &clk_a9pll[0]; /* arm_clk */ ++ div = 4; ++ } else if( freq_id == 2 ) { ++ clk->parent = &clk_a9pll[0]; /* arm_clk */ ++ div = 4; ++ } else if (freq_id == 0) { ++ clk->parent = &clk_a9pll[0]; ++ div = 1; ++ } else if (freq_id == 1) { ++ struct clk * clk_lcpll_200; ++ clk_lcpll_200 = ++ clk_get_sys( NULL, "sdio_clk"); ++ BUG_ON( ! clk_lcpll_200 ); ++ clk->parent = clk_lcpll_200; ++ div = 1; ++ } else { ++ clk->parent = &clk_a9pll[0]; ++ div = 2; ++ } ++ /* Parent may have changed, refresh it */ ++ if(clk->parent->ops && clk->parent->ops->status) ++ clk->parent->ops->status( clk->parent); ++ break; ++ ++ case 0x0f: /* periph_clk */ ++ div = 2; ++ break; ++ ++ default: ++ return -EINVAL; ++ ++ } ++ ++ BUG_ON(!clk->parent); ++ printk(KERN_DEBUG "Clock divisor %d\n", div); ++ // clk->rate = clk->parent->rate / div ; ++ clk->rate = clk->parent->rate / div ; ++ printk(KERN_DEBUG "Clock rate %lu\n", clk->rate); ++ ++ return 0; ++} ++ ++ ++static const struct clk_ops a9pll_chan_ops = { ++ .status = a9pll_chan_status, ++}; ++ ++/* ++ * iProc A9 PLL output clocks ++ */ ++#ifdef CONFIG_MACH_CYGNUS_EMULATION //chandra:emul ++ static struct clk clk_a9chan[] = { ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_ARM_CLK, ++ .name = "arm_clk", ++ .chan = 0x3a ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_PCLK, ++ .name = "periph_clk", ++ .chan = 0x0f ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_PCLK, ++ .name = "apb0_free", ++ .chan = 0x0a ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_ARM_CLK, ++ .name = "arm_switch", ++ .chan = 0x0b ++ }, ++ { ++ .ops = NULL, ++ .type = CLK_DIV, ++ .parent = NULL, ++ .rate = CONFIG_CYGNUS_EMULATION_PCLK, ++ .name = "apb_clk", ++ .chan = 0x1a ++ }, ++ }; ++#else ++static struct clk clk_a9chan[] = { ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "arm_clk", ++ .chan = 0x3a ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "periph_clk", ++ .chan = 0x0f ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "apb0_free", ++ .chan = 0x0a ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "arm_switch", ++ .chan = 0x0b ++ }, ++ { ++ .ops = &a9pll_chan_ops, ++ .type = CLK_DIV, ++ .parent = &clk_a9chan[0], ++ .name = "apb_clk", ++ .chan = 0x1a ++ }, ++}; ++#endif /* End of CONFIG_MACH_CYGNUS */ ++ ++static struct clk_lookup cru_clk_lookups[] = { ++ { ++ .con_id= "a9pll0", ++ .clk= &clk_a9pll[0], ++ }, ++ { ++ .con_id= "a9pll1", ++ .clk= &clk_a9pll[1], ++ }, ++ { ++ .con_id= "arm_clk", ++ .clk= &clk_a9chan[0], ++ }, ++ { ++ .con_id= "periph_clk", ++ .clk= &clk_a9chan[1], ++ }, ++ { ++ .con_id= "apb0_free", ++ .clk= &clk_a9chan[2], ++ }, ++ { ++ .con_id= "axi_clk", ++ .clk= &clk_a9chan[3], ++ }, ++ { ++ .con_id= "apb_clk", ++ .clk= &clk_a9chan[4], ++ }, ++}; ++ ++void __init iproc_cru_init(struct clk * src_clk) ++{ ++ void * __iomem reg_base; ++ unsigned i; ++ ++ BUG_ON(request_resource( &iomem_resource, &ccu_regs)); ++ ++ reg_base = IOMEM(ccu_regs.start); ++ ++ BUG_ON(IS_ERR_OR_NULL(reg_base)); ++ ++ /* Initialize clocks */ ++ ++ for (i = 0; i < ARRAY_SIZE(clk_a9pll); i++) { ++ clk_a9pll[i].regs_base = reg_base ; ++ clk_a9pll[i].parent = src_clk ; ++ } ++ ++ clk_a9chan[0].parent = src_clk ; /* tentative */ ++ for (i = 0; i < ARRAY_SIZE(clk_a9chan); i++) { ++ clk_a9chan[i].regs_base = reg_base ; ++ } ++ ++ /* Install clock sources into the lookup table */ ++ clkdev_add_table(cru_clk_lookups, ++ ARRAY_SIZE(cru_clk_lookups)); ++} ++ ++void cru_clocks_show(void) ++{ ++ unsigned i; ++ ++ printk( "CRU Clocks:\n" ); ++ for (i = 0; i < ARRAY_SIZE( cru_clk_lookups); i++) { ++ printk( "%s: (%s) %lu\n", ++ cru_clk_lookups[i].con_id, ++ cru_clk_lookups[i].clk->name, ++ clk_get_rate( cru_clk_lookups[i].clk)); ++ } ++ printk( "CRU Clocks# %u\n", i ); ++ ++} +diff --git a/arch/arm/plat-iproc/irq.c b/arch/arm/plat-iproc/irq.c +new file mode 100644 +index 0000000..6d6bda2 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch new file mode 100644 index 00000000..184f887b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_irq.c.patch @@ -0,0 +1,51 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/irq.c +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++ ++void __init iproc_init_irq(void) ++{ ++ unsigned int cr; ++ ++ cr = get_cr(); ++ cr |= CR_VE; ++ set_cr(cr); ++ ++ /* start with GLBTIMER */ ++ ++ gic_init(0, BCM_INT_ID_PPI0, ++ IOMEM(IPROC_PERIPH_INT_DISTR_REG_VA), ++ IOMEM(IPROC_GICCPU_VA)); ++} +diff --git a/arch/arm/plat-iproc/lm.c b/arch/arm/plat-iproc/lm.c +new file mode 100644 +index 0000000..a6ac191 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch new file mode 100644 index 00000000..f42fd327 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_lm.c.patch @@ -0,0 +1,144 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/lm.c +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define to_lm_device(d) container_of(d, struct lm_device, dev) ++#define to_lm_driver(d) container_of(d, struct lm_driver, drv) ++ ++static int ++lm_match(struct device *dev, struct device_driver *drv) ++{ ++ printk(KERN_INFO "lm_match()\n"); ++ return 1; ++} ++ ++static int ++lm_bus_probe(struct device *dev) ++{ ++ struct lm_device *lmdev = to_lm_device(dev); ++ struct lm_driver *lmdrv = to_lm_driver(dev->driver); ++ ++ printk(KERN_INFO "lm_bus_probe()\n"); ++ return lmdrv->probe(lmdev); ++} ++ ++static int ++lm_bus_remove(struct device *dev) ++{ ++ struct lm_device *lmdev = to_lm_device(dev); ++ struct lm_driver *lmdrv = to_lm_driver(dev->driver); ++ ++ printk(KERN_INFO "lm_bus_remove()\n"); ++ if (lmdrv->remove) ++ lmdrv->remove(lmdev); ++ return 0; ++} ++ ++static struct bus_type lm_bustype = ++{ ++ .name = "logicmodule", ++ .match = lm_match, ++ .probe = lm_bus_probe, ++ .remove = lm_bus_remove, ++ /* .suspend = lm_bus_suspend, */ ++ /* .resume = lm_bus_resume, */ ++}; ++ ++static int __init ++lm_init(void) ++{ ++ printk(KERN_INFO "lm_init()\n"); ++ return bus_register(&lm_bustype); ++} ++ ++postcore_initcall(lm_init); ++ ++int ++lm_driver_register(struct lm_driver *drv) ++{ ++ printk(KERN_INFO "lm_driver_register(): name=%s\n", drv->drv.name); ++ drv->drv.bus = &lm_bustype; ++ return driver_register(&drv->drv); ++} ++ ++void ++lm_driver_unregister(struct lm_driver *drv) ++{ ++ printk(KERN_INFO "lm_driver_unregister()\n"); ++ driver_unregister(&drv->drv); ++} ++ ++static void ++lm_device_release(struct device *dev) ++{ ++ struct lm_device *lmdev = to_lm_device(dev); ++ ++ printk(KERN_INFO "lm_device_release()\n"); ++ release_resource(&lmdev->resource); ++ kfree(lmdev); ++} ++ ++int ++lm_device_register(struct lm_device *lmdev) ++{ ++ int ret; ++ ++ printk(KERN_INFO "lm_device_register(): id=%d irq=%d start=0x%08x end=0x%08x\n", lmdev->id, lmdev->irq, lmdev->resource.start, lmdev->resource.end); ++ ++ lmdev->dev.release = lm_device_release; ++ lmdev->dev.bus = &lm_bustype; ++ dev_set_name (&lmdev->dev, "lm%d", lmdev->id); ++ lmdev->resource.name = dev_name (&lmdev->dev); ++ ++ ret = request_resource(&iomem_resource, &lmdev->resource); ++ if (ret == 0) { ++ ret = device_register(&lmdev->dev); ++ if (ret) ++ { ++ printk(KERN_ERR "lm_device_register(): device_register() failed, rc=%d\n", ret ); ++ release_resource(&lmdev->resource); ++ } ++ } ++ else ++ printk(KERN_ERR "lm_device_register(): request_resource() failed, rc=%d\n", ret ); ++ ++ return ret; ++} ++ ++void ++lm_device_unregister(struct lm_device *lmdev) ++{ ++ printk(KERN_INFO "lm_device_unregister()\n"); ++ device_unregister(&lmdev->dev); ++} ++ ++ ++EXPORT_SYMBOL(lm_device_register); ++EXPORT_SYMBOL(lm_device_unregister); ++ ++EXPORT_SYMBOL(lm_driver_register); ++EXPORT_SYMBOL(lm_driver_unregister); +diff --git a/arch/arm/plat-iproc/localtimer.c b/arch/arm/plat-iproc/localtimer.c +new file mode 100644 +index 0000000..ca13311 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch new file mode 100644 index 00000000..cb9b2431 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_localtimer.c.patch @@ -0,0 +1,42 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/localtimer.c +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define IRQ_LOCALTIMER BCM_INT_ID_PPI13 ++/* ++ * Setup the local clock events for a CPU. ++ */ ++ ++void iproc_local_timer_init(void) ++{ ++ twd_base = IO_ADDRESS(IPROC_PERIPH_PVT_TIM_REG_VA); ++} +diff --git a/arch/arm/plat-iproc/platsmp.c b/arch/arm/plat-iproc/platsmp.c +new file mode 100644 +index 0000000..e902c8d diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch new file mode 100644 index 00000000..a1535a7d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_platsmp.c.patch @@ -0,0 +1,271 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/platsmp.c +@@ -0,0 +1,265 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* Lookup table phys addr and offset */ ++#define SOC_ROM_BASE_PA 0xFFFF0000 ++#ifdef CONFIG_MACH_NS ++#define SOC_ROM_LUT_OFF 0x400 ++#elif defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define SOC_ROM_LUT_OFF 0x42c ++#elif defined(CONFIG_MACH_HR2) ++#define SOC_ROM_LUT_OFF 0x400 ++#elif defined(CONFIG_MACH_NSP) ++#define SOC_ROM_LUT_OFF 0x42c ++#elif defined(CONFIG_MACH_CYGNUS) ++#define SOC_ROM_LUT_OFF 0x400 ++#elif defined(CONFIG_MACH_KT2) ++#define SOC_ROM_LUT_OFF 0x42c ++#else ++#error "SOC_ROM_LUT_OFF is not defined" ++#endif ++ ++/* ++ * control for which core is the next to come out of the secondary ++ * boot "holding pen" ++ */ ++volatile int pen_release = -1; ++ ++/* SCU base address */ ++static void __iomem *scu_base = (void __iomem *)(IPROC_PERIPH_SCU_REG_VA); ++ ++/* ++ * Use SCU config register to count number of cores ++ */ ++static inline unsigned int get_core_count(void) ++{ ++ if (scu_base) ++ return scu_get_core_count(scu_base); ++ return 1; ++} ++ ++/* ++ * Initialise the CPU possible map early - this describes the CPUs ++ * which may be present or become present in the system. ++ */ ++void __init smp_init_cpus(void) ++{ ++unsigned int i, ncores = get_core_count(); ++ ++ printk(KERN_DEBUG "smp_init_cpus: Enter ncores %d\n", ncores); ++ ++ for (i = 0; i < ncores; i++) ++ set_cpu_possible(i, true); ++ ++ set_smp_cross_call(gic_raise_softirq); ++ ++ printk(KERN_DEBUG "smp_init_cpus: Leave ncores %d\n", ncores); ++} ++ ++static DEFINE_SPINLOCK(boot_lock); ++ ++ ++ ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ ++static void enable_a9_features(void) { ++ unsigned int a9_aux=0, a9_aux_m=0, a9_sys=0; ++ ++ // Read a9_aux Register ++ asm volatile ("MRC p15, 0, %0, c1, c0, 1\t\n": "=r"(a9_aux)); ++ ++ // Write a9_aux Register; L1/L2 prefetch enable & Fill line zero ++ asm volatile ("mcr p15, 0, %0, c1, c0, 1\t\n" : : "r"(a9_aux | (0x7 << 1))); ++ ++ // Read a9_aux Register again ++ asm volatile ("MRC p15, 0, %0, c1, c0, 1\t\n": "=r"(a9_aux_m)); ++ ++ //System Control Register ++ asm volatile ("MRC p15, 0, %0, c1, c0, 0\t\n": "=r"(a9_sys)); ++ ++ printk(KERN_INFO "\n<%s> CUP_ID %d a9_aux = 0x%x; a9_aux_m = 0x%x; a9_sys = 0x%x\n", \ ++ __FUNCTION__, smp_processor_id(), a9_aux, a9_aux_m, a9_sys); ++} ++ ++#endif ++ ++ ++void __cpuinit platform_secondary_init(unsigned int cpu) ++{ ++ printk(KERN_DEBUG "platform_secondary_init: Enter cpu %d\n", cpu); ++ ++ ++ /* ++ * If any interrupts are already enabled for the primary ++ * core (e.g. timer irq), then they will not have been enabled ++ * for us: do so ++ */ ++ ++ // modelled after omap-smp.c:platform_secondary_init() changes ++ // between 2.6.37.6 and 2.6.38.1. ++ gic_secondary_init(0); ++ ++ /* ++ * let the primary processor know we're out of the ++ * pen, then head off into the C entry point ++ */ ++ pen_release = -1; ++ ++ ++#ifdef CONFIG_BCM_IPROC_CA9_PREFETCH ++ enable_a9_features(); ++ smp_call_function((void (*)(void))enable_a9_features, NULL, 0); ++#endif ++ ++ ++ smp_wmb(); ++ ++ /* ++ * Synchronise with the boot thread. ++ */ ++ spin_lock(&boot_lock); ++ spin_unlock(&boot_lock); ++ ++ printk(KERN_DEBUG "platform_secondary_init: Leave pen_release %d\n", pen_release); ++} ++ ++int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ unsigned long timeout; ++ ++ printk(KERN_DEBUG "boot_secondary: Enter CPU%d\n", cpu); ++ ++ /* ++ * Set synchronisation state between this boot processor ++ * and the secondary one ++ */ ++ spin_lock(&boot_lock); ++ ++ /* ++ * The secondary processor is waiting to be released from ++ * the holding pen - release it, then wait for it to flag ++ * that it has been released by resetting pen_release. ++ * ++ * Note that "pen_release" is the hardware CPU ID, whereas ++ * "cpu" is Linux's internal ID. ++ */ ++ pen_release = cpu; ++ clean_dcache_area( (void *) &pen_release, sizeof(pen_release)); ++ outer_clean_range(__pa(&pen_release), ++ __pa(&pen_release + sizeof(pen_release))); ++ // flush_cache_all(); ++ ++ /* ++ * Now the secondary CPU must start marching on its ++ * own. ++ */ ++ dsb_sev(); ++ ++ /* wait at most 1 second for the secondary to wake up */ ++ ++ timeout = jiffies + (1 * HZ); ++ while (time_before(jiffies, timeout)) { ++ smp_rmb(); ++ if (pen_release == -1) ++ break; ++ ++ udelay(10); ++ clean_dcache_area( (void *) &pen_release, sizeof(pen_release)); ++ } ++ ++ /* ++ * Now the secondary core is starting up let it run its ++ * calibrations, then wait for it to finish ++ */ ++ spin_unlock(&boot_lock); ++ ++ printk(KERN_DEBUG "boot_secondary: Leave pen-release %d\n", pen_release); ++ ++ return pen_release != -1 ? -ENOSYS : 0; ++} ++ ++ ++static void __init wakeup_secondary(unsigned cpu, void (* _sec_entry_va)(void)) ++{ ++ void __iomem * rombase = NULL; ++ phys_addr_t lut_pa; ++ u32 offset; ++ u32 mask; ++ u32 val; ++ ++ printk(KERN_DEBUG "wakeup_secondary: Enter cpu %d\n", cpu); ++ ++ mask = (1UL << PAGE_SHIFT) -1; ++ ++ lut_pa = SOC_ROM_BASE_PA & ~mask; ++ offset = SOC_ROM_BASE_PA & mask; ++ offset += SOC_ROM_LUT_OFF; ++ ++ rombase = ioremap(lut_pa, PAGE_SIZE); ++ if(rombase == NULL) ++ return; ++ val = virt_to_phys(_sec_entry_va); ++ ++ writel(val, rombase + offset); ++ ++ smp_wmb(); /* probably not needed - io regs are not cached */ ++ ++#ifdef CONFIG_SMP ++ dsb_sev(); /* Exit WFI */ ++#endif ++ mb(); ++ ++ iounmap(rombase); ++ ++ printk(KERN_DEBUG "wakeup_secondary: Leave cpu %d\n", cpu); ++} ++ ++ ++void __init platform_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ int i; ++ ++ /* ++ * Initialise the present map, which describes the set of CPUs ++ * actually populated at the present time. ++ */ ++ for (i = 0; i < max_cpus; i++) ++ set_cpu_present(i, true); ++ ++ /* ++ * Initialise the SCU and wake up the secondary core using ++ * wakeup_secondary(). ++ */ ++ scu_enable(scu_base); ++ wakeup_secondary(max_cpus, iproc_secondary_startup); ++} +diff --git a/arch/arm/plat-iproc/shm.c b/arch/arm/plat-iproc/shm.c +new file mode 100644 +index 0000000..2c59270 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch new file mode 100644 index 00000000..59f461ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_shm.c.patch @@ -0,0 +1,177 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/shm.c +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "include/plat/shm.h" ++/** ++ * iproc_platform_get_irq - get an IRQ for a device ++ * wrapper function for platform_get_irq ++ * @dev: platform device ++ * @num: IRQ number index ++ */ ++int iproc_platform_get_irq(struct platform_device *dev, unsigned int num) ++{ ++ return platform_get_irq(dev, num); ++} ++EXPORT_SYMBOL(iproc_platform_get_irq); ++ ++ ++/** ++ * iproc_platform_get_resource_byname - ++ * wrapper function for platform_get_resource_byname ++ * @dev: platform device ++ * @type: resource type ++ * @name: resource name ++ */ ++struct resource * ++iproc_platform_get_resource_byname(struct platform_device *dev, ++ unsigned int type, ++ const char *name) ++{ ++ return platform_get_resource_byname(dev, type, name); ++} ++EXPORT_SYMBOL(iproc_platform_get_resource_byname); ++ ++ ++/** ++ * iproc_platform_get_resource - ++ * wrapper function for platform_get_resource ++ * @dev: platform device ++ * @type: resource type ++ * @num: resource index ++ */ ++struct resource * ++iproc_platform_get_resource(struct platform_device *dev, unsigned int type, ++ unsigned int num) ++{ ++ return platform_get_resource(dev, type, num); ++} ++EXPORT_SYMBOL(iproc_platform_get_resource); ++ ++ ++/** ++ * iproc_platform_driver_register - ++ * wrapper function for platform_driver_register ++ * @drv: platform driver structure ++ */ ++int iproc_platform_driver_register(struct platform_driver *drv) ++{ ++ return platform_driver_register(drv); ++} ++EXPORT_SYMBOL(iproc_platform_driver_register); ++ ++ ++/** ++ * iproc_platform_driver_unregister ++ * wrapper function for platform_driver_unregister ++ * @drv: platform driver structure ++ */ ++void iproc_platform_driver_unregister(struct platform_driver *drv) ++{ ++ return platform_driver_unregister(drv); ++} ++EXPORT_SYMBOL(iproc_platform_driver_unregister); ++ ++ ++/** ++ * iproc_platform_device_register - add a platform-level device ++ * wrapper function for platform_device_register ++ * @pdev: platform device we're adding ++ * ++ */ ++int iproc_platform_device_register(struct platform_device * pdev) ++{ ++ return platform_device_register(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_register); ++ ++ ++/** ++ * iproc_platform_device_unregister - ++ * wrapper function for platform_device_unregister ++ * @pdev: platform device we're unregistering ++ */ ++void iproc_platform_device_unregister(struct platform_device * pdev) ++{ ++ return platform_device_unregister(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_unregister); ++ ++ ++/** ++ * iproc_platform_device_alloc - ++ * wrapper function for platform_device_alloc ++ * @name: base name of the device we're adding ++ * @id: instance id ++ */ ++struct platform_device *iproc_platform_device_alloc(const char *name, int id) ++{ ++ return platform_device_alloc(name, id); ++} ++EXPORT_SYMBOL(iproc_platform_device_alloc); ++ ++/** ++ * iproc_platform_device_add - ++ * wrapper function for platform_device_add ++ * @pdev: platform device we're adding ++ */ ++int iproc_platform_device_add(struct platform_device *pdev) ++{ ++ return platform_device_add(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_add); ++ ++/** ++ * iproc_platform_device_put - ++ * wrapper function for platform_device_put ++ * @pdev: platform device to free ++ */ ++void iproc_platform_device_put(struct platform_device *pdev) ++{ ++ platform_device_put(pdev); ++} ++EXPORT_SYMBOL(iproc_platform_device_put); ++ ++ ++/** ++ * iproc_platform_device_put - ++ * wrapper function for sysfs_create_group ++ * @kobj: The kobject to create the group on ++ * @grp: The attribute group to create ++ */ ++int iproc_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) ++{ ++ return sysfs_create_group(kobj, grp); ++} ++EXPORT_SYMBOL(iproc_sysfs_create_group); ++ ++ ++/** ++ * iproc_sysfs_remove_group - ++ * wrapper function for sysfs_remove_group ++ * @kobj: The kobject which the group is on ++ * @grp: The attribute group to remove ++ */ ++void iproc_sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) ++{ ++ sysfs_remove_group(kobj, grp); ++} ++EXPORT_SYMBOL(iproc_sysfs_remove_group); +diff --git a/arch/arm/plat-iproc/swreset_rec.c b/arch/arm/plat-iproc/swreset_rec.c +new file mode 100644 +index 0000000..aaa0d61 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch new file mode 100644 index 00000000..2147e611 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_swreset_rec.c.patch @@ -0,0 +1,181 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/swreset_rec.c +@@ -0,0 +1,175 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_SWRESET_RECORD_COUNT (4) ++ ++struct swreset_record { ++ int position; ++}; ++ ++struct swreset_record records[MAX_SWRESET_RECORD_COUNT]; ++static unsigned int record_count; ++static unsigned int record_width; ++static DEFINE_SPINLOCK(swrr_lock); ++ ++unsigned int ++swreset_record_get_record_width(void) ++{ ++ return record_width; ++} ++ ++unsigned int ++swreset_record_get_record_count(void) ++{ ++ return record_count; ++} ++ ++SWRR_HANDLE ++swreset_record_register(const char *name) ++{ ++ int i; ++ int j; ++ ++ if (record_count == 0) { ++ return NULL; ++ } ++ ++ /* Use the name as a hash value to try to avoid race condition */ ++ j = 0; ++ while(*name != 0) { ++ j += *name; ++ if (j > 0xff) ++ j = (j & 0xff) + 1; ++ name++; ++ } ++ ++ for(i=0; iposition < 0 || swrr->position >= record_count) ++ return; ++ swrr->position = -1; ++} ++ ++int ++swreset_record_set(SWRR_HANDLE handle, int value) ++{ ++ struct swreset_record *swrr = (struct swreset_record *)handle; ++ void __iomem *reg; ++ unsigned long rval; ++ unsigned long flags; ++ ++ if (handle == NULL) ++ return -1; ++ if (swrr->position < 0 || swrr->position >= record_count) ++ return -1; ++ if (value & ~((1 << record_width) - 1)) ++ return -1; ++ ++ /* This requires atomic operation */ ++ spin_lock_irqsave(&swrr_lock, flags); ++ ++ /* CoStar specific; could require modification for newer chips */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_CLKSET_KEY_OFFSET); ++ writel(0xea68, reg); /* magic number */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL5_OFFSET); ++ writel(readl(reg) | (1 << IPROC_DMU_GENPLL_CONTROL5__SEL_SW_SETTING), reg); ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL7_OFFSET); ++ rval = readl(reg) & ~(1 << (IPROC_DMU_GENPLL_CONTROL7__SW_RESET_REC + swrr->position)); ++ rval |= value << (IPROC_DMU_GENPLL_CONTROL7__SW_RESET_REC + swrr->position); ++ writel(rval, reg); ++ ++ spin_unlock_irqrestore(&swrr_lock, flags); ++ return 0; ++} ++ ++int ++swreset_record_get(SWRR_HANDLE handle, int *value) ++{ ++ struct swreset_record *swrr = (struct swreset_record *)handle; ++ void __iomem *reg; ++ unsigned long flags; ++ ++ if (handle == NULL) ++ return -1; ++ if (swrr->position < 0 || swrr->position >= record_count) ++ return -1; ++ if (value == NULL) ++ return 0; ++ ++ /* This requires atomic operation */ ++ spin_lock_irqsave(&swrr_lock, flags); ++ ++ /* CoStar specific; could require modification for newer chips */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_CLKSET_KEY_OFFSET); ++ writel(0xea68, reg); /* magic number */ ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL5_OFFSET); ++ writel(readl(reg) | (1 << IPROC_DMU_GENPLL_CONTROL5__SEL_SW_SETTING), reg); ++ reg = IOMEM(IPROC_DMU_BASE_VA + IPROC_DMU_GENPLL_CONTROL7_OFFSET); ++ *value = readl(reg) >> IPROC_DMU_GENPLL_CONTROL7__SW_RESET_REC; ++ *value = (*value >> swrr->position) & 1; ++ ++ spin_unlock_irqrestore(&swrr_lock, flags); ++ return 0; ++} ++ ++int __init ++init_swreset_records(void) ++{ ++ int i; ++ for(i=0; i ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct kobject *bcm_kobj; ++ ++static ssize_t ++mem_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ uint32_t addr, val, count = 0, loop = 0; ++ void __iomem *vaddr; ++ char rw; ++ ++ if (sscanf(buf, "%c %x %x", &rw, &addr, &val) == 3) { ++ pr_info("\n"); ++ vaddr = ioremap(addr, PAGE_SIZE); ++ if (rw == 'W' || rw == 'w') { ++ writel(val, vaddr); ++ count = 4; ++ } else if (rw == 'R' || rw == 'r') { ++ count = val; /* count read in val for simplicity */ ++ if (count & 0x3) /* Align to 4 */ ++ count += (4 - (count & 0x3)); ++ } ++ for (; loop < count; loop += 4) { ++ val = readl(vaddr + loop); ++ pr_info("[0x%08x] = 0x%08x\n", addr + loop, val); ++ } ++ iounmap(vaddr); ++ return n; ++ } ++ pr_info("\nUsage: echo " ++ " /sys/bcm/mem\n" ++ "E.g. echo R 0x88CE000 0x40 > /sys/bcm/mem\n" ++ " echo w 0x88CE000 0xDEADBEAF > /sys/bcm/mem\n"); ++ return -EINVAL; ++} ++ ++#ifdef CONFIG_IPROC_TIMER_UNIT_TESTS ++static ssize_t ++iproc_timer_module_cfg(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ char name[255]; ++ unsigned int rate; ++ ++ if (sscanf(buf, "%s %d", name, &rate) == 2) { ++ ++ pr_info("timer name:%s rate(0-32KHz, 1-1MHz, 2-19.5MHz):%d \r\n", ++ name, rate); ++ ++ /* ++ * Assuming that iproc_timer_modules_init has happend already (this is ++ * safe because this function is called during system timer init ++ * itself ++ */ ++ if ( iproc_timer_module_set_rate(name,rate) < 0) { ++ pr_err("iproc_timer_module_cfg: Unable to set the said rate \r\n"); ++ return n; ++ } ++ ++ pr_info("iproc_timer_module_cfg: Configured the module with" ++ "rate %d \r\n", rate); ++ ++ return n; ++ } ++ ++ pr_info("\r\nusage: echo [timer_name(aon-timer/slave-timer)]" ++ "[rate (0-32KHz, 1-1MHz, 2-19.5MHz)] > /sys/bcm/timer_module_cfg \r\n"); ++ ++ return -EINVAL; ++} ++ ++struct iproc_timer *kt; ++struct timer_ch_cfg cfg; ++int timer_callback (void *p); ++ ++/* Note that this is called back from ISR context */ ++int timer_callback (void *p) ++{ ++ pr_info("timer callback \r\n"); ++ return 0; ++} ++ ++static ssize_t ++iproc_timer_start_test(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int ch_num, mode, count; ++ char name[255]; ++ ++ if (sscanf(buf, "%s %d %d %d", name, &ch_num, &mode, &count) == 4) { ++ ++ pr_info("channel_num:%d mode(0-periodic 1-oneshot):%d count:%d \r\n", ++ ch_num, mode, count); ++ ++ if ( (kt=iproc_timer_request (name, ch_num)) < 0) { ++ pr_err("iproc_timer_request returned error \r\n"); ++ goto out; ++ } ++ ++ cfg.mode = mode; ++ cfg.arg = kt; ++ cfg.cb = timer_callback; ++ cfg.reload = count; ++ ++ if ( iproc_timer_config(kt,&cfg) < 0) { ++ pr_err("iproc_timer_config returned error \r\n"); ++ goto out; ++ } ++ ++ if (iproc_timer_set_match_start(kt,count) < 0) { ++ pr_err("iproc_timer_set_match_start returned error \r\n"); ++ goto out; ++ } ++ pr_info("Timer test started \r\n"); ++out: ++ return n; ++ } ++ ++ pr_info("\r\nusage: echo [name (aon-timer/slave-timer)] " ++ "[channel num (0-3)] [mode(0-periodic" ++ "1-oneshot)] [count value] > /sys/bcm/timer_start_test\r\n"); ++ return -EINVAL; ++} ++ ++static ssize_t ++iproc_timer_stop_test(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int ch_num; ++ ++ if (sscanf(buf, "%d", &ch_num) == 1) { ++ pr_info("channel_num:%d \r\n", ch_num); ++ if (iproc_timer_stop(kt) < 0) { ++ pr_err("Unable to stop the timer iproc_timer_stop " ++ "returned error \r\n"); ++ goto out; ++ } ++ ++ if (iproc_timer_free(kt) < 0) { ++ pr_err("Unable to free the timer \r\n"); ++ goto out; ++ } ++ pr_info("Stopped and freed the timer \r\n"); ++out: ++ return n; ++ } ++ ++ pr_info("\r\nusage: echo [channel num (0-3)] > " ++ "/sys/bcm/timer_stop_test\r\n"); ++ return -EINVAL; ++} ++#endif ++ ++static DEVICE_ATTR(mem, 0644, NULL, mem_store); ++ ++#ifdef CONFIG_IPROC_TIMER_UNIT_TESTS ++static DEVICE_ATTR(timer_module_cfg, 0666, NULL, iproc_timer_module_cfg); ++static DEVICE_ATTR(timer_start_test, 0666, NULL, iproc_timer_start_test); ++static DEVICE_ATTR(timer_stop_test, 0666, NULL, iproc); ++#endif ++ ++static struct attribute *bcm_attrs[] = { ++ &dev_attr_mem.attr, ++#ifdef CONFIG_IPROC_TIMER_UNIT_TESTS ++ &dev_attr_timer_module_cfg.attr, ++ &dev_attr_timer_start_test.attr, ++ &dev_attr_timer_stop_test.attr, ++#endif ++ NULL, ++}; ++ ++static struct attribute_group bcm_attr_group = { ++ .attrs = bcm_attrs, ++}; ++ ++static int __init bcm_sysfs_init(void) ++{ ++ bcm_kobj = kobject_create_and_add("bcm", NULL); ++ if (!bcm_kobj) ++ return -ENOMEM; ++ return sysfs_create_group(bcm_kobj, &bcm_attr_group); ++} ++ ++static void __exit bcm_sysfs_exit(void) ++{ ++ sysfs_remove_group(bcm_kobj, &bcm_attr_group); ++} ++ ++module_init(bcm_sysfs_init); ++module_exit(bcm_sysfs_exit); +diff --git a/arch/arm/plat-iproc/timer-sp.c b/arch/arm/plat-iproc/timer-sp.c +new file mode 100644 +index 0000000..7773e1c diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch new file mode 100644 index 00000000..83a19fa1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer-sp.c.patch @@ -0,0 +1,256 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/timer-sp.c +@@ -0,0 +1,250 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++//#include ++#include ++ ++#include ++ ++/* ++ * These timers are currently setup to be clocked at 50MHz. ++ */ ++#define ONE_MHZ (1000000) ++#define TIMER_FREQ_HZ (ONE_MHZ * 500) ++#define TIMER_FREQ_KHZ (TIMER_FREQ_HZ/1000) ++#define TIMER_MIN_RANGE 4 ++ ++#define TIM_COUNT_LO 0x00 /* ACVR rw */ ++#define TIM_COUNT_HI 0x04 /* ACVR ro */ ++#define TIMER_CTRL 0x08 /* ACVR rw */ ++#define TIMER_INT_STAT 0x0C ++#define TIMER_COMP_LO 0x10 ++#define TIMER_COMP_HI 0x14 ++#define TIMER_RELOAD 0x18 ++#define TIMER_CTRL_PRESC_SHFT (8) /* ACVR */ ++ ++#define TIMER_ENABLE (1 << 0) /* ACVR */ ++#define TIMER_CMP (1 << 1) ++#define TIMER_IRQ (1 << 2) ++#define TIMER_AUTO (1 << 3) ++ ++extern unsigned long clk_get_rate(struct clk *clk); ++ ++static void __iomem *clksrc_base; ++static u32 ticks_per_jiffy; ++static u32 timer_ints = 0; ++static unsigned long cpu_clk_freq = 0; ++ ++static cycle_t iproc_read(struct clocksource *cs) ++{ ++ u32 hi; ++ u32 lo; ++ u32 ho; ++ u64 count; ++ ++ /* ++ * Read the upper half to detect a roll-over count ++ */ ++ do { ++ hi = readl(clksrc_base + TIM_COUNT_HI); ++ lo = readl(clksrc_base + TIM_COUNT_LO); ++ ho = readl(clksrc_base + TIM_COUNT_HI); ++ } while(hi != ho); ++ ++ count = (u64) hi << 32 | lo; ++ return count; ++ ++} ++static void iproc_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt); ++ ++static int iproc_set_next_event(unsigned long next, ++ struct clock_event_device *evt); ++static struct clock_event_device iproc_clockevent = { ++ .name = "iproc_gtimer", ++ .shift = 20, ++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, ++ .set_mode = iproc_set_mode, ++ .set_next_event = iproc_set_next_event, ++ .rating = 300, ++ .cpumask = cpu_all_mask, ++}; ++ ++ ++static struct clocksource clocksource_iproc = { ++ .name = "iproc_gtimer", ++ .rating = 300, ++ .read = iproc_read, ++ .mask = CLOCKSOURCE_MASK(64), ++ .shift = 20, ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); ++ ++void __init iproc_clocksource_init(void __iomem *base) ++{ ++ struct clocksource *cs = &clocksource_iproc; ++ struct clk *clk; ++ ++ clksrc_base = base; ++ ++ /* ++ * setup global CPU timer as free-running clocksource ++ * obtain CPU clock frequency from clock module configuration ++ */ ++ clk = clk_get_sys(NULL, "periph_clk"); ++ BUG_ON(IS_ERR_OR_NULL(clk)); ++ clk_prepare(clk); ++ clk_enable(clk); ++ cpu_clk_freq = clk_get_rate(clk); ++ BUG_ON(!cpu_clk_freq); ++ ++ ++ printk(KERN_DEBUG ++ "iproc_clocksource_init: CPU global timer freq %lu\n", ++ cpu_clk_freq); ++ ++ /* ref - arch/arcm/mach-u300/timer.c (2.6.37 vs 2.6.38) */ ++ clocksource_register_hz(cs, cpu_clk_freq); ++} ++ ++ ++static void __iomem *clkevt_base; ++ ++/* ++ * IRQ handler for the timer ++ */ ++ irqreturn_t iproc_timer_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *evt = &iproc_clockevent; ++#warning "iproc_timer_interrupt: Fix this code to receive clock_event handler correctly" ++ ++ /* clear the interrupt */ ++ writel(1, clkevt_base + TIMER_INT_STAT); ++ ++ timer_ints++; ++ evt->event_handler(evt); ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++ u32 ctrl; ++ u32 period; ++ u64 count; ++ ++ ctrl = readl(clkevt_base + TIMER_CTRL); ++ ++ /* Clear mode bits */ ++ ctrl &= ~(TIMER_CMP | TIMER_IRQ | TIMER_AUTO); ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ period = ticks_per_jiffy; ++ count = iproc_read(NULL); ++ count += period; ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ writel(period, clkevt_base + TIMER_RELOAD); ++ ctrl = (TIMER_CMP | ++ TIMER_IRQ | ++ TIMER_AUTO | ++ TIMER_ENABLE); ++ break; ++ ++ case CLOCK_EVT_MODE_ONESHOT: ++ /* period set, and timer enabled in 'next_event' hook */ ++ break; ++ ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ break; ++ default: ++ break; ++ } ++ ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++} ++ ++static int iproc_set_next_event(unsigned long next, ++ struct clock_event_device *evt) ++{ ++ u64 count = iproc_read(NULL); ++ u32 ctrl = readl(clkevt_base + TIMER_CTRL); ++ ++ ctrl &= ~TIMER_CMP; ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ ++ count += next; ++ writel(count & 0xffffffffUL, clkevt_base + TIMER_COMP_LO); ++ //writel(count, clkevt_base + TIM_COUNT_LO); ++ writel(count >> 32, clkevt_base + TIMER_COMP_HI); ++ ++ ctrl |= (TIMER_CMP | TIMER_IRQ); ++ writel(ctrl, clkevt_base + TIMER_CTRL); ++ ++ return 0; ++} ++ ++static struct irqaction iproc_timer_irq = { ++ .name = "iproc_gtimer", ++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_PERCPU, ++ .handler = iproc_timer_interrupt, ++ .dev_id = &iproc_clockevent, ++ .irq = BCM_INT_ID_PPI11, ++}; ++ ++void __init iproc_clockevents_init(void __iomem *base, unsigned int timer_irq) ++{ ++ int ret; ++ clkevt_base = base; ++ ticks_per_jiffy = (cpu_clk_freq/HZ); ++ ++ clockevents_calc_mult_shift(&iproc_clockevent, cpu_clk_freq, TIMER_MIN_RANGE); ++ iproc_clockevent.max_delta_ns = ++ clockevent_delta2ns(0x1fffffff, &iproc_clockevent); ++ iproc_clockevent.min_delta_ns = ++ clockevent_delta2ns(0xf, &iproc_clockevent); ++ iproc_clockevent.cpumask = cpumask_of(0); ++ iproc_clockevent.irq = timer_irq; ++ clockevents_register_device(&iproc_clockevent); ++#warning "iproc_clockevents_init: Fix this code to enable timer irq and pass clock_event handler correctly" ++ ret = setup_percpu_irq(timer_irq, &iproc_timer_irq); ++ if (ret) { ++ printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret); ++ BUG(); ++ } ++ ++ printk(KERN_DEBUG "cpu_clk_freq: %lu\n", cpu_clk_freq); ++ printk(KERN_DEBUG "HZ: %d, ticks_per_jiffy: %u\n", HZ, ticks_per_jiffy); ++ ++ enable_percpu_irq(timer_irq, 0); ++ ++} +diff --git a/arch/arm/plat-iproc/timer.c b/arch/arm/plat-iproc/timer.c +new file mode 100644 +index 0000000..f92e244 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch new file mode 100644 index 00000000..64772bed --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_plat-iproc_timer.c.patch @@ -0,0 +1,285 @@ +--- /dev/null ++++ b/arch/arm/plat-iproc/timer.c +@@ -0,0 +1,280 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_LOCAL_TIMERS ++#include ++#endif ++ ++static struct iproc_timer *gpt_evt = NULL; ++static struct iproc_timer *gpt_src = NULL; ++static void __iomem* proftmr_regbase = IOMEM(IPROC_CCU_PROF_CTL_REG_VA); ++ ++static int gptimer_set_next_event(unsigned long clc, ++ struct clock_event_device *unused) ++{ ++ /* gptimer (0) is disabled by the timer interrupt already ++ * so, here we reload the next event value and re-enable ++ * the timer ++ * ++ * This way, we are potentially losing the time between ++ * timer-interrupt->set_next_event. CPU local timers, when ++ * they come in should get rid of skew ++ */ ++ iproc_timer_set_match_start(gpt_evt,clc); ++ return 0; ++} ++ ++static void gptimer_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *unused) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ /* by default mode is one shot don't do any thing */ ++ break; ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ default: ++ iproc_timer_disable_and_clear(gpt_evt); ++ } ++} ++ ++static cycle_t gptimer_clksrc_read (struct clocksource *cs) ++{ ++ unsigned long msw, lsw; ++ cycle_t count = 0; ++ ++ iproc_timer_get_counter (gpt_src, &msw, &lsw); ++ count = ((cycle_t)msw << 32) | (cycle_t)lsw; ++ return count; ++} ++ ++static struct clock_event_device clockevent_gptimer = { ++ .name = "gpt_event_1", ++ .features = CLOCK_EVT_FEAT_ONESHOT, ++ .shift = 32, ++ .set_next_event = gptimer_set_next_event, ++ .set_mode = gptimer_set_mode ++}; ++ ++static struct clocksource clksrc_gptimer = { ++ .name = "gpt_source_2", ++ .rating = 200, ++ .read = gptimer_clksrc_read, ++ .mask = CLOCKSOURCE_MASK(64), ++ .shift = 16, ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++ ++static void __init gptimer_clockevents_init(void) ++{ ++ clockevent_gptimer.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ++ clockevent_gptimer.shift); ++ ++ clockevent_gptimer.max_delta_ns = ++ clockevent_delta2ns(0xffffffff, &clockevent_gptimer); ++ ++ clockevent_gptimer.min_delta_ns = ++ clockevent_delta2ns(6, &clockevent_gptimer); ++ ++ clockevent_gptimer.cpumask = cpumask_of(0); ++ clockevents_register_device(&clockevent_gptimer); ++} ++ ++static void __init gptimer_clocksource_init(void) ++{ ++ clksrc_gptimer.mult = clocksource_hz2mult(CLOCK_TICK_RATE, ++ clksrc_gptimer.shift); ++ clocksource_register(&clksrc_gptimer); ++ return; ++} ++ ++static int gptimer_interrupt_cb(void *dev) ++{ ++ struct clock_event_device *evt = (struct clock_event_device *)dev; ++ evt->event_handler(evt); ++ return 0; ++} ++ ++static void profile_timer_init(void __iomem *base) ++{ ++ uint32_t reg; ++ ++ /* Reset profile/global timer */ ++ writel(0, base + IPROC_GTIM_GLB_CTL); ++ ++ /* Clear pending interrupts */ ++ reg = readl(base + IPROC_GTIM_GLB_STS); ++ reg &= ~(IPROC_GLB_TIM_CTRL_PRESC_MASK); ++ reg |= (1 << GLBTMR_GLOB_STATUS_EVENT_G_SHIFT); ++ writel(reg, base + IPROC_GTIM_GLB_STS); ++ ++ /* Enable profile timer now with ++ * prescaler = 0, so timer freq = A9 PERIPHCLK ++ * IRQ disabled ++ * Comapre disabled ++ */ ++ ++ reg = readl(base + IPROC_GTIM_GLB_CTL); ++ reg &= ~(IPROC_GLB_TIM_CTRL_PRESC_MASK); ++ reg |= (1 << GLBTMR_GLOB_CTRL_TIMER_EN_G_SHIFT); ++ writel(reg, base + IPROC_GTIM_GLB_CTL); ++} ++ ++static void ++profile_timer_get_counter(void __iomem *base, uint32_t *msw, uint32_t *lsw) ++{ ++ /* Read 64-bit free running counter ++ * 1. Read hi-word ++ * 2. Read low-word ++ * 3. Read hi-word again ++ * 4.1 ++ * if new hi-word is not equal to previously read hi-word, then ++ * start from #1 ++ * 4.2 ++ * if new hi-word is equal to previously read hi-word then stop. ++ */ ++ ++ while (1) { ++ *msw = readl(base + IPROC_GTIM_GLB_HI); ++ *lsw = readl(base + IPROC_GTIM_GLB_LO); ++ if (*msw == readl(base + IPROC_GTIM_GLB_HI)) ++ break; ++ } ++ ++ return; ++} ++ ++static void __init timers_init(struct gp_timer_setup *gpt_setup) ++{ ++ struct timer_ch_cfg evt_tm_cfg; ++ ++ iproc_timer_modules_init (); ++ iproc_timer_module_set_rate(gpt_setup->name, gpt_setup->rate); ++ ++ /* Initialize Event timer */ ++ gpt_evt = iproc_timer_request(gpt_setup->name, gpt_setup->ch_num); ++ if (gpt_evt == NULL) { ++ pr_err("timers_init: Unable to get GPT timer for event\r\n"); ++ } ++ ++ pr_info("timers_init: === SYSTEM TIMER NAME: %s CHANNEL NUMBER %d \ ++ RATE (0-32KHz, 1-1MHz) %d \r\n",gpt_setup->name, ++ gpt_setup->ch_num, gpt_setup->rate); ++ ++ evt_tm_cfg.mode = MODE_PERIODIC; ++ evt_tm_cfg.arg = &clockevent_gptimer; ++ evt_tm_cfg.cb = gptimer_interrupt_cb; ++ ++ iproc_timer_config(gpt_evt, &evt_tm_cfg); ++ ++ gptimer_set_next_event((CLOCK_TICK_RATE / HZ), NULL); ++ ++ /* ++ * IMPORTANT ++ * Note that we don't want to waste a channel for clock source. In iProc ++ * timer module by default there is a counter that keeps counting ++ * irrespective of the channels. So instead of implementing a periodic ++ * timer using a channel (which in the HW is not peridoic) we can ++ * simply read the counters of the timer that is used for event and ++ * send it for source. The only catch is that this timer should not be ++ * stopped by PM or any other sub-systems. ++ */ ++ gpt_src = gpt_evt; ++ ++ /* Initialize the profile timer */ ++ ++ return ; ++} ++ ++void __init iproc_timer_init(struct gp_timer_setup *gpt_setup) ++{ ++ timers_init(gpt_setup); ++ gptimer_clocksource_init(); ++ gptimer_clockevents_init(); ++ gptimer_set_next_event((CLOCK_TICK_RATE / HZ), NULL); ++#ifdef CONFIG_LOCAL_TIMERS ++ twd_base = IOMEM(IPROC_PERIPH_PVT_TIM_REG_VA); ++#endif ++ ++} ++ ++ ++/* Profile timer implementations */ ++ ++/* ++ * TODO: The below profile timer code is retained as it is. ++ * The clock manager is not up yet, once its ready read the ++ * correct frequency from it. ++ * ++ * Right now Global timer runs at 5000000 on FPGA (A9 PERIPHCLK) ++ * Ideally, this should be derived by timer.prof_clk and ++ * prescaler. ++ */ ++ ++#define GLOBAL_TIMER_FREQ_HZ (351875) /* For FPGA only, (temp)*/ ++//#define GLOBAL_TIMER_FREQ_HZ (500000) /* For FPGA only, (temp)*/ ++timer_tick_rate_t timer_get_tick_rate(void) ++{ ++ uint32_t prescaler; ++ ++ prescaler = readl(IPROC_PERIPH_GLB_TIM_REG_BASE); ++ prescaler &= IPROC_GLB_TIM_CTRL_PRESC_MASK; ++ //prescaler >>= IPROC_GLB_TIM_CTRL_PRESC_SHIFT; ++ ++ return (GLOBAL_TIMER_FREQ_HZ / (1 + prescaler)); ++} ++ ++timer_tick_count_t timer_get_tick_count(void) ++{ ++ uint32_t msw, lsw; ++ uint64_t tick; ++ ++ profile_timer_get_counter(proftmr_regbase, &msw, &lsw); ++ ++ tick = (((uint64_t)msw << 32) | ((uint64_t)lsw)); ++ ++ return (*(uint32_t *)(&tick)); ++} ++ ++timer_msec_t timer_ticks_to_msec(timer_tick_count_t ticks) ++{ ++ return (ticks / (timer_get_tick_rate() / 1000)); ++} ++ ++timer_msec_t timer_get_msec(void) ++{ ++ return timer_ticks_to_msec(timer_get_tick_count()); ++} ++ ++EXPORT_SYMBOL(timer_get_tick_count); ++EXPORT_SYMBOL(timer_ticks_to_msec); ++EXPORT_SYMBOL(timer_get_tick_rate); ++EXPORT_SYMBOL(timer_get_msec); +diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c +index 10d1608..af95af2 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch b/packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch new file mode 100644 index 00000000..08fdfda7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/arch_arm_tools_mach-types.patch @@ -0,0 +1,9 @@ +--- a/arch/arm/tools/mach-types ++++ b/arch/arm/tools/mach-types +@@ -1126,3 +1126,4 @@ atdgp318 MACH_ATDGP318 ATDGP318 3494 + m28evk MACH_M28EVK M28EVK 3613 + smdk4212 MACH_SMDK4212 SMDK4212 3638 + smdk4412 MACH_SMDK4412 SMDK4412 3765 ++iproc MACH_IPROC IPROC 4735 +diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c +index e84faff..2233be7 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch new file mode 100644 index 00000000..7446d53f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_Kconfig.patch @@ -0,0 +1,11 @@ +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -136,4 +136,6 @@ source "drivers/hv/Kconfig" + + source "drivers/devfreq/Kconfig" + ++source "drivers/bcmdrivers/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 1b31421..9352f86 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch new file mode 100644 index 00000000..b8059ba5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_Makefile.patch @@ -0,0 +1,9 @@ +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -132,3 +132,4 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/ + obj-$(CONFIG_HYPERV) += hv/ + + obj-$(CONFIG_PM_DEVFREQ) += devfreq/ ++obj-y += bcmdrivers/ +diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c +index 7f9eba9..0eefa12 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch new file mode 100644 index 00000000..e224dcf4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Kconfig.patch @@ -0,0 +1,15 @@ +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -172,6 +172,10 @@ config SYS_HYPERVISOR + bool + default n + ++config GENERIC_CPU_DEVICES ++ bool ++ default n ++ + source "drivers/base/regmap/Kconfig" + + endmenu +diff --git a/drivers/base/Makefile b/drivers/base/Makefile +index 99a375a..1334d89 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch new file mode 100644 index 00000000..d419debd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_Makefile.patch @@ -0,0 +1,22 @@ +--- a/drivers/base/Makefile ++++ b/drivers/base/Makefile +@@ -3,7 +3,8 @@ + obj-y := core.o sys.o bus.o dd.o syscore.o \ + driver.o class.o platform.o \ + cpu.o firmware.o init.o map.o devres.o \ +- attribute_container.o transport_class.o ++ attribute_container.o transport_class.o \ ++ topology.o + obj-$(CONFIG_DEVTMPFS) += devtmpfs.o + obj-y += power/ + obj-$(CONFIG_HAS_DMA) += dma-mapping.o +@@ -12,7 +13,6 @@ obj-$(CONFIG_ISA) += isa.o + obj-$(CONFIG_FW_LOADER) += firmware_class.o + obj-$(CONFIG_NUMA) += node.o + obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o +-obj-$(CONFIG_SMP) += topology.o + ifeq ($(CONFIG_SYSFS),y) + obj-$(CONFIG_MODULES) += module.o + endif +diff --git a/drivers/base/base.h b/drivers/base/base.h +index 21c1b96..b858dfd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch new file mode 100644 index 00000000..a62f9068 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_base.h.patch @@ -0,0 +1,63 @@ +--- a/drivers/base/base.h ++++ b/drivers/base/base.h +@@ -4,7 +4,9 @@ + * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure. + * + * @subsys - the struct kset that defines this subsystem +- * @devices_kset - the list of devices associated ++ * @devices_kset - the subsystem's 'devices' directory ++ * @interfaces - list of subsystem interfaces associated ++ * @mutex - protect the devices, and interfaces lists. + * + * @drivers_kset - the list of drivers associated + * @klist_devices - the klist to iterate over the @devices_kset +@@ -14,10 +16,8 @@ + * @bus - pointer back to the struct bus_type that this structure is associated + * with. + * +- * @class_interfaces - list of class_interfaces associated + * @glue_dirs - "glue" directory to put in-between the parent device to + * avoid namespace conflicts +- * @class_mutex - mutex to protect the children, devices, and interfaces lists. + * @class - pointer back to the struct class that this structure is associated + * with. + * +@@ -28,6 +28,8 @@ + struct subsys_private { + struct kset subsys; + struct kset *devices_kset; ++ struct list_head interfaces; ++ struct mutex mutex; + + struct kset *drivers_kset; + struct klist klist_devices; +@@ -36,9 +38,7 @@ struct subsys_private { + unsigned int drivers_autoprobe:1; + struct bus_type *bus; + +- struct list_head class_interfaces; + struct kset glue_dirs; +- struct mutex class_mutex; + struct class *class; + }; + #define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj) +@@ -94,8 +94,7 @@ extern int hypervisor_init(void); + static inline int hypervisor_init(void) { return 0; } + #endif + extern int platform_bus_init(void); +-extern int system_bus_init(void); +-extern int cpu_dev_init(void); ++extern void cpu_dev_init(void); + + extern int bus_add_device(struct device *dev); + extern void bus_probe_device(struct device *dev); +@@ -116,6 +115,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj); + + extern int devres_release_all(struct device *dev); + ++/* /sys/devices directory */ + extern struct kset *devices_kset; + + #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS) +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index b802cfc..cd8337b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch new file mode 100644 index 00000000..4f60648f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_bus.c.patch @@ -0,0 +1,382 @@ +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -16,9 +16,14 @@ + #include + #include + #include ++#include + #include "base.h" + #include "power/power.h" + ++/* /sys/devices/system */ ++/* FIXME: make static after drivers/base/sys.c is deleted */ ++struct kset *system_kset; ++ + #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) + + /* +@@ -362,6 +367,47 @@ struct device *bus_find_device_by_name(struct bus_type *bus, + } + EXPORT_SYMBOL_GPL(bus_find_device_by_name); + ++/** ++ * subsys_find_device_by_id - find a device with a specific enumeration number ++ * @subsys: subsystem ++ * @id: index 'id' in struct device ++ * @hint: device to check first ++ * ++ * Check the hint's next object and if it is a match return it directly, ++ * otherwise, fall back to a full list search. Either way a reference for ++ * the returned object is taken. ++ */ ++struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id, ++ struct device *hint) ++{ ++ struct klist_iter i; ++ struct device *dev; ++ ++ if (!subsys) ++ return NULL; ++ ++ if (hint) { ++ klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus); ++ dev = next_device(&i); ++ if (dev && dev->id == id && get_device(dev)) { ++ klist_iter_exit(&i); ++ return dev; ++ } ++ klist_iter_exit(&i); ++ } ++ ++ klist_iter_init_node(&subsys->p->klist_devices, &i, NULL); ++ while ((dev = next_device(&i))) { ++ if (dev->id == id && get_device(dev)) { ++ klist_iter_exit(&i); ++ return dev; ++ } ++ } ++ klist_iter_exit(&i); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(subsys_find_device_by_id); ++ + static struct device_driver *next_driver(struct klist_iter *i) + { + struct klist_node *n = klist_next(i); +@@ -489,38 +535,59 @@ out_put: + void bus_probe_device(struct device *dev) + { + struct bus_type *bus = dev->bus; ++ struct subsys_interface *sif; + int ret; + +- if (bus && bus->p->drivers_autoprobe) { ++ if (!bus) ++ return; ++ ++ if (bus->p->drivers_autoprobe) { + ret = device_attach(dev); + WARN_ON(ret < 0); + } ++ ++ mutex_lock(&bus->p->mutex); ++ list_for_each_entry(sif, &bus->p->interfaces, node) ++ if (sif->add_dev) ++ sif->add_dev(dev, sif); ++ mutex_unlock(&bus->p->mutex); + } + + /** + * bus_remove_device - remove device from bus + * @dev: device to be removed + * +- * - Remove symlink from bus's directory. ++ * - Remove device from all interfaces. ++ * - Remove symlink from bus' directory. + * - Delete device from bus's list. + * - Detach from its driver. + * - Drop reference taken in bus_add_device(). + */ + void bus_remove_device(struct device *dev) + { +- if (dev->bus) { +- sysfs_remove_link(&dev->kobj, "subsystem"); +- sysfs_remove_link(&dev->bus->p->devices_kset->kobj, +- dev_name(dev)); +- device_remove_attrs(dev->bus, dev); +- if (klist_node_attached(&dev->p->knode_bus)) +- klist_del(&dev->p->knode_bus); +- +- pr_debug("bus: '%s': remove device %s\n", +- dev->bus->name, dev_name(dev)); +- device_release_driver(dev); +- bus_put(dev->bus); +- } ++ struct bus_type *bus = dev->bus; ++ struct subsys_interface *sif; ++ ++ if (!bus) ++ return; ++ ++ mutex_lock(&bus->p->mutex); ++ list_for_each_entry(sif, &bus->p->interfaces, node) ++ if (sif->remove_dev) ++ sif->remove_dev(dev, sif); ++ mutex_unlock(&bus->p->mutex); ++ ++ sysfs_remove_link(&dev->kobj, "subsystem"); ++ sysfs_remove_link(&dev->bus->p->devices_kset->kobj, ++ dev_name(dev)); ++ device_remove_attrs(dev->bus, dev); ++ if (klist_node_attached(&dev->p->knode_bus)) ++ klist_del(&dev->p->knode_bus); ++ ++ pr_debug("bus: '%s': remove device %s\n", ++ dev->bus->name, dev_name(dev)); ++ device_release_driver(dev); ++ bus_put(dev->bus); + } + + static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv) +@@ -849,14 +916,14 @@ static ssize_t bus_uevent_store(struct bus_type *bus, + static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); + + /** +- * bus_register - register a bus with the system. ++ * __bus_register - register a driver-core subsystem + * @bus: bus. + * + * Once we have that, we registered the bus with the kobject + * infrastructure, then register the children subsystems it has: +- * the devices and drivers that belong to the bus. ++ * the devices and drivers that belong to the subsystem. + */ +-int bus_register(struct bus_type *bus) ++int __bus_register(struct bus_type *bus, struct lock_class_key *key) + { + int retval; + struct subsys_private *priv; +@@ -900,6 +967,8 @@ int bus_register(struct bus_type *bus) + goto bus_drivers_fail; + } + ++ INIT_LIST_HEAD(&priv->interfaces); ++ __mutex_init(&priv->mutex, "subsys mutex", key); + klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); + klist_init(&priv->klist_drivers, NULL, NULL); + +@@ -929,7 +998,7 @@ out: + bus->p = NULL; + return retval; + } +-EXPORT_SYMBOL_GPL(bus_register); ++EXPORT_SYMBOL_GPL(__bus_register); + + /** + * bus_unregister - remove a bus from the system +@@ -941,6 +1010,8 @@ EXPORT_SYMBOL_GPL(bus_register); + void bus_unregister(struct bus_type *bus) + { + pr_debug("bus: '%s': unregistering\n", bus->name); ++ if (bus->dev_root) ++ device_unregister(bus->dev_root); + bus_remove_attrs(bus); + remove_probe_files(bus); + kset_unregister(bus->p->drivers_kset); +@@ -1030,10 +1101,194 @@ void bus_sort_breadthfirst(struct bus_type *bus, + } + EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); + ++/** ++ * subsys_dev_iter_init - initialize subsys device iterator ++ * @iter: subsys iterator to initialize ++ * @subsys: the subsys we wanna iterate over ++ * @start: the device to start iterating from, if any ++ * @type: device_type of the devices to iterate over, NULL for all ++ * ++ * Initialize subsys iterator @iter such that it iterates over devices ++ * of @subsys. If @start is set, the list iteration will start there, ++ * otherwise if it is NULL, the iteration starts at the beginning of ++ * the list. ++ */ ++void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys, ++ struct device *start, const struct device_type *type) ++{ ++ struct klist_node *start_knode = NULL; ++ ++ if (start) ++ start_knode = &start->p->knode_bus; ++ klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode); ++ iter->type = type; ++} ++EXPORT_SYMBOL_GPL(subsys_dev_iter_init); ++ ++/** ++ * subsys_dev_iter_next - iterate to the next device ++ * @iter: subsys iterator to proceed ++ * ++ * Proceed @iter to the next device and return it. Returns NULL if ++ * iteration is complete. ++ * ++ * The returned device is referenced and won't be released till ++ * iterator is proceed to the next device or exited. The caller is ++ * free to do whatever it wants to do with the device including ++ * calling back into subsys code. ++ */ ++struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter) ++{ ++ struct klist_node *knode; ++ struct device *dev; ++ ++ for (;;) { ++ knode = klist_next(&iter->ki); ++ if (!knode) ++ return NULL; ++ dev = container_of(knode, struct device_private, knode_bus)->device; ++ if (!iter->type || iter->type == dev->type) ++ return dev; ++ } ++} ++EXPORT_SYMBOL_GPL(subsys_dev_iter_next); ++ ++/** ++ * subsys_dev_iter_exit - finish iteration ++ * @iter: subsys iterator to finish ++ * ++ * Finish an iteration. Always call this function after iteration is ++ * complete whether the iteration ran till the end or not. ++ */ ++void subsys_dev_iter_exit(struct subsys_dev_iter *iter) ++{ ++ klist_iter_exit(&iter->ki); ++} ++EXPORT_SYMBOL_GPL(subsys_dev_iter_exit); ++ ++int subsys_interface_register(struct subsys_interface *sif) ++{ ++ struct bus_type *subsys; ++ struct subsys_dev_iter iter; ++ struct device *dev; ++ ++ if (!sif || !sif->subsys) ++ return -ENODEV; ++ ++ subsys = bus_get(sif->subsys); ++ if (!subsys) ++ return -EINVAL; ++ ++ mutex_lock(&subsys->p->mutex); ++ list_add_tail(&sif->node, &subsys->p->interfaces); ++ if (sif->add_dev) { ++ subsys_dev_iter_init(&iter, subsys, NULL, NULL); ++ while ((dev = subsys_dev_iter_next(&iter))) ++ sif->add_dev(dev, sif); ++ subsys_dev_iter_exit(&iter); ++ } ++ mutex_unlock(&subsys->p->mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(subsys_interface_register); ++ ++void subsys_interface_unregister(struct subsys_interface *sif) ++{ ++ struct bus_type *subsys = sif->subsys; ++ struct subsys_dev_iter iter; ++ struct device *dev; ++ ++ if (!sif) ++ return; ++ ++ mutex_lock(&subsys->p->mutex); ++ list_del_init(&sif->node); ++ if (sif->remove_dev) { ++ subsys_dev_iter_init(&iter, subsys, NULL, NULL); ++ while ((dev = subsys_dev_iter_next(&iter))) ++ sif->remove_dev(dev, sif); ++ subsys_dev_iter_exit(&iter); ++ } ++ mutex_unlock(&subsys->p->mutex); ++ ++ bus_put(subsys); ++} ++EXPORT_SYMBOL_GPL(subsys_interface_unregister); ++ ++static void system_root_device_release(struct device *dev) ++{ ++ kfree(dev); ++} ++/** ++ * subsys_system_register - register a subsystem at /sys/devices/system/ ++ * @subsys - system subsystem ++ * @groups - default attributes for the root device ++ * ++ * All 'system' subsystems have a /sys/devices/system/ root device ++ * with the name of the subsystem. The root device can carry subsystem- ++ * wide attributes. All registered devices are below this single root ++ * device and are named after the subsystem with a simple enumeration ++ * number appended. The registered devices are not explicitely named; ++ * only 'id' in the device needs to be set. ++ * ++ * Do not use this interface for anything new, it exists for compatibility ++ * with bad ideas only. New subsystems should use plain subsystems; and ++ * add the subsystem-wide attributes should be added to the subsystem ++ * directory itself and not some create fake root-device placed in ++ * /sys/devices/system/. ++ */ ++int subsys_system_register(struct bus_type *subsys, ++ const struct attribute_group **groups) ++{ ++ struct device *dev; ++ int err; ++ ++ err = bus_register(subsys); ++ if (err < 0) ++ return err; ++ ++ dev = kzalloc(sizeof(struct device), GFP_KERNEL); ++ if (!dev) { ++ err = -ENOMEM; ++ goto err_dev; ++ } ++ ++ err = dev_set_name(dev, "%s", subsys->name); ++ if (err < 0) ++ goto err_name; ++ ++ dev->kobj.parent = &system_kset->kobj; ++ dev->groups = groups; ++ dev->release = system_root_device_release; ++ ++ err = device_register(dev); ++ if (err < 0) ++ goto err_dev_reg; ++ ++ subsys->dev_root = dev; ++ return 0; ++ ++err_dev_reg: ++ put_device(dev); ++ dev = NULL; ++err_name: ++ kfree(dev); ++err_dev: ++ bus_unregister(subsys); ++ return err; ++} ++EXPORT_SYMBOL_GPL(subsys_system_register); ++ + int __init buses_init(void) + { + bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); + if (!bus_kset) + return -ENOMEM; ++ ++ system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); ++ if (!system_kset) ++ return -ENOMEM; ++ + return 0; + } +diff --git a/drivers/base/class.c b/drivers/base/class.c +index b80d91c..03243d4 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch new file mode 100644 index 00000000..45591327 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_class.c.patch @@ -0,0 +1,53 @@ +--- a/drivers/base/class.c ++++ b/drivers/base/class.c +@@ -184,9 +184,9 @@ int __class_register(struct class *cls, struct lock_class_key *key) + if (!cp) + return -ENOMEM; + klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put); +- INIT_LIST_HEAD(&cp->class_interfaces); ++ INIT_LIST_HEAD(&cp->interfaces); + kset_init(&cp->glue_dirs); +- __mutex_init(&cp->class_mutex, "struct class mutex", key); ++ __mutex_init(&cp->mutex, "subsys mutex", key); + error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); + if (error) { + kfree(cp); +@@ -460,15 +460,15 @@ int class_interface_register(struct class_interface *class_intf) + if (!parent) + return -EINVAL; + +- mutex_lock(&parent->p->class_mutex); +- list_add_tail(&class_intf->node, &parent->p->class_interfaces); ++ mutex_lock(&parent->p->mutex); ++ list_add_tail(&class_intf->node, &parent->p->interfaces); + if (class_intf->add_dev) { + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) + class_intf->add_dev(dev, class_intf); + class_dev_iter_exit(&iter); + } +- mutex_unlock(&parent->p->class_mutex); ++ mutex_unlock(&parent->p->mutex); + + return 0; + } +@@ -482,7 +482,7 @@ void class_interface_unregister(struct class_interface *class_intf) + if (!parent) + return; + +- mutex_lock(&parent->p->class_mutex); ++ mutex_lock(&parent->p->mutex); + list_del_init(&class_intf->node); + if (class_intf->remove_dev) { + class_dev_iter_init(&iter, parent, NULL, NULL); +@@ -490,7 +490,7 @@ void class_interface_unregister(struct class_interface *class_intf) + class_intf->remove_dev(dev, class_intf); + class_dev_iter_exit(&iter); + } +- mutex_unlock(&parent->p->class_mutex); ++ mutex_unlock(&parent->p->mutex); + + class_put(parent); + } +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 81e0e87..72a7fa8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch new file mode 100644 index 00000000..7b22bd8d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_core.c.patch @@ -0,0 +1,166 @@ +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -118,6 +118,56 @@ static const struct sysfs_ops dev_sysfs_ops = { + .store = dev_attr_store, + }; + ++#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) ++ ++ssize_t device_store_ulong(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ char *end; ++ unsigned long new = simple_strtoul(buf, &end, 0); ++ if (end == buf) ++ return -EINVAL; ++ *(unsigned long *)(ea->var) = new; ++ /* Always return full write size even if we didn't consume all */ ++ return size; ++} ++EXPORT_SYMBOL_GPL(device_store_ulong); ++ ++ssize_t device_show_ulong(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); ++} ++EXPORT_SYMBOL_GPL(device_show_ulong); ++ ++ssize_t device_store_int(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ char *end; ++ long new = simple_strtol(buf, &end, 0); ++ if (end == buf || new > INT_MAX || new < INT_MIN) ++ return -EINVAL; ++ *(int *)(ea->var) = new; ++ /* Always return full write size even if we didn't consume all */ ++ return size; ++} ++EXPORT_SYMBOL_GPL(device_store_int); ++ ++ssize_t device_show_int(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct dev_ext_attribute *ea = to_ext_attr(attr); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); ++} ++EXPORT_SYMBOL_GPL(device_show_int); + + /** + * device_release - free device structure. +@@ -464,7 +514,7 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr, + static struct device_attribute devt_attr = + __ATTR(dev, S_IRUGO, show_dev, NULL); + +-/* kset to create /sys/devices/ */ ++/* /sys/devices/ */ + struct kset *devices_kset; + + /** +@@ -711,6 +761,10 @@ static struct kobject *get_device_parent(struct device *dev, + return k; + } + ++ /* subsystems can specify a default root directory for their devices */ ++ if (!parent && dev->bus && dev->bus->dev_root) ++ return &dev->bus->dev_root->kobj; ++ + if (parent) + return &parent->kobj; + return NULL; +@@ -731,14 +785,6 @@ static void cleanup_device_parent(struct device *dev) + cleanup_glue_dir(dev, dev->kobj.parent); + } + +-static void setup_parent(struct device *dev, struct device *parent) +-{ +- struct kobject *kobj; +- kobj = get_device_parent(dev, parent); +- if (kobj) +- dev->kobj.parent = kobj; +-} +- + static int device_add_class_symlinks(struct device *dev) + { + int error; +@@ -891,6 +937,7 @@ int device_private_init(struct device *dev) + int device_add(struct device *dev) + { + struct device *parent = NULL; ++ struct kobject *kobj; + struct class_interface *class_intf; + int error = -EINVAL; + +@@ -914,6 +961,10 @@ int device_add(struct device *dev) + dev->init_name = NULL; + } + ++ /* subsystems can specify simple device enumeration */ ++ if (!dev_name(dev) && dev->bus && dev->bus->dev_name) ++ dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); ++ + if (!dev_name(dev)) { + error = -EINVAL; + goto name_error; +@@ -922,7 +973,9 @@ int device_add(struct device *dev) + pr_debug("device: '%s': %s\n", dev_name(dev), __func__); + + parent = get_device(dev->parent); +- setup_parent(dev, parent); ++ kobj = get_device_parent(dev, parent); ++ if (kobj) ++ dev->kobj.parent = kobj; + + /* use parent numa_node */ + if (parent) +@@ -982,17 +1035,17 @@ int device_add(struct device *dev) + &parent->p->klist_children); + + if (dev->class) { +- mutex_lock(&dev->class->p->class_mutex); ++ mutex_lock(&dev->class->p->mutex); + /* tie the class to the device */ + klist_add_tail(&dev->knode_class, + &dev->class->p->klist_devices); + + /* notify any interfaces that the device is here */ + list_for_each_entry(class_intf, +- &dev->class->p->class_interfaces, node) ++ &dev->class->p->interfaces, node) + if (class_intf->add_dev) + class_intf->add_dev(dev, class_intf); +- mutex_unlock(&dev->class->p->class_mutex); ++ mutex_unlock(&dev->class->p->mutex); + } + done: + put_device(dev); +@@ -1107,15 +1160,15 @@ void device_del(struct device *dev) + if (dev->class) { + device_remove_class_symlinks(dev); + +- mutex_lock(&dev->class->p->class_mutex); ++ mutex_lock(&dev->class->p->mutex); + /* notify any interfaces that the device is now gone */ + list_for_each_entry(class_intf, +- &dev->class->p->class_interfaces, node) ++ &dev->class->p->interfaces, node) + if (class_intf->remove_dev) + class_intf->remove_dev(dev, class_intf); + /* remove the device from the class list */ + klist_del(&dev->knode_class); +- mutex_unlock(&dev->class->p->class_mutex); ++ mutex_unlock(&dev->class->p->mutex); + } + device_remove_file(dev, &uevent_attr); + device_remove_attrs(dev); +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index 251acea..a3409a1 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch new file mode 100644 index 00000000..acba66e3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_cpu.c.patch @@ -0,0 +1,363 @@ +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -1,8 +1,8 @@ + /* +- * drivers/base/cpu.c - basic CPU class support ++ * CPU subsystem support + */ + +-#include ++#include + #include + #include + #include +@@ -11,43 +11,45 @@ + #include + #include + #include ++#include ++#include + + #include "base.h" + +-static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; +- +-struct sysdev_class cpu_sysdev_class = { ++struct bus_type cpu_subsys = { + .name = "cpu", +- .attrs = cpu_sysdev_class_attrs, ++ .dev_name = "cpu", + }; +-EXPORT_SYMBOL(cpu_sysdev_class); ++EXPORT_SYMBOL_GPL(cpu_subsys); + +-static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); ++static DEFINE_PER_CPU(struct device *, cpu_sys_devices); + + #ifdef CONFIG_HOTPLUG_CPU +-static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr, ++static ssize_t show_online(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + +- return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); ++ return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id)); + } + +-static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr, +- const char *buf, size_t count) ++static ssize_t __ref store_online(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + ssize_t ret; + + cpu_hotplug_driver_lock(); + switch (buf[0]) { + case '0': +- ret = cpu_down(cpu->sysdev.id); ++ ret = cpu_down(cpu->dev.id); + if (!ret) + kobject_uevent(&dev->kobj, KOBJ_OFFLINE); + break; + case '1': +- ret = cpu_up(cpu->sysdev.id); ++ ret = cpu_up(cpu->dev.id); + if (!ret) + kobject_uevent(&dev->kobj, KOBJ_ONLINE); + break; +@@ -60,44 +62,44 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut + ret = count; + return ret; + } +-static SYSDEV_ATTR(online, 0644, show_online, store_online); ++static DEVICE_ATTR(online, 0644, show_online, store_online); + + static void __cpuinit register_cpu_control(struct cpu *cpu) + { +- sysdev_create_file(&cpu->sysdev, &attr_online); ++ device_create_file(&cpu->dev, &dev_attr_online); + } + void unregister_cpu(struct cpu *cpu) + { +- int logical_cpu = cpu->sysdev.id; ++ int logical_cpu = cpu->dev.id; + + unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); + +- sysdev_remove_file(&cpu->sysdev, &attr_online); ++ device_remove_file(&cpu->dev, &dev_attr_online); + +- sysdev_unregister(&cpu->sysdev); ++ device_unregister(&cpu->dev); + per_cpu(cpu_sys_devices, logical_cpu) = NULL; + return; + } + + #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +-static ssize_t cpu_probe_store(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t cpu_probe_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { + return arch_cpu_probe(buf, count); + } + +-static ssize_t cpu_release_store(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t cpu_release_store(struct device *dev, ++ struct device_attribute *attr, + const char *buf, + size_t count) + { + return arch_cpu_release(buf, count); + } + +-static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); +-static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); ++static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); ++static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); + #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ + + #else /* ... !CONFIG_HOTPLUG_CPU */ +@@ -109,15 +111,15 @@ static inline void register_cpu_control(struct cpu *cpu) + #ifdef CONFIG_KEXEC + #include + +-static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr, ++static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr, + char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, sysdev); ++ struct cpu *cpu = container_of(dev, struct cpu, dev); + ssize_t rc; + unsigned long long addr; + int cpunum; + +- cpunum = cpu->sysdev.id; ++ cpunum = cpu->dev.id; + + /* + * Might be reading other cpu's data based on which cpu read thread +@@ -129,7 +131,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute + rc = sprintf(buf, "%Lx\n", addr); + return rc; + } +-static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); ++static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL); + #endif + + /* +@@ -137,12 +139,12 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); + */ + + struct cpu_attr { +- struct sysdev_class_attribute attr; ++ struct device_attribute attr; + const struct cpumask *const * const map; + }; + +-static ssize_t show_cpus_attr(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_cpus_attr(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); +@@ -153,10 +155,10 @@ static ssize_t show_cpus_attr(struct sysdev_class *class, + return n; + } + +-#define _CPU_ATTR(name, map) \ +- { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } ++#define _CPU_ATTR(name, map) \ ++ { __ATTR(name, 0444, show_cpus_attr, NULL), map } + +-/* Keep in sync with cpu_sysdev_class_attrs */ ++/* Keep in sync with cpu_subsys_attrs */ + static struct cpu_attr cpu_attrs[] = { + _CPU_ATTR(online, &cpu_online_mask), + _CPU_ATTR(possible, &cpu_possible_mask), +@@ -166,19 +168,19 @@ static struct cpu_attr cpu_attrs[] = { + /* + * Print values for NR_CPUS and offlined cpus + */ +-static ssize_t print_cpus_kernel_max(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *buf) ++static ssize_t print_cpus_kernel_max(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); + return n; + } +-static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); ++static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); + + /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ + unsigned int total_cpus; + +-static ssize_t print_cpus_offline(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, char *buf) ++static ssize_t print_cpus_offline(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + int n = 0, len = PAGE_SIZE-2; + cpumask_var_t offline; +@@ -205,7 +207,26 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, + n += snprintf(&buf[n], len - n, "\n"); + return n; + } +-static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); ++static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); ++ ++static void cpu_device_release(struct device *dev) ++{ ++ /* ++ * This is an empty function to prevent the driver core from spitting a ++ * warning at us. Yes, I know this is directly opposite of what the ++ * documentation for the driver core and kobjects say, and the author ++ * of this code has already been publically ridiculed for doing ++ * something as foolish as this. However, at this point in time, it is ++ * the only way to handle the issue of statically allocated cpu ++ * devices. The different architectures will have their cpu device ++ * code reworked to properly handle this in the near future, so this ++ * function will then be changed to correctly free up the memory held ++ * by the cpu device. ++ * ++ * Never copy this way of doing things, or you too will be made fun of ++ * on the linux-kerenl list, you have been warned. ++ */ ++} + + /* + * register_cpu - Setup a sysfs device for a CPU. +@@ -218,57 +239,92 @@ static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); + int __cpuinit register_cpu(struct cpu *cpu, int num) + { + int error; +- cpu->node_id = cpu_to_node(num); +- cpu->sysdev.id = num; +- cpu->sysdev.cls = &cpu_sysdev_class; +- +- error = sysdev_register(&cpu->sysdev); + ++ cpu->node_id = cpu_to_node(num); ++ memset(&cpu->dev, 0x00, sizeof(struct device)); ++ cpu->dev.id = num; ++ cpu->dev.bus = &cpu_subsys; ++ cpu->dev.release = cpu_device_release; ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++ cpu->dev.bus->uevent = arch_cpu_uevent; ++#endif ++ error = device_register(&cpu->dev); + if (!error && cpu->hotpluggable) + register_cpu_control(cpu); + if (!error) +- per_cpu(cpu_sys_devices, num) = &cpu->sysdev; ++ per_cpu(cpu_sys_devices, num) = &cpu->dev; + if (!error) + register_cpu_under_node(num, cpu_to_node(num)); + + #ifdef CONFIG_KEXEC + if (!error) +- error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); ++ error = device_create_file(&cpu->dev, &dev_attr_crash_notes); + #endif + return error; + } + +-struct sys_device *get_cpu_sysdev(unsigned cpu) ++struct device *get_cpu_device(unsigned cpu) + { + if (cpu < nr_cpu_ids && cpu_possible(cpu)) + return per_cpu(cpu_sys_devices, cpu); + else + return NULL; + } +-EXPORT_SYMBOL_GPL(get_cpu_sysdev); +- +-int __init cpu_dev_init(void) +-{ +- int err; ++EXPORT_SYMBOL_GPL(get_cpu_device); + +- err = sysdev_class_register(&cpu_sysdev_class); +-#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) +- if (!err) +- err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class); ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); + #endif + +- return err; +-} +- +-static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = { ++static struct attribute *cpu_root_attrs[] = { + #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE +- &attr_probe, +- &attr_release, ++ &dev_attr_probe.attr, ++ &dev_attr_release.attr, ++#endif ++ &cpu_attrs[0].attr.attr, ++ &cpu_attrs[1].attr.attr, ++ &cpu_attrs[2].attr.attr, ++ &dev_attr_kernel_max.attr, ++ &dev_attr_offline.attr, ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++ &dev_attr_modalias.attr, + #endif +- &cpu_attrs[0].attr, +- &cpu_attrs[1].attr, +- &cpu_attrs[2].attr, +- &attr_kernel_max, +- &attr_offline, + NULL + }; ++ ++static struct attribute_group cpu_root_attr_group = { ++ .attrs = cpu_root_attrs, ++}; ++ ++static const struct attribute_group *cpu_root_attr_groups[] = { ++ &cpu_root_attr_group, ++ NULL, ++}; ++ ++#ifdef CONFIG_GENERIC_CPU_DEVICES ++static DEFINE_PER_CPU(struct cpu, cpu_devices); ++#endif ++ ++static void __init cpu_dev_register_generic(void) ++{ ++#ifdef CONFIG_GENERIC_CPU_DEVICES ++ int i; ++ ++ for_each_possible_cpu(i) { ++ if (register_cpu(&per_cpu(cpu_devices, i), i)) ++ panic("Failed to register CPU device"); ++ } ++#endif ++} ++ ++void __init cpu_dev_init(void) ++{ ++ if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups)) ++ panic("Failed to register CPU subsystem"); ++ ++ cpu_dev_register_generic(); ++ ++#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) ++ sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root); ++#endif ++} +diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c +index 763b356..2168f2f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch new file mode 100644 index 00000000..8b5ed74e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_init.c.patch @@ -0,0 +1,12 @@ +--- a/drivers/base/init.c ++++ b/drivers/base/init.c +@@ -31,7 +31,6 @@ void __init driver_init(void) + * core core pieces. + */ + platform_bus_init(); +- system_bus_init(); + cpu_dev_init(); + memory_dev_init(); + } +diff --git a/drivers/base/node.c b/drivers/base/node.c +index 5693ece..90cf357 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch new file mode 100644 index 00000000..a3055586 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_node.c.patch @@ -0,0 +1,34 @@ +--- a/drivers/base/node.c ++++ b/drivers/base/node.c +@@ -317,12 +317,12 @@ struct node node_devices[MAX_NUMNODES]; + int register_cpu_under_node(unsigned int cpu, unsigned int nid) + { + int ret; +- struct sys_device *obj; ++ struct device *obj; + + if (!node_online(nid)) + return 0; + +- obj = get_cpu_sysdev(cpu); ++ obj = get_cpu_device(cpu); + if (!obj) + return 0; + +@@ -339,12 +339,12 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid) + + int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) + { +- struct sys_device *obj; ++ struct device *obj; + + if (!node_online(nid)) + return 0; + +- obj = get_cpu_sysdev(cpu); ++ obj = get_cpu_device(cpu); + if (!obj) + return 0; + +diff --git a/drivers/base/sys.c b/drivers/base/sys.c +index 9dff77b..409f5ce 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch new file mode 100644 index 00000000..665e1f67 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_sys.c.patch @@ -0,0 +1,28 @@ +--- a/drivers/base/sys.c ++++ b/drivers/base/sys.c +@@ -126,7 +126,7 @@ void sysdev_class_remove_file(struct sysdev_class *c, + } + EXPORT_SYMBOL_GPL(sysdev_class_remove_file); + +-static struct kset *system_kset; ++extern struct kset *system_kset; + + int sysdev_class_register(struct sysdev_class *cls) + { +@@ -331,14 +331,6 @@ void sysdev_unregister(struct sys_device *sysdev) + EXPORT_SYMBOL_GPL(sysdev_register); + EXPORT_SYMBOL_GPL(sysdev_unregister); + +-int __init system_bus_init(void) +-{ +- system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); +- if (!system_kset) +- return -ENOMEM; +- return 0; +-} +- + #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) + + ssize_t sysdev_store_ulong(struct sys_device *sysdev, +diff --git a/drivers/base/topology.c b/drivers/base/topology.c +index f6f37a0..ae989c5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch new file mode 100644 index 00000000..a7fad20d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_base_topology.c.patch @@ -0,0 +1,119 @@ +--- a/drivers/base/topology.c ++++ b/drivers/base/topology.c +@@ -23,7 +23,6 @@ + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +-#include + #include + #include + #include +@@ -32,14 +31,14 @@ + #include + + #define define_one_ro_named(_name, _func) \ +-static SYSDEV_ATTR(_name, 0444, _func, NULL) ++ static DEVICE_ATTR(_name, 0444, _func, NULL) + + #define define_one_ro(_name) \ +-static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) ++ static DEVICE_ATTR(_name, 0444, show_##_name, NULL) + + #define define_id_show_func(name) \ +-static ssize_t show_##name(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + unsigned int cpu = dev->id; \ + return sprintf(buf, "%d\n", topology_##name(cpu)); \ +@@ -65,16 +64,16 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) + + #ifdef arch_provides_topology_pointers + #define define_siblings_show_map(name) \ +-static ssize_t show_##name(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + unsigned int cpu = dev->id; \ + return show_cpumap(0, topology_##name(cpu), buf); \ + } + + #define define_siblings_show_list(name) \ +-static ssize_t show_##name##_list(struct sys_device *dev, \ +- struct sysdev_attribute *attr, \ ++static ssize_t show_##name##_list(struct device *dev, \ ++ struct device_attribute *attr, \ + char *buf) \ + { \ + unsigned int cpu = dev->id; \ +@@ -83,15 +82,15 @@ static ssize_t show_##name##_list(struct sys_device *dev, \ + + #else + #define define_siblings_show_map(name) \ +-static ssize_t show_##name(struct sys_device *dev, \ +- struct sysdev_attribute *attr, char *buf) \ ++static ssize_t show_##name(struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ + { \ + return show_cpumap(0, topology_##name(dev->id), buf); \ + } + + #define define_siblings_show_list(name) \ +-static ssize_t show_##name##_list(struct sys_device *dev, \ +- struct sysdev_attribute *attr, \ ++static ssize_t show_##name##_list(struct device *dev, \ ++ struct device_attribute *attr, \ + char *buf) \ + { \ + return show_cpumap(1, topology_##name(dev->id), buf); \ +@@ -124,16 +123,16 @@ define_one_ro_named(book_siblings_list, show_book_cpumask_list); + #endif + + static struct attribute *default_attrs[] = { +- &attr_physical_package_id.attr, +- &attr_core_id.attr, +- &attr_thread_siblings.attr, +- &attr_thread_siblings_list.attr, +- &attr_core_siblings.attr, +- &attr_core_siblings_list.attr, ++ &dev_attr_physical_package_id.attr, ++ &dev_attr_core_id.attr, ++ &dev_attr_thread_siblings.attr, ++ &dev_attr_thread_siblings_list.attr, ++ &dev_attr_core_siblings.attr, ++ &dev_attr_core_siblings_list.attr, + #ifdef CONFIG_SCHED_BOOK +- &attr_book_id.attr, +- &attr_book_siblings.attr, +- &attr_book_siblings_list.attr, ++ &dev_attr_book_id.attr, ++ &dev_attr_book_siblings.attr, ++ &dev_attr_book_siblings_list.attr, + #endif + NULL + }; +@@ -146,16 +145,16 @@ static struct attribute_group topology_attr_group = { + /* Add/Remove cpu_topology interface for CPU device */ + static int __cpuinit topology_add_dev(unsigned int cpu) + { +- struct sys_device *sys_dev = get_cpu_sysdev(cpu); ++ struct device *dev = get_cpu_device(cpu); + +- return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); ++ return sysfs_create_group(&dev->kobj, &topology_attr_group); + } + + static void __cpuinit topology_remove_dev(unsigned int cpu) + { +- struct sys_device *sys_dev = get_cpu_sysdev(cpu); ++ struct device *dev = get_cpu_device(cpu); + +- sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); ++ sysfs_remove_group(&dev->kobj, &topology_attr_group); + } + + static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, +diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c +index 48e06be..8128330 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch new file mode 100644 index 00000000..87dc9367 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcma_host_pci.c.patch @@ -0,0 +1,20 @@ +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -263,11 +263,13 @@ static int bcma_host_pci_resume(struct pci_dev *dev) + #endif /* CONFIG_PM */ + + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { ++#if !IS_ENABLED(CONFIG_BRCMSMAC) + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, +- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, ++#endif ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); +diff --git a/drivers/bcmdrivers/Kconfig b/drivers/bcmdrivers/Kconfig +new file mode 100755 +index 0000000..f0466c2 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch new file mode 100644 index 00000000..1fb68a12 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Kconfig.patch @@ -0,0 +1,90 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/Kconfig +@@ -0,0 +1,84 @@ ++menu "Broadcom iProc Drivers" ++ depends on ARCH_IPROC ++ ++source "drivers/bcmdrivers/timer/Kconfig" ++source "drivers/bcmdrivers/mdio/Kconfig" ++source "drivers/bcmdrivers/dma/Kconfig" ++source "drivers/bcmdrivers/gpio/Kconfig" ++source "drivers/bcmdrivers/qspi/Kconfig" ++source "drivers/bcmdrivers/nand/Kconfig" ++source "drivers/bcmdrivers/pwm/Kconfig" ++source "drivers/bcmdrivers/wdt/Kconfig" ++source "drivers/bcmdrivers/usb2h/Kconfig" ++source "drivers/bcmdrivers/gmac/et/Kconfig" ++source "drivers/bcmdrivers/gmac/hnd/Kconfig" ++source "drivers/bcmdrivers/smbus/Kconfig" ++source "drivers/bcmdrivers/pmu/Kconfig" ++ ++config BCM_IPROC_CA9_PREFETCH ++ tristate "CortexA9 cache auto-prefetching support" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable iProc CortexA9 L1/L2 cache auto-prefetching support ++ ++ If unsure, say N. ++ ++config BCM_BARRIER_PERFORMANCE ++ bool "Linux memory barrier performance improvement" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable linux memory barrier performance improvements ++ ++ If unsure, say N. ++ ++config BCM_MEM_OPTIMIZATION ++ bool "ARM Memory library optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable ARM memory library optimization ++ ++ If unsure, say N. ++ ++config BROADCOM_CUSTOM_SENDFILE ++ bool "Custom Sendfile optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable Broadcom Custom Sendfile optimization ++ ++ If unsure, say N. ++ ++config BCM_CUSTOM_RECVFILE ++ bool "Custom Receivefile optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable Broadcom Custom Receivefile optimization ++ ++ If unsure, say N. ++ ++config BCM_CUSTOM_RECVFILE_MAX_PERF ++# Enabling BCM_CUSTOM_RECVFILE_MAX_PERF gives maximum write performance ++# at the risk of filesystem errors (due to skipping cache invalidation ++# on writes) and exposure to A0 hardware errata for lazy interrupts. ++ bool "Custom Receivefile Max Performance optimization" ++ depends on ARCH_IPROC && BCM_CUSTOM_RECVFILE ++ default n ++ help ++ Enable Broadcom Custom Receivefile Maximum Performance optimization ++ ++ If unsure, say N. ++ ++config BCM_GRO_ENABLE ++ bool "Broadcom GRO Enable" ++ depends on ARCH_IPROC && (ET_NAPI_POLL || ET_NAPI2_POLL) ++ default n ++ help ++ Enable Broadcom Generic Receive Offload ++ ++ If unsure, say N. ++ ++endmenu +diff --git a/drivers/bcmdrivers/Makefile b/drivers/bcmdrivers/Makefile +new file mode 100755 +index 0000000..6a8ba6f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch new file mode 100644 index 00000000..690f6f13 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_Makefile.patch @@ -0,0 +1,27 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/Makefile +@@ -0,0 +1,21 @@ ++# File: bcmdrivers/Makefile ++# ++# Makefile for the Linux kernel modules. ++# ++ ++# The following must have config defined for each driver ++ ++obj-y += timer/ ++obj-y += mdio/ ++obj-y += dma/ ++obj-y += qspi/ ++obj-$(CONFIG_IPROC_MTD_NAND) += nand/ ++obj-y += pwm/ ++obj-y += gpio/ ++obj-y += wdt/ ++obj-y += usb2h/ ++obj-$(CONFIG_ET) += gmac/et/ ++obj-y += gmac/hnd/ ++obj-y += smbus/ ++ ++obj-y += pmu/ +diff --git a/drivers/bcmdrivers/dma/.gitignore b/drivers/bcmdrivers/dma/.gitignore +new file mode 100644 +index 0000000..d741861 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch new file mode 100644 index 00000000..2342d0a7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_.gitignore.patch @@ -0,0 +1,10 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/dma/Kconfig b/drivers/bcmdrivers/dma/Kconfig +new file mode 100644 +index 0000000..652fbb4 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch new file mode 100644 index 00000000..1477e5ec --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Kconfig.patch @@ -0,0 +1,21 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/Kconfig +@@ -0,0 +1,15 @@ ++config IPROC_DMA ++ tristate "DMA support" ++ depends on ARCH_IPROC ++ select DMADEVICES ++ select DMADEVICES_DEBUG ++ select DMADEVICES_VDEBUG ++ select DMA_ENGINE ++ select PL330 ++ select DMAC_PL330 ++ select DMATEST ++ default n ++ help ++ DMA support for pl330 ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/dma/Makefile b/drivers/bcmdrivers/dma/Makefile +new file mode 100644 +index 0000000..0b6a480 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch new file mode 100644 index 00000000..fc4043ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_DMA) += iproc_dma.o ++iproc_dma-objs := dma.o +diff --git a/drivers/bcmdrivers/dma/dma-pl330.h b/drivers/bcmdrivers/dma/dma-pl330.h +new file mode 100644 +index 0000000..bf45e7b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch new file mode 100644 index 00000000..eca1fec7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma-pl330.h.patch @@ -0,0 +1,109 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma-pl330.h +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_DMA_H ++#define __PLAT_DMA_H ++ ++#include ++ ++#define MAX_CHAN_NAME_LENGTH 32 ++ ++/* DMA direction control */ ++enum dma_direction { ++ DMA_DIRECTION_MEM_TO_MEM = 0, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC = 1, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI = 2, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC = 3, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI = 4, ++ DMA_DIRECTION_DEV_TO_DEV = 5 /* Invalid, unsupported */ ++}; ++#define DMA_DIRECTION_MASK 0x7 ++ ++/* Channel configurations definition */ ++#define DMA_CFG_SRC_ADDR_FIXED (0x0 << 0) ++#define DMA_CFG_SRC_ADDR_INCREMENT (0x1 << 0) ++#define DMA_CFG_DST_ADDR_FIXED (0x0 << 14) ++#define DMA_CFG_DST_ADDR_INCREMENT (0x1 << 14) ++ ++#define DMA_CFG_BURST_SIZE_MASK (0x7 << 1) ++#define DMA_CFG_BURST_SIZE_1 (0x0 << 1) ++#define DMA_CFG_BURST_SIZE_2 (0x1 << 1) ++#define DMA_CFG_BURST_SIZE_4 (0x2 << 1) ++#define DMA_CFG_BURST_SIZE_8 (0x3 << 1) ++#define DMA_CFG_BURST_SIZE_16 (0x4 << 1) ++#define DMA_CFG_BURST_SIZE_32 (0x5 << 1) ++#define DMA_CFG_BURST_SIZE_64 (0x6 << 1) ++#define DMA_CFG_BURST_SIZE_128 (0x7 << 1) ++ ++#define DMA_CFG_BURST_LENGTH_MASK (0xF << 4) ++#define DMA_CFG_BURST_LENGTH_1 (0x0 << 4) ++#define DMA_CFG_BURST_LENGTH_2 (0x1 << 4) ++#define DMA_CFG_BURST_LENGTH_3 (0x2 << 4) ++#define DMA_CFG_BURST_LENGTH_4 (0x3 << 4) ++#define DMA_CFG_BURST_LENGTH_5 (0x4 << 4) ++#define DMA_CFG_BURST_LENGTH_6 (0x5 << 4) ++#define DMA_CFG_BURST_LENGTH_7 (0x6 << 4) ++#define DMA_CFG_BURST_LENGTH_8 (0x7 << 4) ++#define DMA_CFG_BURST_LENGTH_9 (0x8 << 4) ++#define DMA_CFG_BURST_LENGTH_10 (0x9 << 4) ++#define DMA_CFG_BURST_LENGTH_11 (0xA << 4) ++#define DMA_CFG_BURST_LENGTH_12 (0xB << 4) ++#define DMA_CFG_BURST_LENGTH_13 (0xC << 4) ++#define DMA_CFG_BURST_LENGTH_14 (0xD << 4) ++#define DMA_CFG_BURST_LENGTH_15 (0xE << 4) ++#define DMA_CFG_BURST_LENGTH_16 (0xF << 4) ++ ++#define DMA_CFG_BURST_LEN(x) (((x - 1) & 0xF) << 4) ++ ++/* src and dest burst size and burst length are assumed to be same */ ++ ++enum pl330_xfer_status { ++ DMA_PL330_XFER_OK, ++ DMA_PL330_XFER_ERR, ++ DMA_PL330_XFER_ABORT, ++}; ++ ++struct dma_transfer_list { ++ dma_addr_t srcaddr; /* src address */ ++ dma_addr_t dstaddr; /* dst address */ ++ unsigned int xfer_size; /* In bytes */ ++ struct list_head next; /* Next item */ ++}; ++ ++typedef void (*pl330_xfer_callback_t) (void *private_data, ++ enum pl330_xfer_status status); ++ ++int dma_request_chan(unsigned int *chan, const char *name); ++int dma_free_chan(unsigned int chan); ++int dma_map_peripheral(unsigned int chan, const char *peri_name); ++int dma_unmap_peripheral(unsigned int chan); ++int dma_setup_transfer(unsigned int chan, dma_addr_t s, dma_addr_t d, ++ unsigned int xfer_size, int ctrl, int cfg); ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int ctrl, int cfg); ++int dma_start_transfer(unsigned int chan); ++int dma_stop_transfer(unsigned int chan); ++int dma_shutdown_all_chan(void); ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t cb, void *pri); ++int dma_free_callback(unsigned int chan); ++ ++#endif /* __PLAT_DMA_H */ +diff --git a/drivers/bcmdrivers/dma/dma.c b/drivers/bcmdrivers/dma/dma.c +new file mode 100755 +index 0000000..2ff23da diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch new file mode 100644 index 00000000..2a1a11d8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma.c.patch @@ -0,0 +1,892 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma.c +@@ -0,0 +1,886 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "pl330-pdata.h" ++#include "dma-pl330.h" ++ ++#define IPROC_IDM_DMAC_RESET_CONTROL (0x18114800) ++#define IPROC_IDM_DMAC_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_DMAC_RESET_CONTROL) ++ ++/** ++ * struct pl330_chan_desc - Peripheral channel descriptor. ++ */ ++struct pl330_chan_desc { ++ int id; /* channel ID for the client */ ++ struct list_head node; /* Link to next channel desc */ ++ bool is_peri_mapped; /*Is peripheral mapped?, false if mem to mem */ ++ char *name[MAX_CHAN_NAME_LENGTH]; /* Name of the peripheral */ ++ int event_id; /* ID of event/Interrupt line to notify */ ++ u8 peri_req_id; /* mapped peripheral request interface(PRI) ID */ ++ void *pl330_chan_id; /* PL330 channel id alloted */ ++ unsigned int options; /* DMA options */ ++ struct pl330_reqcfg rqcfg; /* DMA req configurations */ ++ pl330_xfer_callback_t xfer_callback; /* DMA callback function */ ++ void *client_cookie; /* client data for callback fn */ ++ bool in_use; /* is DMA channel busy */ ++ bool is_setup; /* Is 'pl330_req' having valid transfer setup */ ++ struct pl330_req req; /* A DMA request item */ ++}; ++ ++/** ++ * struct pl330_dmac_desc - PL330 DMAC Descriptor. ++ */ ++struct pl330_dmac_desc { ++ struct pl330_info *pi; /* PL330 DMAC info */ ++ int irq_start; /* First PL330 Irq mapped */ ++ int irq_end; /* Last Irq number mapped */ ++ struct list_head chan_list; /* List of channel descriptors */ ++ int chan_count; /* channel descriptors count */ ++}; ++ ++/* PL330 DMAC Descriptor structure */ ++static struct pl330_dmac_desc *dmac = NULL; /* Allocate on platform device probe */ ++/* global resources lock */ ++static DEFINE_SPINLOCK(lock); ++ ++/* always call this function with global spinlock held */ ++static struct pl330_chan_desc *chan_id_to_cdesc(int id) ++{ ++ struct pl330_chan_desc *cdesc; ++ ++ list_for_each_entry(cdesc, &dmac->chan_list, node) ++ if (cdesc->id == id) ++ return cdesc; ++ ++ return NULL; ++} ++ ++static void _cleanup_req(struct pl330_req *rq) ++{ ++ struct pl330_xfer *x, *nxt; ++ ++ if (!rq) ++ return; ++ ++ rq->rqtype = DEVTODEV; /* Invalid type */ ++ ++ if (rq->cfg) { ++ kfree(rq->cfg); ++ rq->cfg = NULL; ++ } ++ ++ if (!rq->x) ++ return; ++ ++ /* Free all the xfer items */ ++ x = rq->x; ++ do { ++ nxt = x->next; ++ kfree(x); ++ x = nxt; ++ } while (x); ++ rq->x = NULL; ++ ++ return; ++} ++ ++static void _free_cdesc(struct pl330_chan_desc *cdesc) ++{ ++ /* Deallocate all mapped peripherals */ ++ if (cdesc->is_peri_mapped) { ++ cdesc->is_peri_mapped = false; ++ } ++ ++ /* Release PL330 channel thread */ ++ pl330_release_channel(cdesc->pl330_chan_id); ++ ++ list_del(&cdesc->node); ++ dmac->chan_count--; ++ kfree(cdesc); ++} ++ ++static void pl330_req_callback(void *token, enum pl330_op_err err) ++{ ++ struct pl330_req *r = token; ++ enum pl330_xfer_status stat; ++ struct pl330_chan_desc *c = ++ container_of(r, struct pl330_chan_desc, req); ++ ++ printk("\n----> %s ()\n", __func__); ++ if (c && c->xfer_callback) { ++ switch (err) { ++ case PL330_ERR_NONE: ++ stat = DMA_PL330_XFER_OK; ++ break; ++ case PL330_ERR_ABORT: ++ stat = DMA_PL330_XFER_ABORT; ++ break; ++ case PL330_ERR_FAIL: ++ stat = DMA_PL330_XFER_ERR; ++ break; ++ default: ++ stat = DMA_PL330_XFER_OK; ++ break; ++ } ++ /* call client callback function */ ++ c->xfer_callback(c->client_cookie, stat); ++ } ++} ++ ++int dma_request_chan(unsigned int *chan, const char *name) ++{ ++ int ch, err = -1; ++ //enum dma_peri peri; ++ u8 pri_id; ++ void *pl330_chan_id = NULL; ++ struct pl330_chan_desc *cdesc = NULL; ++ unsigned long flags; ++ bool is_peri = false; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* channel request for a 'named' peripheral, NULL if memory<->memory DMA */ ++ /* no peripheral mapping in IPROC */ ++ ++ /* Allocate PL330 DMA channel thread first */ ++ pl330_chan_id = pl330_request_channel(dmac->pi); ++ if (!pl330_chan_id) { ++ dev_info(dmac->pi->dev, ++ "Failed to allocate PL330 channel thread!!!\n"); ++ goto err_1; ++ } ++ ++ ++ if (dmac->chan_count >= 8) ++ { ++ dev_info(dmac->pi->dev, "MAX DMAC channel exceeded\n"); ++ goto err_2; ++ } ++ ++ /* No peripheral mapping in IPROC */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Channel allocation is done, create a 'channel descriptor' for the client */ ++ cdesc = (struct pl330_chan_desc *)kzalloc(sizeof(*cdesc), GFP_KERNEL); ++ ++ spin_lock_irqsave(&lock, flags); ++ if (!cdesc) { ++ err = -ENOMEM; ++ goto err_4; ++ } ++ ++ /* Populate the cdesc and return channel id to client */ ++ cdesc->id = dmac->chan_count; ++ cdesc->xfer_callback = NULL; ++ cdesc->client_cookie = NULL; ++ cdesc->is_peri_mapped = is_peri; ++ cdesc->event_id = 0; /* always use INTR/EVT line 0 */ ++ cdesc->peri_req_id = pri_id; ++ cdesc->pl330_chan_id = pl330_chan_id; ++ cdesc->in_use = false; ++ cdesc->req.rqtype = DEVTODEV; /* set invalid type */ ++ if (name) ++ strlcpy(cdesc->name, name, MAX_CHAN_NAME_LENGTH); ++ ++ /* Attach cdesc to DMAC channel list */ ++ list_add_tail(&cdesc->node, &dmac->chan_list); ++ dmac->chan_count++; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Give the channel ID to client */ ++ *chan = cdesc->id; ++ return 0; ++ ++ err_4: ++ err_3: ++ err_2: ++ pl330_release_channel(pl330_chan_id); ++ err_1: ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return err; ++} ++ ++int dma_free_chan(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *cdesc; ++ ++ spin_lock_irqsave(&lock, flags); ++ cdesc = chan_id_to_cdesc(chan); ++ if (!cdesc || cdesc->in_use) /* can free id channel is active */ ++ goto err; ++ ++ _cleanup_req(&cdesc->req); ++ ++ _free_cdesc(cdesc); ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_map_peripheral(unsigned int chan, const char *peri_name) ++{ ++ struct pl330_chan_desc *c = NULL; ++ unsigned long flags; ++ //enum dma_peri peri; ++ u8 pri_id; ++ ++ if (!peri_name) ++ return -1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err_ret; ++ ++ /* If a peripheral is already mapped, return failure */ ++ if (c->is_peri_mapped) { ++ dev_info(dmac->pi->dev, ++ "Already peripheral mapped, need to unmap first!!!\n"); ++ goto err_ret; ++ } ++ ++ /* no peripheral mapping in IPROC */ ++ ++ /* no peripheral mapping in IPROC */ ++ ++ c->peri_req_id = pri_id; ++ c->is_peri_mapped = true; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_unmap_peripheral(unsigned int chan) ++{ ++ struct pl330_chan_desc *c = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err_ret; ++ ++ /* If a peripheral is already mapped or channel in use, return failure */ ++ if (!c->is_peri_mapped || c->in_use) { ++ dev_info(dmac->pi->dev, "Peripheral is not mapped\n"); ++ goto err_ret; ++ } ++ ++ c->is_peri_mapped = false; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_setup_transfer(unsigned int chan, ++ dma_addr_t src_addr, ++ dma_addr_t dst_addr, ++ unsigned int xfer_size, int control, int cfg) ++{ ++ unsigned long flags; ++ enum pl330_reqtype rqtype; ++ struct pl330_reqcfg *config; ++ struct pl330_xfer *xfer; ++ struct pl330_chan_desc *c; ++ int err = -1; ++ ++ if (!xfer_size) ++ goto err1; ++ ++ /* DMA transfer direction */ ++ switch (control & DMA_DIRECTION_MASK) { ++ /* Peripheral transfers with DMAC flow control are ++ * treated as Mem to Mem transfers at PL330 microcode level. ++ */ ++ case DMA_DIRECTION_MEM_TO_MEM: ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC: ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC: ++ rqtype = MEMTOMEM; ++ break; ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI: ++ rqtype = MEMTODEV; ++ break; ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI: ++ rqtype = DEVTOMEM; ++ break; ++ case DMA_DIRECTION_DEV_TO_DEV: ++ default: ++ rqtype = DEVTODEV; /*Unsupported */ ++ break; ++ }; ++ ++ if (rqtype == DEVTODEV) ++ goto err1; ++ ++ /* Burst size max is 64 bit(AXI), not supporting >64 bit burst size */ ++ if ((cfg & DMA_CFG_BURST_SIZE_MASK) > DMA_CFG_BURST_SIZE_8) ++ goto err1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ if (c->in_use || c->is_setup) { ++ dev_info(dmac->pi->dev, ++ "Cant setup transfer, already setup/running\n"); ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ }; ++ ++ if ((rqtype != DMA_DIRECTION_MEM_TO_MEM) && (!c->is_peri_mapped)) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ c->is_setup = true; /* Mark it now, for setup */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Allocate */ ++ config = (struct pl330_reqcfg *)kzalloc(sizeof(*config), GFP_KERNEL); ++ if (!config) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ xfer = (struct pl330_xfer *)kzalloc(sizeof(*xfer), GFP_KERNEL); ++ if (!xfer) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ ++ /* configuration options */ ++ config->src_inc = (cfg & DMA_CFG_SRC_ADDR_INCREMENT) ? 1 : 0; ++ config->dst_inc = (cfg & DMA_CFG_DST_ADDR_INCREMENT) ? 1 : 0; ++ /* Burst size */ ++ config->brst_size = (cfg & DMA_CFG_BURST_SIZE_MASK) >> 1; ++ /* Burst Length */ ++ config->brst_len = (((cfg & DMA_CFG_BURST_LENGTH_MASK) >> 4) + 1); ++ ++ /* default settings: Noncacheable, nonbufferable, no swapping */ ++ config->scctl = SCCTRL0; ++ config->dcctl = DCCTRL0; ++ config->swap = SWAP_NO; ++ ++ /* TrustZone security AXPROT[2:0} = 000 */ ++ config->insnaccess = false; /* tied LOW */ ++ config->nonsecure = true; /* DMAC boots in Non Secure Mode */ ++ config->privileged = false; ++ ++ xfer->src_addr = src_addr; ++ xfer->dst_addr = dst_addr; ++ xfer->bytes = xfer_size; ++ xfer->next = NULL; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* Attach the request */ ++ c->req.rqtype = rqtype; ++ ++ if (rqtype != MEMTOMEM) ++ c->req.peri = c->peri_req_id; ++ ++ /* callback function */ ++ c->req.xfer_cb = pl330_req_callback; ++ c->req.token = &c->req; /* callback data */ ++ /* attach configuration */ ++ c->req.cfg = config; ++ /* attach xfer item */ ++ c->req.x = xfer; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err2: ++ kfree(config); ++ err1: ++ return err; ++} ++ ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int control, int cfg) ++{ ++ unsigned long flags; ++ enum pl330_reqtype rqtype; ++ struct pl330_reqcfg *config; ++ struct pl330_xfer *xfer_front, *nxt, *priv; ++ struct pl330_chan_desc *c; ++ struct dma_transfer_list *lli; ++ int err = -1; ++ ++ if (!head) ++ return -1; ++ ++ /* DMA transfer direction */ ++ switch (control & DMA_DIRECTION_MASK) { ++ /* Peripheral transfers with DMAC flow control are ++ * treated as Mem to Mem transfers at PL330 microcode level. ++ */ ++ case DMA_DIRECTION_MEM_TO_MEM: ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC: ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC: ++ rqtype = MEMTOMEM; ++ break; ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI: ++ rqtype = MEMTODEV; ++ break; ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI: ++ rqtype = DEVTOMEM; ++ break; ++ case DMA_DIRECTION_DEV_TO_DEV: ++ default: ++ rqtype = DEVTODEV; /*Unsupported */ ++ break; ++ }; ++ ++ if (rqtype == DEVTODEV) ++ goto err1; ++ ++ /* Burst size max is 64 bit(AXI), not supporting > 64 bit burst size */ ++ if ((cfg & DMA_CFG_BURST_SIZE_MASK) > DMA_CFG_BURST_SIZE_8) ++ goto err1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ if (c->in_use || c->is_setup) { ++ dev_info(dmac->pi->dev, ++ "Cant setup transfer, already setup/running\n"); ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ }; ++ ++ if ((rqtype != DMA_DIRECTION_MEM_TO_MEM) && (!c->is_peri_mapped)) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ c->is_setup = true; /* Mark it now, for setup */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Allocate config strcuture */ ++ config = (struct pl330_reqcfg *)kzalloc(sizeof(*config), GFP_KERNEL); ++ if (!config) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ /* configuration options */ ++ config->src_inc = (cfg & DMA_CFG_SRC_ADDR_INCREMENT) ? 1 : 0; ++ config->dst_inc = (cfg & DMA_CFG_DST_ADDR_INCREMENT) ? 1 : 0; ++ /* Burst size */ ++ config->brst_size = (cfg & DMA_CFG_BURST_SIZE_MASK) >> 1; ++ /* Burst Length */ ++ config->brst_len = (((cfg & DMA_CFG_BURST_LENGTH_MASK) >> 4) + 1); ++ ++ /* default settings: Noncacheable, nonbufferable, no swapping */ ++ config->scctl = SCCTRL0; ++ config->dcctl = DCCTRL0; ++ config->swap = SWAP_NO; ++ ++ /* TrustZone security AXPROT[2:0} = 000 */ ++ config->insnaccess = false; /* tied LOW */ ++ config->nonsecure = true; /* DMAC boots in non Secure Mode */ ++ config->privileged = false; /* AXPROT[2:0] = 000 */ ++ ++ /* Generate xfer list based on linked list passed */ ++ xfer_front = NULL; ++ list_for_each_entry(lli, head, next) { ++ ++ if (!lli->xfer_size) ++ continue; ++ ++ nxt = (struct pl330_xfer *)kzalloc(sizeof(*nxt), GFP_KERNEL); ++ if (!nxt) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ nxt->src_addr = lli->srcaddr; ++ nxt->dst_addr = lli->dstaddr; ++ nxt->bytes = lli->xfer_size; ++ nxt->next = NULL; ++ ++ if (!xfer_front) { ++ xfer_front = nxt; /* First Item */ ++ priv = nxt; ++ } else { ++ priv->next = nxt; /* Add to the tail */ ++ priv = nxt; ++ } ++ } ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* Attach the request */ ++ c->req.rqtype = rqtype; ++ ++ if (rqtype != MEMTOMEM) ++ c->req.peri = c->peri_req_id; ++ ++ /* callback function */ ++ c->req.xfer_cb = pl330_req_callback; ++ c->req.token = &c->req; /* callback data */ ++ /* attach configuration */ ++ c->req.cfg = config; ++ /* attach xfer item list */ ++ c->req.x = xfer_front; ++ c->is_setup = true; /* Mark the xfer item as valid */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err2: ++ /* Free all allocated xfer items */ ++ if (xfer_front) { ++ nxt = xfer_front; ++ while (nxt->next) { ++ priv = nxt; ++ nxt = nxt->next; ++ kfree(priv); ++ } ++ } ++ kfree(config); ++ err1: ++ return err; ++} ++ ++int dma_start_transfer(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ ++ if (!c || !c->is_setup || c->in_use) ++ goto err; ++ ++ /* Acquire DMUX semaphore while microcode loading ++ * This call always success because protect(unprotect) happen ++ * atomically within global spinlock. ++ */ ++ if (pl330_submit_req(c->pl330_chan_id, &c->req) != 0) ++ goto err2; ++ ++ /* Start DMA channel thread */ ++ if (pl330_chan_ctrl(c->pl330_chan_id, PL330_OP_START) != 0) { ++ goto err2; ++ } ++ ++ c->in_use = true; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++ err2: ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_stop_transfer(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ pl330_chan_ctrl(c->pl330_chan_id, PL330_OP_FLUSH); ++ ++ /* Free the completed transfer req */ ++ c->in_use = false; ++ c->is_setup = false; ++ /* free memory allocated for this request */ ++ _cleanup_req(&c->req); ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t callback, void *private_data) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ c->xfer_callback = callback; ++ c->client_cookie = private_data; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_free_callback(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ c->xfer_callback = NULL; ++ c->client_cookie = NULL; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++ ++} ++ ++static irqreturn_t pl330_irq_handler(int irq, void *data) ++{ ++ printk("\n-----> %s(): irq = %d\n", __func__, irq); ++ if (pl330_update(data)) ++ return IRQ_HANDLED; ++ else ++ return IRQ_NONE; ++} ++ ++static int pl330_probe(struct platform_device *pdev) ++{ ++ struct pl330_dmac_desc *pd; ++ struct iproc_pl330_data *pl330_pdata; ++ struct pl330_info *pl330_info; ++ int ret, i, irq_start, irq; ++ ++ printk("\niproc-dmac-pl330: Probe ()\n"); ++ ++ pl330_pdata = pdev->dev.platform_data; ++ ++ /* Only One Pl330 device is supported, ++ * since PL330 is closely bound to DMUX logic ++ */ ++ if (dmac) { ++ dev_err(&pdev->dev, "Multiple devices are not supported!!!\n"); ++ ret = -ENODEV; ++ goto probe_err1; ++ } ++ ++ /* Platform data is required */ ++ if (!pl330_pdata) { ++ dev_err(&pdev->dev, "platform data missing!\n"); ++ ret = -ENODEV; ++ goto probe_err1; ++ } ++ ++ pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL); ++ if (!pl330_info) { ++ ret = -ENOMEM; ++ goto probe_err1; ++ } ++ ++ pl330_info->pl330_data = NULL; ++ pl330_info->client_data = NULL; ++ pl330_info->dev = &pdev->dev; ++ ++ /* For NS DMAC is in non-secure mode */ ++ pl330_info->base = (void __iomem *)pl330_pdata->dmac_ns_base; ++ /* pl330_info->base = (void __iomem *)pl330_pdata->dmac_s_base; */ ++ ++ /* Get the first IRQ line */ ++ irq_start = pl330_pdata->irq_base; ++ irq = irq_start; ++ ++ for (i = 0; i < pl330_pdata->irq_line_count; i++) { ++ irq = irq_start + i; ++ ret = request_irq(irq, pl330_irq_handler, 0, ++ dev_name(&pdev->dev), pl330_info); ++ if (ret) { ++ irq--; ++ goto probe_err2; ++ } ++ } ++ ++ ret = pl330_add(pl330_info); ++ if (ret) ++ goto probe_err3; ++ ++ /* Allocate DMAC descriptor */ ++ pd = kmalloc(sizeof(*pd), GFP_KERNEL); ++ if (!pd) { ++ ret = -ENOMEM; ++ goto probe_err4; ++ } ++ ++ /* Hook the info */ ++ pd->pi = pl330_info; ++ pd->irq_start = irq_start; ++ pd->irq_end = irq; ++ /* init channel desc list, channels are added during dma_request_chan() */ ++ pd->chan_list.next = pd->chan_list.prev = &pd->chan_list; ++ pd->chan_count = 0; ++ ++ /* Assign the DMAC descriptor */ ++ dmac = pd; ++ ++ printk(KERN_INFO ++ "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name); ++ printk(KERN_INFO ++ "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", ++ pl330_info->pcfg.data_buf_dep, ++ pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan, ++ pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events); ++ ++ return 0; ++ ++ probe_err4: ++ pl330_del(pl330_info); ++ probe_err3: ++ probe_err2: ++ while (irq >= irq_start) { ++ free_irq(irq, pl330_info); ++ irq--; ++ } ++ ++ kfree(pl330_info); ++ probe_err1: ++ return ret; ++} ++ ++static int pl330_remove(struct platform_device *pdev) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *cdesc; ++ int irq; ++ ++ spin_lock_irqsave(&lock, flags); ++ /* Free all channel descriptors first */ ++ list_for_each_entry(cdesc, &dmac->chan_list, node) { ++ /* free requests */ ++ _cleanup_req(&cdesc->req); ++ /* Free channel desc */ ++ _free_cdesc(cdesc); ++ } ++ ++ /* Free interrupt resource */ ++ for (irq = dmac->irq_start; irq <= dmac->irq_end; irq++) ++ free_irq(irq, dmac->pi); ++ ++ pl330_del(dmac->pi); ++ /* free PL330 info handle */ ++ kfree(dmac->pi); ++ /* Free dmac descriptor */ ++ kfree(dmac); ++ dmac = NULL; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++} ++ ++static struct platform_driver pl330_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "iproc-dmac-pl330", ++ }, ++ .probe = pl330_probe, ++ .remove = pl330_remove, ++}; ++ ++static int __init pl330_init(void) ++{ ++ int dmac_reset_state; ++ ++ dmac_reset_state = readl_relaxed(IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ printk("Initial dmac_reset_state is: %08x\n", dmac_reset_state); ++ if ((dmac_reset_state & 1) == 1) ++ { ++ writel_relaxed(0x0, IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ dmac_reset_state = readl_relaxed(IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ printk("dmac_reset_state is set and now it is: %08x\n", dmac_reset_state); ++ } ++ return platform_driver_register(&pl330_driver); ++} ++ ++module_init(pl330_init); ++ ++static void __exit pl330_exit(void) ++{ ++ platform_driver_unregister(&pl330_driver); ++ return; ++} ++ ++module_exit(pl330_exit); ++ ++EXPORT_SYMBOL(dma_request_chan); ++EXPORT_SYMBOL(dma_free_chan); ++EXPORT_SYMBOL(dma_map_peripheral); ++EXPORT_SYMBOL(dma_unmap_peripheral); ++EXPORT_SYMBOL(dma_setup_transfer); ++EXPORT_SYMBOL(dma_setup_transfer_list); ++EXPORT_SYMBOL(dma_start_transfer); ++EXPORT_SYMBOL(dma_stop_transfer); ++EXPORT_SYMBOL(dma_register_callback); ++EXPORT_SYMBOL(dma_free_callback); +diff --git a/drivers/bcmdrivers/dma/dma_drv.h b/drivers/bcmdrivers/dma/dma_drv.h +new file mode 100644 +index 0000000..ca5a6b5 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch new file mode 100644 index 00000000..30e54716 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_dma_drv.h.patch @@ -0,0 +1,608 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma_drv.h +@@ -0,0 +1,602 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/** ++* ++* @file dma_drv.h ++* ++* @brief DMA device driver defines and prototypes. ++* ++****************************************************************************/ ++/** ++* ++* @defgroup DMAGroup Direct Memory Access ++* @ingroup CSLGroup ++* @brief This group defines the APIs for DMA driver ++ ++Click here to navigate back to the Chip Support Library Overview page: \ref CSLOverview. \n ++*****************************************************************************/ ++#ifndef _DMA_DRV_H_ ++#define _DMA_DRV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @addtogroup DMAGroup ++ * @{ ++ */ ++ ++/** ++* ++* DMA driver status definition ++* ++*****************************************************************************/ ++#define DMADRV_STATUS_t DMADRV_STATUS ++typedef enum ++{ ++ DMADRV_STATUS_CLOSED, ++ DMADRV_STATUS_OPEN, ++ DMADRV_STATUS_OK, ++ DMADRV_STATUS_FAIL ++}DMADRV_STATUS_t; ++ ++/** ++* ++* DMA driver callback status definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_STATUS_t DMADRV_CALLBACK_STATUS ++typedef enum ++{ ++ DMADRV_CALLBACK_OK = 0, ++ DMADRV_CALLBACK_FAIL ++} DMADRV_CALLBACK_STATUS_t; ++ ++/** ++* ++* DMA driver channel descriptor definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 src; ++ UInt32 dest; ++ UInt32 next; ++ UInt32 control; ++ UInt32 size; ++ UInt32 owner; ++} Dma_Chan_Desc; ++ ++/** ++* ++* DMA driver data buffer feature definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 srcAddr; ++ UInt32 destAddr; ++ UInt32 length; ++ UInt32 bRepeat; ++ UInt32 interrupt; ++} Dma_Buffer; ++ ++/** ++* ++* DMA driver data buffer definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ Dma_Buffer buffers[1]; ++} Dma_Buffer_List; ++ ++/** ++* ++* DMA driver data buffer list definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 numBuffer; ++ Dma_Buffer_List *pBufList; ++} Dma_Data; ++ ++ ++/** ++* ++* DMA data transfer width definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_DATA_SIZE_8BIT = 0x00, ++ DMA_DATA_SIZE_16BIT = 0x01, ++ DMA_DATA_SIZE_32BIT = 0x02 ++} DMA_DWIDTH; ++ ++/** ++* ++* DMA data transfer type definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_FCTRL_MEM_TO_MEM = 0, ++ DMA_FCTRL_MEM_TO_PERI = 1, ++ DMA_FCTRL_PERI_TO_MEM = 2, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI = 3, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_DESTPERI = 4, ++ DMA_FCTRL_MEM_TO_PERI_CTRL_PERI = 5, ++ DMA_FCTRL_PERI_TO_MEM_CTRL_PERI = 6, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_SRCPERI = 7 ++} DMA_CHAN_TYPE; ++ ++/** ++* ++* DMA burst length definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_BURST_LEN_1 = 0x00, ///< ++ DMA_BURST_LEN_2 = 0x01, ///< ++ DMA_BURST_LEN_3 = 0x02, ///< ++ DMA_BURST_LEN_4 = 0x03, ///< ++ DMA_BURST_LEN_5 = 0x04, ///< ++ DMA_BURST_LEN_6 = 0x05, ///< ++ DMA_BURST_LEN_7 = 0x06, ///< ++ DMA_BURST_LEN_8 = 0x07, ///< ++ DMA_BURST_LEN_9 = 0x08, ///< ++ DMA_BURST_LEN_10 = 0x09, ///< ++ DMA_BURST_LEN_11 = 0x0A, ///< ++ DMA_BURST_LEN_12 = 0x0B, ///< ++ DMA_BURST_LEN_13 = 0x0C, ///< ++ DMA_BURST_LEN_14 = 0x0D, ///< ++ DMA_BURST_LEN_15 = 0x0E, ///< ++ DMA_BURST_LEN_16 = 0x0F ///< ++} DMADRV_BLENGTH; ++ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_2 = 0x01, ++ DMA_BURST_SIZE_4 = 0x02, ++ DMA_BURST_SIZE_8 = 0x03, ++ DMA_BURST_SIZE_16 = 0x04, ++ DMA_BURST_SIZE_32 = 0x05, ++ DMA_BURST_SIZE_64 = 0x06, ++ DMA_BURST_SIZE_128 = 0x07 ++} DMA_BSIZE; ++ ++#else ++/** ++* ++* DMA burst size definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_4 = 0x01, ++ DMA_BURST_SIZE_8 = 0x02, ++ DMA_BURST_SIZE_16 = 0x03, ++ DMA_BURST_SIZE_32 = 0x04, ++ DMA_BURST_SIZE_64 = 0x05, ++ DMA_BURST_SIZE_128 = 0x06, ++ DMA_BURST_SIZE_256 = 0x07 ++} DMA_BSIZE; ++#endif ++ ++/** ++* ++* DMA alignment definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_ALIGNMENT_8 = 8, ++ DMA_ALIGNMENT_16 = 16, ++ DMA_ALIGNMENT_32 = 32 ++} DMA_ALIGN; ++ ++/** ++* ++* DMA data transfer incremnet definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_INC_MODE_NONE = 0, ++ DMA_INC_MODE_SRC, ++ DMA_INC_MODE_DST, ++ DMA_INC_MODE_BOTH, ++} DMA_INC_MODE; ++ ++/** ++* ++* DMA driver client type definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_CLIENT_EP_INVALID = 0xff, ++ DMA_CLIENT_EP_UARTB_A = 8, ++ DMA_CLIENT_EP_UARTB_B = 9, ++ DMA_CLIENT_EP_UARTB2_A = 10, ++ DMA_CLIENT_EP_UARTB2_B = 11, ++ DMA_CLIENT_EP_UARTB3_A = 12, ++ DMA_CLIENT_EP_UARTB3_B = 13, ++ DMA_CLIENT_EP_SSP_0A_RX0 = 16, ++ DMA_CLIENT_EP_SSP_0B_TX0 = 17, ++ DMA_CLIENT_EP_SSP_0C_RX1 = 18, ++ DMA_CLIENT_EP_SSP_0D_TX1 = 19, ++ DMA_CLIENT_EP_SSP_1A_RX0 = 20, ++ DMA_CLIENT_EP_SSP_1B_TX0 = 21, ++ DMA_CLIENT_EP_SSP_1C_RX1 = 22, ++ DMA_CLIENT_EP_SSP_1D_TX1 = 23, ++ DMA_CLIENT_EP_HSIA = 32, ++ DMA_CLIENT_EP_HSIB = 33, ++ DMA_CLIENT_EP_HSIC = 34, ++ DMA_CLIENT_EP_HSID = 35, ++ DMA_CLIENT_EP_EANC = 40, ++ DMA_CLIENT_EP_STEREO = 41, ++ DMA_CLIENT_EP_NVIN = 42, ++ DMA_CLIENT_EP_VIN = 43, ++ DMA_CLIENT_EP_VIBRA = 44, ++ DMA_CLIENT_EP_IHF_0 = 45, ++ DMA_CLIENT_EP_VOUT = 46, ++ DMA_CLIENT_EP_SLIMA = 47, ++ DMA_CLIENT_EP_SLIMB = 48, ++ DMA_CLIENT_EP_SLIMC = 49, ++ DMA_CLIENT_EP_SLIMD = 50, ++ DMA_CLIENT_EP_SIM_A = 51, ++ DMA_CLIENT_EP_SIM_B = 52, ++ DMA_CLIENT_EP_SIM2_A = 53, ++ DMA_CLIENT_EP_SIM2_B = 54, ++ DMA_CLIENT_EP_IHF_1 = 55, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_3A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_3B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_3C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_3D_TX1 = 59, ++#else ++ DMA_CLIENT_EP_SSP_2A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_2B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_2C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_2D_TX1 = 59, ++#endif ++ DMA_CLIENT_EP_SPUM_SecureA = 65, ++ DMA_CLIENT_EP_SPUM_SecureB = 66, ++ DMA_CLIENT_EP_SPUM_OpenA = 67, ++ DMA_CLIENT_EP_SPUM_OpenB = 68, ++ DMA_CLIENT_MEMORY = 69, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_4A_RX0 = 76, ++ DMA_CLIENT_EP_SSP_4B_TX0 = 77, ++ DMA_CLIENT_EP_SSP_4C_RX1 = 78, ++ DMA_CLIENT_EP_SSP_4D_TX1 = 79, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#else ++typedef enum ++{ ++ DMA_CLIENT_BULK_CRYPT_OUT = 0, ++ DMA_CLIENT_CAM = 1, ++ DMA_CLIENT_I2S_TX = 2, ++ DMA_CLIENT_I2S_RX = 3, ++ DMA_CLIENT_SIM_RX = 4, ++ DMA_CLIENT_SIM_TX = 4, ++ DMA_CLIENT_CRC = 5, ++ DMA_CLIENT_SPI_RX = 6, ++ DMA_CLIENT_SPI_TX = 7, ++ DMA_CLIENT_UARTA_RX = 8, ++ DMA_CLIENT_UARTA_TX = 9, ++ DMA_CLIENT_UARTB_RX = 10, ++ DMA_CLIENT_UARTB_TX = 11, ++ DMA_CLIENT_DES_IN = 12, ++ DMA_CLIENT_DES_OUT = 13, ++ DMA_CLIENT_USB_RX = 14, ++ DMA_CLIENT_USB_TX = 15, ++ DMA_CLIENT_UARTC_RX = 16, ++ DMA_CLIENT_UARTC_TX = 17, ++ DMA_CLIENT_BULK_CRYPT_IN = 18, ++ DMA_CLIENT_LCD = 19, ++ DMA_CLIENT_MSPRO = 20, ++ DMA_CLIENT_DSI_CM = 21, ++ DMA_CLIENT_DSI_VM = 22, ++ DMA_CLIENT_TVENC1 = 23, ++ DMA_CLIENT_TVENC2 = 24, ++#if defined(_ATHENA_) ++ DMA_CLIENT_AUDIO_IN_FIFO = 25, ++ DMA_CLIENT_AUDIO_OUT_FIFO = 26, ++ DMA_CLIENT_POLYRING_OUT_FIFO = 27, ++ DMA_CLIENT_AUDIO_WB_MIXERTAP = 28, ++ DMA_CLIENT_MEMORY = 29, ++#else ++ DMA_CLIENT_MEMORY = 25, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#endif ++ ++/** ++* ++* DMA driver channel definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_CHANNEL_INVALID = 0xFF, ++ DMA_CHANNEL_0 = 0, ++ DMA_CHANNEL_1 = 1, ++ DMA_CHANNEL_2 = 2, ++ DMA_CHANNEL_3 = 3, ++#if !defined(_SAMOA_) ++ DMA_CHANNEL_4 = 4, ++ DMA_CHANNEL_5 = 5, ++ DMA_CHANNEL_6 = 6, ++ DMA_CHANNEL_7 = 7, ++#if defined(_ATHENA_) ++ DMA_CHANNEL_8 = 8, //used for DMA_CLIENT_AUDIO_OUT_FIFO ++ DMA_CHANNEL_9 = 9, //used for DMA_CLIENT_POLYRING_OUT_FIFO ++ DMA_CHANNEL_10 = 10, //used for DMA_CLIENT_AUDIO_WB_MIXERTAP ++ DMA_CHANNEL_11 = 11, //used for DMA_CLIENT_AUDIO_IN_FIFO ++#endif ++#endif ++ TOTAL_DMA_CHANNELS ++} DMA_CHANNEL; ++ ++/** ++* ++* DMA driver callback function definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_t DmaDrv_Callback ++typedef void (*DMADRV_CALLBACK_t)(DMADRV_CALLBACK_STATUS_t Err); ++ ++/** ++* ++* DMA driver channel info structure definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ DMA_CLIENT srcID; ++ DMA_CLIENT dstID; ++ DMA_CHAN_TYPE type; ++ DMA_ALIGN alignment; ++ DMA_BSIZE srcBstSize; ++ DMA_BSIZE dstBstSize; ++ DMA_DWIDTH srcDataWidth; ++ DMA_DWIDTH dstDataWidth; ++ UInt32 priority; ++ UInt32 chanNumber; ++ UInt32 dmaCfgReg; ++ UInt32 incMode; ++ DmaDrv_Callback xferCompleteCb; ++ UInt32 prot; ++ UInt32 dstMaster; ++ UInt32 srcMaster; ++ UInt32 dstIncrement; ++ UInt32 srcIncrement; ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++ DMADRV_BLENGTH srcBstLength; ++ DMADRV_BLENGTH dstBstLength; ++#endif ++ Boolean freeChan; ++ Boolean bCircular; ++} Dma_Chan_Info, *pChanInfo; ++ ++/** ++* ++* DMA driver LLI structure definition ++* ++*****************************************************************************/ ++typedef void *DMADRV_LLI_T; ++ ++/** ++* ++* This function initialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Init(void); ++ ++/** ++* ++* This function deinitialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_DeInit(void); ++ ++/** ++* ++* This function allocates dma channel ++* ++* @param srcID (in) source identification ++* @param dstID (in) destination identification ++* @param chanID (in) buffer to store channel number ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Obtain_Channel( ++ DMA_CLIENT srcID, ++ DMA_CLIENT dstID, ++ DMA_CHANNEL *chanID ++); ++ ++/** ++* ++* This function release dma channel ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Release_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function configure dma channel ++* ++* @param chanID (in) channel number ++* @param pChanInfo (in) pointer to dma channe info structure ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Config_Channel( ++ DMA_CHANNEL chanID, ++ Dma_Chan_Info *pChanInfo ++); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data(DMA_CHANNEL chanID, Dma_Data *pData); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* @param pLLI (in) buffer to store returned LLI table ++* identification info ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data_Ex( ++ DMA_CHANNEL chanID, ++ Dma_Data *pData, ++ DMADRV_LLI_T *pLLI ++); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* @param pLLI (in) one of the LLI tables needs to be used for DMA ++* transfer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer_Ex( ++ DMA_CHANNEL chanID, ++ DMADRV_LLI_T pLLI ++); ++ ++/** ++* ++* This function stop dma channel trnasfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Stop_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function stop dma channel trnasfer and lose all data in FIFO ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Force_Shutdown_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function register hisr for client usage ++* ++* @param client (in) client identification ++* @param hisr (in) registered hisr ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_Register_HISR(DMA_CLIENT client, void *hisr); ++ ++/** ++* ++* This function unregister hisr from client usage ++* ++* @param client (in) client identification ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_UnRegister_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get hisr for client usage ++* ++* @param client (in) client identification ++* ++* @return hisr (out) return registered client's hisr ++* ++*****************************************************************************/ ++void *DMADRV_Get_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get DMA driver version number ++* ++* @return driver version number ++* ++*****************************************************************************/ ++UInt32 DMADRV_Get_Version(void); ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DMA_DRV_H_ */ +diff --git a/drivers/bcmdrivers/dma/pl330-pdata.h b/drivers/bcmdrivers/dma/pl330-pdata.h +new file mode 100644 +index 0000000..21c74c8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch new file mode 100644 index 00000000..ed8cb597 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_dma_pl330-pdata.h.patch @@ -0,0 +1,42 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/dma/pl330-pdata.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __DMA_PL330_PDATA_H ++#define __DMA_PL330_PDATA_H ++ ++/* ++ * The platforms just need to provide this info to the KONA DMA API ++ */ ++struct iproc_pl330_data { ++ /* Non Secure DMAC virtual base address */ ++ unsigned int dmac_ns_base; ++ /* Secure DMAC virtual base address */ ++ unsigned int dmac_s_base; ++ /* # of PL330 dmac channels 'configurable' */ ++ unsigned int num_pl330_chans; ++ /* DMAC irq number, connected to GIC */ ++ int irq_base; ++ /* # of PL330 Interrupts/events 'configurable' */ ++ unsigned int irq_line_count; ++ //int dmac_abort_irq; ++}; ++ ++#endif /* __DMA_PL330_PDATA_H */ +diff --git a/drivers/bcmdrivers/gmac/et/.gitignore b/drivers/bcmdrivers/gmac/et/.gitignore +new file mode 100644 +index 0000000..752a208 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch new file mode 100644 index 00000000..a3c38ad0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_.gitignore.patch @@ -0,0 +1,12 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/.gitignore +@@ -0,0 +1,6 @@ ++/.built-in.o.cmd ++/.et.o.cmd ++/built-in.o ++/et.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gmac/et/Kconfig b/drivers/bcmdrivers/gmac/et/Kconfig +new file mode 100644 +index 0000000..53f6462 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch new file mode 100644 index 00000000..1538385c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Kconfig.patch @@ -0,0 +1,20 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/Kconfig +@@ -0,0 +1,14 @@ ++config IPROC_GMAC ++ tristate "GMAC support " ++ select NETDEVICES ++ select PCI ++ select HND ++ select ET ++ select ET_47XX ++ select ET_ALL_PASSIVE_ON ++ depends on ARCH_IPROC ++ default n ++ help ++ Add GMAC support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/gmac/et/Makefile b/drivers/bcmdrivers/gmac/et/Makefile +new file mode 100755 +index 0000000..4f603a0 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch new file mode 100644 index 00000000..ac7108b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_et_Makefile.patch @@ -0,0 +1,103 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/Makefile +@@ -0,0 +1,97 @@ ++# ++# Makefile for the Broadcom et driver ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.5 2010-12-07 04:47:36 $ ++# ++ ++ ++ETSRCDIR := ../src/et ++ ++et-objs := $(ETSRCDIR)/sys/et_linux.o $(ETSRCDIR)/sys/etc.o ++ ++## from linux dir ########## ++export SRCBASE_et := $(src)/$(ETSRCDIR)/sys/../../ ++KBUILD_CFLAGS += -I$(SRCBASE_et)/include ++KBUILD_AFLAGS += -I$(SRCBASE_et)/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++KBUILD_CFLAGS += -DCFG_NORTHSTAR -DCFG_SIM ++ ++######## ######################### ++ ++#EXTRA_CFLAGS += -DGMAC3 ++ ++EXTRA_CFLAGS += -DGMAC_RATE_LIMITING ++ ++ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) ++EXTRA_CFLAGS += -DBCMDMASGLISTOSL ++endif ++ ++ifeq ($(CONFIG_ET_47XX),y) ++et-objs += $(ETSRCDIR)/sys/etcgmac.o ++EXTRA_CFLAGS += -DCFG_GMAC -DBCMDMA64 -DBCMDMA32 -DBCMDBG_ERR ++ifeq ($(CONFIG_ROOT_NFS),y) ++else ++ifeq ($(CONFIG_MACH_NS),y) ++EXTRA_CFLAGS += -DETROBO ++endif ++endif ++ifeq ($(CONFIG_MACH_NSP),y) ++EXTRA_CFLAGS += -DETROBO ++endif ++endif ++ ++obj-$(CONFIG_ET) := et.o ++ ++EXTRA_CFLAGS += -DDMA -Wno-error ++ifeq ($(CONFIG_ET_ALL_PASSIVE_ON),y) ++#EXTRA_CFLAGS += -DET_ALL_PASSIVE_ON -DET_ALL_PASSIVE ++# Forcing the use of CONFIG_ET_ALL_PASSIVE_RUNTIME ++EXTRA_CFLAGS += -DET_ALL_PASSIVE ++else ++ifeq ($(CONFIG_ET_ALL_PASSIVE_RUNTIME),y) ++EXTRA_CFLAGS += -DET_ALL_PASSIVE ++endif ++endif ++ ++ifeq ($(CONFIG_ET_NAPI_POLL),y) ++EXTRA_CFLAGS += -DNAPI_POLL ++else ++ifeq ($(CONFIG_ET_NAPI2_POLL),y) ++EXTRA_CFLAGS += -DNAPI2_POLL ++endif ++endif ++ ++# Disable PKTC for now, it is required the CTF enabled ++#EXTRA_CFLAGS += -DPKTC ++ ++# Search for sources under src/et/sys or objects under src/et/linux ++EXTRA_CFLAGS += -I$(src)/$(ETSRCDIR)/sys ++ ++ifneq ($(KERNELRELEASE),) ++# kbuild part of makefile ++else ++# Normal makefile ++KERNELDIR := ../../kernel/linux ++all: ++ $(MAKE) -C $(KERNELDIR) M=`pwd` ++ ++clean: ++ $(MAKE) -C $(KERNELDIR) M=`pwd` clean ++endif ++ ++clean-files += $(ETSRCDIR)/sys/*.o $(ETSRCDIR)/sys/.*.o.cmd +diff --git a/drivers/bcmdrivers/gmac/hnd/.gitignore b/drivers/bcmdrivers/gmac/hnd/.gitignore +new file mode 100644 +index 0000000..e015903 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch new file mode 100644 index 00000000..ffc9b767 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_.gitignore.patch @@ -0,0 +1,12 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/.gitignore +@@ -0,0 +1,6 @@ ++/.built-in.o.cmd ++/.hnd.o.cmd ++/built-in.o ++/hnd.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gmac/hnd/Kconfig b/drivers/bcmdrivers/gmac/hnd/Kconfig +new file mode 100755 +index 0000000..e57b937 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch new file mode 100644 index 00000000..94c36635 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Kconfig.patch @@ -0,0 +1,203 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/Kconfig +@@ -0,0 +1,197 @@ ++# ++# Broadcom Home Networking Division (HND) driver configuration ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Kconfig,v 1.6 2010-07-05 07:01:45 $ ++# ++ ++menu "Broadcom HND network devices" ++# Kenlo depends on PCI ++config HND ++ bool "Broadcom HND network device support" ++config ET ++ tristate "10/100 Ethernet support" ++ depends on HND ++config ET_47XX ++ bool "BCM47xx support" ++ depends on ET ++choice ++ prompt "ET ALL PASSIVE mode" ++ depends on ET ++ optional ++config ET_ALL_PASSIVE_ON ++ bool "ET ALL PASSIVE on" ++config ET_ALL_PASSIVE_RUNTIME ++ bool "ET ALL PASSIVE with runtime setting" ++endchoice ++config ET_NAPI2_POLL ++ bool "BCM GMAC NAPI2_POLL" ++ default n ++ depends on !ET_ALL_PASSIVE_ON && !ET_ALL_PASSIVE_RUNTIME ++config BCM_CTF ++ tristate "BCMCTF support" ++ depends on HND ++config BCM_CTF2 ++ tristate "BCMCTF2 support (NETFILTER and NF_DEFRAG_IPV4 required)" ++ depends on HND ++ default n ++ help ++ Add BCM_CTF2 support for performance enhancements with WLAN integration in LDK ++config BCM_IPROC_GMAC_ACP ++ tristate "BCM GMAC_ACP support" ++ depends on HND ++ default n ++ help ++ Add GMAC_ACP support to improve performance without ++ cache flushing/invalidate. The uboot's bootargs must ++ include "mem=240M" to limit whole Kernel memory inside ++ ACP region which is 256MB from 0x80000000; since kernel ++ starts from 0x81000000, total mem is 240MB only ++ If unsure, say N. ++config BCM_IPROC_GMAC_PREFETCH ++ tristate "BCM GMAC prefetching support" ++ depends on HND ++ default n ++ help ++ If unsure, say N. ++config BCM_IPROC_GMAC_TXONCPU1 ++ tristate "BCM GMAC TX-ON-CPU1 support" ++ depends on HND && SMP && (ET_ALL_PASSIVE_ON || ET_ALL_PASSIVE_RUNTIME) ++ default n ++ help ++ Run "Passive Mode" Tx workthread on CPU1 for ++ multi-cores utilizing; ++ If unsure, say N. ++config BCM_IPROC_GMAC_SKB_RECYCLING ++ tristate "BCM GMAC SKB-RECYCLING support" ++ depends on HND ++ default n ++ help ++ Recycle Tx/Rx skb_buff for high-speed IP forwarding tasks; ++ it is still an experimental feature now. ++ If unsure, say N. ++config BCM_IPROC_GMAC_LOCK_OPT ++ tristate "BCM GMAC LOCK OPTIMIZATION support" ++ depends on HND ++ default n ++ help ++ Minimize locks during Tx/Rx tasks; ++ it is tested under "Passive Mode" (workthread) only. ++ If unsure, say N. ++config BCM_IPROC_GMAC_RWREG_OPT ++ tristate "BCM GMAC R/W_REG OPTIMIZATION support" ++ depends on HND ++ default n ++ help ++ Remove unnecessary "DSB" intructions of R/W_REG Macro. ++ If unsure, say N. ++config BCM_IPROC_GMAC_SG ++ bool "BCM GMAC Scatter Gather support" ++ default n ++ depends on HND ++config WL_EMULATOR ++ bool "WL emulation using Gigabit ethernet" ++ depends on HND ++config BCM57XX ++ tristate "BCM57xx support is ON" ++ depends on WL_EMULATOR ++config WL ++ tristate "Wireless feature variant is set to AP" ++ depends on WL_EMULATOR ++ select WL_USE_AP ++config BCM57XX ++ tristate "BCM57xx Gigabit Ethernet support" ++ depends on HND && !WL_EMULATOR ++config WL ++ tristate "BCM43xx 802.11 Wireless support" ++ depends on HND && !WL_EMULATOR ++config WAPI ++ bool "Wireless Authentication Privacy Infrastructure (WAPI) support" ++ depends on HND && !WL_EMULATOR && WL ++ select MTD_BCMCONF_PARTS ++choice ++ prompt "Wireless feature variant" ++ depends on HND && !WL_EMULATOR && WL ++config WL_USE_AP ++ bool "Config file for basic AP variant" ++config WL_USE_AP_SDSTD ++ bool "Config file for basic AP sdstd variant" ++config WL_USE_STA ++ bool "Config file for basic STA variant" ++config WL_USE_APSTA ++ bool "Config file for basic APSTA variant" ++config WL_USE_AP_ONCHIP_G ++ bool "Config file for AP 1chipG variant" ++config WL_USE_STA_ONCHIP_G ++ bool "Config file for STA 1chipG variant" ++config WL_USE_APSTA_ONCHIP_G ++ bool "Config file for APSTA 1chipG variant" ++endchoice ++config WL_USBAP ++ bool "USB/HSIC Wireless Access Point support" ++config WL_AP ++ string "Config file for basic AP variant" ++ default "wlconfig_lx_router_ap" ++config WL_AP_SDSTD ++ string "Config file for basic AP sdstd variant" ++ default "wlconfig_lx_router_ap_sdstd" ++config WL_STA ++ string "Config file for basic STA variant" ++ default "wlconfig_lx_router_sta" ++config WL_APSTA ++ string "Config file for basic APSTA variant" ++ default "wlconfig_lx_router_apsta" ++config WL_AP_ONCHIP_G ++ string "Config file for AP 1chipG variant" ++ default "wlconfig_lx_router_ap_1chipG" ++config WL_STA_ONCHIP_G ++ string "Config file for STA 1chipG variant" ++ default "wlconfig_lx_router_sta_1chipG" ++config WL_HIGH ++ string "Config file for high/bmac split variant" ++ default "wlconfig_lx_router_high" ++ ++choice ++ prompt "WL ALL PASSIVE mode" ++ depends on WL ++ ++config WL_ALL_PASSIVE_ON ++ bool "WL ALL PASSIVE on" ++config WL_ALL_PASSIVE_RUNTIME ++ bool "WL ALL PASSIVE with runtime setting" ++endchoice ++config DPSTA ++ tristate "Broadcom dualband wireless proxy repeater support" ++ depends on WL ++config EMF ++ tristate "Efficient Multicast Forwarding & IGMP Snooping Layers" ++ depends on NETFILTER ++config PLC ++ bool "Broadcom PLC network failover support" ++ depends on ET && WL ++config IPROC_SDK_MGT_PORT_HANDOFF ++ bool "GMAC SDK Management port handoff" ++ default y ++ depends on HND ++config IPROC_2STAGE_RX ++ bool "GMAC 2 stage packet RX" ++ default n ++ depends on HND ++config SERDES_ASYMMETRIC_MODE ++ bool "GMAC SDK Serdes Asymmetric Mode" ++ default n ++ depends on HND && (MACH_KT2 || MACH_HX4) ++endmenu +diff --git a/drivers/bcmdrivers/gmac/hnd/Makefile b/drivers/bcmdrivers/gmac/hnd/Makefile +new file mode 100755 +index 0000000..83c02e2 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch new file mode 100644 index 00000000..fca164c1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_Makefile.patch @@ -0,0 +1,181 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/Makefile +@@ -0,0 +1,175 @@ ++# ++# Makefile for Broadcom Home Networking Division (HND) shared driver code ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.5 2008-05-02 22:49:54 $ ++# ++ ++SHARED := ../src/shared ++ ++include $(src)/$(SHARED)/wl_config ++ ++## from linux dir ########## ++export SRCBASE_hnd := $(src)/$(SHARED)/../ ++KBUILD_CFLAGS += -I$(SRCBASE_hnd)/include ++KBUILD_AFLAGS += -I$(SRCBASE_hnd)/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++KBUILD_CFLAGS += -DCFG_NORTHSTAR -DCFG_SIM ++ ++################################# ++ ++EXTRA_CFLAGS += $(WLFLAGS) -DBCM5354 -DLINUX_HYBRID_POSTPROCESSING_REMOVAL -DBCMDBG_ERR ++ ++ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) ++EXTRA_CFLAGS += -DBCMDMASGLISTOSL ++endif ++ ++### for bcm5301x_otp.h ++EXTRA_CFLAGS += -I$(src)/../../otp/ ++ ++ ++#HND_OBJS += $(src)/$(SHARED)/hndfwd.o ++#hnd-objs += $(SHARED)/hndfwd.o ++#EXTRA_CFLAGS += -DGMAC3 ++ ++ifneq ($(CONFIG_BCM947XX),y) ++HND_OBJS += $(src)/$(SHARED)/nvramstubs.o ++hnd-objs += $(SHARED)/nvramstubs.o ++endif ++ ++ifeq ($(CONFIG_MACH_HX4),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_DNI_3448P),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_ACCTON_AS4610_54),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_KT2),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ ++ifeq ($(CONFIG_MACH_HR2),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5221.o ++hnd-objs += $(SHARED)/bcmiproc_phy5221.o ++endif ++ ++ifeq ($(CONFIG_MACH_NSP),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_robo_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_robo_serdes.o ++endif ++ ++ifeq ($(CONFIG_ET_47XX),y) ++HND_OBJS += $(src)/$(SHARED)/bcmrobo.o ++hnd-objs += $(SHARED)/bcmrobo.o ++endif ++ ++#ifdef HNDDMA ++ifeq ($(HNDDMA),1) ++HND_OBJS += $(src)/$(SHARED)/hnddma.o ++hnd-objs += $(SHARED)/hnddma.o ++endif ++#endif ++ ++#ifdef BCMUTILS ++ifeq ($(BCMUTILS),1) ++HND_OBJS += $(src)/$(SHARED)/bcmutils.o ++hnd-objs += $(SHARED)/bcmutils.o ++endif ++#endif ++ ++#ifdef SIUTILS ++ifeq ($(SIUTILS),1) ++HND_OBJS += $(src)/$(SHARED)/siutils.o ++hnd-objs += $(SHARED)/siutils.o ++HND_OBJS += $(src)/$(SHARED)/aiutils.o ++hnd-objs += $(SHARED)/aiutils.o ++ifeq ($(CONFIG_MACH_HX4),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_DNI_3448P),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_ACCTON_AS4610_54),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_HR2),y) ++HND_OBJS += $(src)/$(SHARED)/hr2_erom.o ++hnd-objs += $(SHARED)/hr2_erom.o ++endif ++ifeq ($(CONFIG_MACH_NSP),y) ++HND_OBJS += $(src)/$(SHARED)/nsp_erom.o ++hnd-objs += $(SHARED)/nsp_erom.o ++endif ++ifeq ($(CONFIG_MACH_KT2),y) ++HND_OBJS += $(src)/$(SHARED)/kt2_erom.o ++hnd-objs += $(SHARED)/kt2_erom.o ++endif ++endif ++#endif /* SIUTILS */ ++ ++#ifdef BCMSROM ++ifeq ($(BCMSROM),1) ++HND_OBJS += $(src)/$(SHARED)/bcmsrom.o ++hnd-objs += $(SHARED)/bcmsrom.o ++HND_OBJS += $(src)/$(SHARED)/bcmotp.o ++hnd-objs += $(SHARED)/bcmotp.o ++endif ++#endif ++ ++#ifdef BCMOTP ++ifeq ($(BCMOTP),1) ++ifneq ($(BCMSROM),1) ++HND_OBJS += $(src)/$(SHARED)/bcmotp.o ++hnd-objs += $(SHARED)/bcmotp.o ++endif ++EXTRA_CFLAGS += -DBCMNVRAMR ++endif ++#endif ++ ++#ifdef OSLLX ++# linux osl ++ifeq ($(OSLLX),1) ++HND_OBJS += $(src)/$(SHARED)/linux_osl.o ++hnd-objs += $(SHARED)/linux_osl.o ++endif ++#endif ++ ++# BCMDMA32 ++ifeq ($(BCMDMA32),1) ++EXTRA_CFLAGS += -DBCMDMA32 ++endif ++ ++obj-$(CONFIG_HND) := hnd.o ++ ++hnd-objs += shared_ksyms.o +diff --git a/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c +new file mode 100755 +index 0000000..a615f54 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch new file mode 100644 index 00000000..63a697c3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch @@ -0,0 +1,68 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c +@@ -0,0 +1,62 @@ ++#include ++#include ++#include ++#include ++#include ++EXPORT_SYMBOL(bcm_atoi); ++EXPORT_SYMBOL(bcm_binit); ++EXPORT_SYMBOL(bcm_bprintf); ++EXPORT_SYMBOL(bcm_ether_atoe); ++EXPORT_SYMBOL(bcm_ether_ntoa); ++EXPORT_SYMBOL(bcm_robo_attach); ++EXPORT_SYMBOL(bcm_robo_config_vlan); ++EXPORT_SYMBOL(bcm_robo_detach); ++EXPORT_SYMBOL(bcm_robo_enable_device); ++EXPORT_SYMBOL(bcm_robo_enable_switch); ++EXPORT_SYMBOL(bcm_strtoul); ++EXPORT_SYMBOL(getgpiopin); ++EXPORT_SYMBOL(getintvar); ++EXPORT_SYMBOL(getvar); ++EXPORT_SYMBOL(nvram_env_gmac_name); ++EXPORT_SYMBOL(nvram_get); ++#ifdef CTFPOOL ++EXPORT_SYMBOL(osl_ctfpool_add); ++EXPORT_SYMBOL(osl_ctfpool_cleanup); ++EXPORT_SYMBOL(osl_ctfpool_init); ++EXPORT_SYMBOL(osl_ctfpool_replenish); ++EXPORT_SYMBOL(osl_ctfpool_stats); ++#endif ++EXPORT_SYMBOL(osl_delay); ++EXPORT_SYMBOL(osl_detach); ++EXPORT_SYMBOL(osl_dma_map); ++EXPORT_SYMBOL(osl_malloc); ++EXPORT_SYMBOL(osl_malloced); ++EXPORT_SYMBOL(osl_mfree); ++EXPORT_SYMBOL(osl_pkt_frmnative); ++EXPORT_SYMBOL(osl_pkt_tonative); ++EXPORT_SYMBOL(osl_pktfree); ++EXPORT_SYMBOL(pktsetprio); ++EXPORT_SYMBOL(robo_bprintf_mib); ++EXPORT_SYMBOL(robo_dump_mib); ++EXPORT_SYMBOL(robo_dump_regs); ++EXPORT_SYMBOL(robo_is_port_cfg); ++EXPORT_SYMBOL(robo_power_save_mode_get); ++EXPORT_SYMBOL(robo_power_save_mode_set); ++EXPORT_SYMBOL(robo_power_save_mode_update); ++EXPORT_SYMBOL(robo_power_save_toggle); ++EXPORT_SYMBOL(robo_reset_mib); ++EXPORT_SYMBOL(robo_watchdog); ++EXPORT_SYMBOL(si_core_cflags); ++EXPORT_SYMBOL(si_core_disable); ++EXPORT_SYMBOL(si_core_reset); ++EXPORT_SYMBOL(si_core_sflags); ++EXPORT_SYMBOL(si_coreid); ++EXPORT_SYMBOL(si_coreidx); ++EXPORT_SYMBOL(si_corerev); ++EXPORT_SYMBOL(si_coreunit); ++EXPORT_SYMBOL(si_detach); ++EXPORT_SYMBOL(si_gpioout); ++EXPORT_SYMBOL(si_gpioouten); ++EXPORT_SYMBOL(si_iscoreup); ++EXPORT_SYMBOL(si_kattach); ++EXPORT_SYMBOL(si_setcoreidx); +diff --git a/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh +new file mode 100755 +index 0000000..8b537a3 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch new file mode 100644 index 00000000..96f3dab2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch @@ -0,0 +1,36 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh +@@ -0,0 +1,30 @@ ++#!/bin/sh ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: shared_ksyms.sh,v 1.2 2008-12-05 20:10:41 $ ++# ++ ++cat < ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include ++#endif ++EOF ++ ++for file in $* ; do ++ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [BDRT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' ++done +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/.gitignore b/drivers/bcmdrivers/gmac/src/et/sys/.gitignore +new file mode 100644 +index 0000000..25794d4 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch new file mode 100644 index 00000000..f4d1f64e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch @@ -0,0 +1,12 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/.gitignore +@@ -0,0 +1,6 @@ ++/.et_linux.o.cmd ++/.etc.o.cmd ++/.etcgmac.o.cmd ++/et_linux.o ++/etc.o ++/etcgmac.o +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h b/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h +new file mode 100755 +index 0000000..38ded3d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch new file mode 100644 index 00000000..9899ba6d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch @@ -0,0 +1,30 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM ET driver config options ++ * ++ * $Id: et_cfg.h,v 1.1.4.1 2010-08-05 19:17:00 $ ++ */ ++ ++#if defined(__NetBSD__) || defined(__FreeBSD__) ++#include ++#include ++#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h b/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h +new file mode 100755 +index 0000000..7d209a1 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch new file mode 100644 index 00000000..ea77478c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch @@ -0,0 +1,65 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Minimal debug/trace/assert driver definitions for ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Device Driver. ++ * ++ * $Id: et_dbg.h 286404 2011-09-27 19:29:08Z $ ++ */ ++ ++#ifndef _et_dbg_ ++#define _et_dbg_ ++ ++#ifdef BCMDBG ++struct ether_header; ++extern void etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit); ++extern void etc_prhex(char *msg, uchar *buf, uint nbytes, int unit); ++/* ++ * et_msg_level is a bitvector: ++ * 0 errors ++ * 1 function-level tracing ++ * 2 one-line frame tx/rx summary ++ * 3 complex frame tx/rx in hex ++ */ ++#define ET_ERROR(args) if (!(et_msg_level & 1)) ; else printf args ++#define ET_TRACE(args) if (!(et_msg_level & 2)) ; else printf args ++#define ET_PRHDR(msg, eh, len, unit) if (!(et_msg_level & 4)) ; else etc_prhdr(msg, eh, len, unit) ++#define ET_PRPKT(msg, buf, len, unit) if (!(et_msg_level & 8)) ; else etc_prhex(msg, buf, len, unit) ++#else /* BCMDBG */ ++#define ET_ERROR(args) ++#define ET_TRACE(args) ++#define ET_PRHDR(msg, eh, len, unit) ++#define ET_PRPKT(msg, buf, len, unit) ++#endif /* BCMDBG */ ++ ++extern uint32 et_msg_level; ++ ++#define ET_LOG(fmt, a1, a2) ++ ++/* include port-specific tunables */ ++#if defined(linux) ++#include ++#else ++#error ++#endif ++ ++#endif /* _et_dbg_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_export.h b/drivers/bcmdrivers/gmac/src/et/sys/et_export.h +new file mode 100755 +index 0000000..e06bf27 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch new file mode 100644 index 00000000..06210c14 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch @@ -0,0 +1,49 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_export.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Required functions exported by the port-specific (os-dependent) driver ++ * to common (os-independent) driver code. ++ * ++ * $Id: et_export.h 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#ifndef _et_export_h_ ++#define _et_export_h_ ++ ++/* misc callbacks */ ++extern void et_init(void *et, uint options); ++extern void et_reset(void *et); ++extern void et_link_up(void *et); ++extern void et_link_down(void *et); ++extern bool et_is_link_up(void *et); ++extern int et_up(void *et); ++extern int et_down(void *et, int reset); ++extern void et_dump(void *et, struct bcmstrbuf *b); ++extern void et_intrson(void *et); ++ ++/* for BCM5222 dual-phy shared mdio contortion */ ++extern void *et_phyfind(void *et, uint coreunit); ++extern uint16 et_phyrd(void *et, uint phyaddr, uint reg); ++extern void et_phywr(void *et, uint reg, uint phyaddr, uint16 val); ++#ifdef HNDCTF ++extern void et_dump_ctf(void *et, struct bcmstrbuf *b); ++#endif ++#endif /* _et_export_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c +new file mode 100755 +index 0000000..e510812 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch new file mode 100644 index 00000000..ab7eba0f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch @@ -0,0 +1,3902 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c +@@ -0,0 +1,3896 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux device driver for ++ * Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller ++ * ++ * $Id: et_linux.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#include ++#define __UNDEF_NO_VERSION__ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef SIOCETHTOOL ++#include ++#endif /* SIOCETHTOOL */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HNDCTF ++#include ++#endif /* HNDCTF */ ++#ifdef GMAC3 ++#include /* GMAC3 */ ++#endif /* GMAC3 */ ++ ++/* to be cleaned and fixed */ ++/* to be cleaned Makefile */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "plat/shm.h" ++ ++#if defined(CONFIG_IPROC_FA2) ++#include "../../../fa2/fa2_defs.h" ++#include "../../../fa2/fa2_if.h" ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#include ++ ++#define SKB_PREFETCH_LEN (128) ++ ++/* 30 rxhdr + 34 mac & ip */ ++#define SKB_DATA_PREFETCH_LEN (96) ++ ++#endif ++ ++#define MIN_PACKET_SIZE 70 /* for gmac2 (&GMAC3?) */ ++ /* if packet is less than 64 bytes, it will not tx */ ++ /* if packet is less than 66 bytes, CRC is not generated) */ ++ /* this length is after brm tag is stripped off */ ++#define NS_MAX_GMAC_CORES 4 ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) ++#define HAVE_NET_DEVICE_OPS 1 ++#define HAVE_NETDEV_PRIV 1 ++#endif ++ ++int gmac_pdev_loaded[NS_MAX_GMAC_CORES]; ++ ++/* Global SB handle */ ++si_t *bcm947xx_sih = NULL; ++spinlock_t bcm947xx_sih_lock; ++EXPORT_SYMBOL(bcm947xx_sih); ++EXPORT_SYMBOL(bcm947xx_sih_lock); ++ ++/* Convenience */ ++#define sih bcm947xx_sih ++#define sih_lock bcm947xx_sih_lock ++ ++#ifdef ET_ALL_PASSIVE_ON ++/* When ET_ALL_PASSIVE_ON, ET_ALL_PASSIVE must be true */ ++#define ET_ALL_PASSIVE_ENAB(et) 1 ++#else ++#ifdef ET_ALL_PASSIVE ++#define ET_ALL_PASSIVE_ENAB(et) (!(et)->all_dispatch_mode) ++#else /* ET_ALL_PASSIVE */ ++#define ET_ALL_PASSIVE_ENAB(et) 0 ++#endif /* ET_ALL_PASSIVE */ ++#endif /* ET_ALL_PASSIVE_ON */ ++ ++//#define BRCM_TAG true ++//#define PRINT_PKT true ++//#define PRINT_PKT_SUM true ++ ++#ifdef ET_ALL_PASSIVE ++#define ET_LIMIT_TXQ ++#endif ++ ++#ifdef PKTC ++#ifndef HNDCTF ++#error "Packet chaining feature can't work w/o CTF" ++#endif ++#define PKTC_ENAB(et) ((et)->etc->pktc) ++ ++#ifdef GMAC3 ++#define PKT_CHAINABLE(et, p, evh, prio, h_sa, h_da, h_prio) \ ++ (!eacmp((h_da), ((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_sa), ((struct ethervlan_header *)(evh))->ether_shost) && \ ++ ((h_prio) == (prio)) && !RXH_FLAGS((et)->etc, PKTDATA((et)->osh, (p))) && \ ++ ((((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \ ++ (((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6)))) ++#else /* !GMAC3 */ ++#define PKT_CHAINABLE(et, p, evh, prio, h_sa, h_da, h_prio) \ ++ (!ETHER_ISNULLDEST(((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_da), ((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_sa), ((struct ethervlan_header *)(evh))->ether_shost) && \ ++ (et)->brc_hot && CTF_HOTBRC_CMP((et)->brc_hot, (evh), (void *)(et)->dev) && \ ++ ((h_prio) == (prio)) && !RXH_FLAGS((et)->etc, PKTDATA((et)->osh, (p))) && \ ++ (((struct ethervlan_header *)(evh))->vlan_type == HTON16(ETHER_TYPE_8021Q)) && \ ++ ((((struct ethervlan_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \ ++ (((struct ethervlan_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6)))) ++#endif /* !GMAC3 */ ++ ++#define PKTCMC 2 ++struct pktc_data { ++ void *chead; /* chain head */ ++ void *ctail; /* chain tail */ ++ uint8 *h_da; /* pointer to da of chain head */ ++ uint8 *h_sa; /* pointer to sa of chain head */ ++ uint8 h_prio; /* prio of chain head */ ++}; ++typedef struct pktc_data pktc_data_t; ++#else /* PKTC */ ++#define PKTC_ENAB(et) 0 ++#define PKT_CHAINABLE(et, p, evh, h_sa, h_da, h_prio) 0 ++#endif /* PKTC */ ++ ++static char bcm5301x_gmac0_string[] = "bcmiproc-gmac0"; ++static char bcm5301x_gmac1_string[] = "bcmiproc-gmac1"; ++static char bcm5301x_gmac2_string[] = "bcmiproc-gmac2"; ++static char bcm5301x_gmac3_string[] = "bcmiproc-gmac3"; ++ ++#ifdef GMAC_RATE_LIMITING ++static int et_rx_rate_limit = 0; ++extern void etc_check_rate_limiting(etc_info_t *etc, void *pch); ++#endif /* GMAC_RATE_LIMITING */ ++extern int nvram_env_gmac_name(int gmac, char *name); ++ ++#if defined(CONFIG_IPROC_FA) ++extern int fc_receive(struct sk_buff *skb_p); ++extern int fc_transmit(struct sk_buff *skb_p); ++#else ++#define fc_receive(arg) {} ++#define fc_transmit(arg) {} ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++#if defined(CONFIG_IPROC_FA2) ++extern int fa2_receive(struct sk_buff *skb_p); ++extern int fa2_transmit(struct sk_buff *skb_p, struct fa2_pkt_info *pkt_info); ++extern int fa2_get_packet_info(struct sk_buff *skb, struct fa2_pkt_info *info); ++extern int fa2_modify_header(struct sk_buff *skb); ++ ++#else ++#define fa2_receive(arg) {} ++#define fa2_transmit(arg) {} ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++extern int gmac_has_mdio_access(void); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++/* In 2.6.20 kernels work functions get passed a pointer to the ++ * struct work, so things will continue to work as long as the work ++ * structure is the first component of the task structure. ++ */ ++typedef struct et_task { ++ struct work_struct work; ++ void *context; ++} et_task_t; ++ ++typedef struct et_info { ++ etc_info_t *etc; /* pointer to common os-independent data */ ++ struct net_device *dev; /* backpoint to device */ ++ struct pci_dev *pdev; /* backpoint to pci_dev */ ++ void *osh; /* pointer to os handle */ ++#ifdef GMAC3 ++ struct fwder *fwdh; /* pointer to my upstream forwarder handle */ ++#endif /* GMAC3 */ ++#ifdef HNDCTF ++ ctf_t *cih; /* ctf instance handle */ ++ ctf_brc_hot_t *brc_hot; /* hot bridge cache entry */ ++#endif ++ struct semaphore sem; /* use semaphore to allow sleep */ ++ spinlock_t lock; /* per-device perimeter lock */ ++ spinlock_t txq_lock; /* lock for txq protection */ ++ spinlock_t tx_lock; /* lock for tx protection */ ++ spinlock_t isr_lock; /* lock for irq reentrancy protection */ ++ struct sk_buff_head txq[NUMTXQ]; /* send queue */ ++ void *regsva; /* opaque chip registers virtual address */ ++ struct timer_list timer; /* one second watchdog timer */ ++ bool set; /* indicate the timer is set or not */ ++ struct net_device_stats stats; /* stat counter reporting structure */ ++ int events; /* bit channel between isr and dpc */ ++ struct et_info *next; /* pointer to next et_info_t in chain */ ++#ifdef NAPI2_POLL ++ struct napi_struct napi_poll; ++#endif /* NAPI2_POLL */ ++#ifndef NAPI_POLL ++ struct tasklet_struct tasklet; /* dpc tasklet */ ++#endif /* NAPI_POLL */ ++#ifdef ET_ALL_PASSIVE ++ et_task_t dpc_task; /* work queue for rx dpc */ ++ et_task_t txq_task; /* work queue for tx frames */ ++ bool all_dispatch_mode; /* dispatch mode: tasklets or passive */ ++#endif /* ET_ALL_PASSIVE */ ++ bool resched; /* dpc was rescheduled */ ++#ifdef CONFIG_IPROC_2STAGE_RX ++ bool rxinisr; ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++} et_info_t; ++ ++static int et_found = 0; ++static et_info_t *et_list = NULL; ++ ++/* defines */ ++#define DATAHIWAT 1000 /* data msg txq hiwat mark */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) ++#define init_MUTEX(x) sema_init(x,1) ++#endif ++ ++ ++#ifndef HAVE_NETDEV_PRIV ++#define HAVE_NETDEV_PRIV ++#define netdev_priv(dev) ((dev)->priv) ++#define ET_INFO(dev) (et_info_t *)((dev)->priv) ++#else ++#define ET_INFO(dev) netdev_priv(dev) ++#endif /* HAVE_NETDEV_PRIV */ ++ ++ ++#define ET_LOCK(et) \ ++do { \ ++ if (ET_ALL_PASSIVE_ENAB(et)) \ ++ down(&(et)->sem); \ ++ else \ ++ spin_lock_bh(&(et)->lock); \ ++} while (0) ++ ++#define ET_UNLOCK(et) \ ++do { \ ++ if (ET_ALL_PASSIVE_ENAB(et)) \ ++ up(&(et)->sem); \ ++ else \ ++ spin_unlock_bh(&(et)->lock); \ ++} while (0) ++ ++#define ET_TXQ_LOCK(et) spin_lock_bh(&(et)->txq_lock) ++#define ET_TXQ_UNLOCK(et) spin_unlock_bh(&(et)->txq_lock) ++ ++#define ET_TX_LOCK(et) spin_lock_bh(&(et)->tx_lock) ++#define ET_TX_UNLOCK(et) spin_unlock_bh(&(et)->tx_lock) ++ ++#define INT_LOCK(et, flags) spin_lock_irqsave(&(et)->isr_lock, flags) ++#define INT_UNLOCK(et, flags) spin_unlock_irqrestore(&(et)->isr_lock, flags) ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) ++#error Linux version must be newer than 2.4.5 ++#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) */ ++ ++/* linux 2.4 doesn't have in_atomic */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) ++#define in_atomic() 0 ++#endif ++ ++/* prototypes called by etc.c */ ++void et_init(et_info_t *et, uint options); ++void et_reset(et_info_t *et); ++void et_link_up(et_info_t *et); ++void et_link_down(et_info_t *et); ++bool et_is_link_down(et_info_t *et); ++void et_up(et_info_t *et); ++void et_down(et_info_t *et, int reset); ++void et_dump(et_info_t *et, struct bcmstrbuf *b); ++#ifdef HNDCTF ++void et_dump_ctf(et_info_t *et, struct bcmstrbuf *b); ++#endif ++ ++/* local prototypes */ ++static void et_free(et_info_t *et); ++static int et_open(struct net_device *dev); ++static int et_close(struct net_device *dev); ++static int et_start(struct sk_buff *skb, struct net_device *dev); ++static void et_sendnext(et_info_t *et); ++static struct net_device_stats *et_get_stats(struct net_device *dev); ++static int et_set_mac_address(struct net_device *dev, void *addr); ++static void et_set_multicast_list(struct net_device *dev); ++static void _et_watchdog(struct net_device *data); ++static void et_watchdog(ulong data); ++#ifdef ET_ALL_PASSIVE ++static void et_watchdog_task(et_task_t *task); ++#endif /* ET_ALL_PASSIVE */ ++static int et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++static irqreturn_t et_isr(int irq, void *dev_id); ++#else ++static irqreturn_t et_isr(int irq, void *dev_id, struct pt_regs *ptregs); ++#endif ++#ifdef NAPI2_POLL ++static int et_poll(struct napi_struct *napi, int budget); ++#elif defined(NAPI_POLL) ++static int et_poll(struct net_device *dev, int *budget); ++#else /* ! NAPI_POLL */ ++static void et_dpc(ulong data); ++#endif /* NAPI_POLL */ ++#ifdef ET_ALL_PASSIVE ++static void et_dpc_work(struct et_task *task); ++static void et_txq_work(struct et_task *task); ++static int et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context); ++#endif /* ET_ALL_PASSIVE */ ++static void et_sendup(et_info_t *et, struct sk_buff *skb); ++static void et_dumpet(et_info_t *et, struct bcmstrbuf *b); ++ ++static int et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd); ++static int et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd); ++static void et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++static const struct ethtool_ops et_ethtool_ops = ++{ ++ .get_settings = et_get_settings, ++ .set_settings = et_set_settings, ++ .get_drvinfo = et_get_driver_info, ++}; ++#endif ++ ++static int bcm5301x_gmac_probe(struct platform_device*); ++static int __exit bcm5301x_gmac_remove(struct platform_device*); ++static int __init bcm5301x_gmac_init_module(void); ++static void __exit bcm5301x_gmac_cleanup_module(void); ++#ifdef CONFIG_PM ++static int bcm5301x_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state); ++static int bcm5301x_gmac_drv_resume(struct platform_device *pdev); ++#endif ++static void bcm5301x_gmac_release (struct device *dev); ++#if 0 //dgb /* Functions related to PROC file system support */ ++static int get_debug_level(char *page, char **start, off_t off, int count, int *eof, void *data); ++static int set_debug_level(struct file *file, const char *buffer, unsigned long count, void *data); ++#define MIN_DEBUG_LEVEL 0 ++#define MAX_DEBUG_LEVEL 3 ++static int cur_dbg_lvl = MIN_DEBUG_LEVEL; ++ ++#endif ++static int eth_mac_proc_create(struct net_device *dev ); ++static void eth_mac_proc_remove(void); ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++static et_info_t *et_get_eth3_info(void); ++#endif ++static int et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota); ++ ++#define DISABLE_FA_BYPASS 0 ++#define ENABLE_FA_BYPASS 1 ++static unsigned int gBypass = DISABLE_FA_BYPASS; ++ ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops et_netdev_ops = { ++ .ndo_open = et_open, ++ .ndo_stop = et_close, ++ .ndo_start_xmit = et_start, ++ .ndo_get_stats = et_get_stats, ++ .ndo_set_mac_address = et_set_mac_address, ++ .ndo_set_rx_mode = et_set_multicast_list, ++ .ndo_do_ioctl = et_ioctl, ++}; ++#endif /*HAVE_NET_DEVICE_OPS*/ ++ ++static struct resource bcm5301x_gmac0_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC0_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC0_REG_BASE, ++ .end = IPROC_GMAC0_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac1_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC1_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC1_REG_BASE, ++ .end = IPROC_GMAC1_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac2_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC2_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC2_REG_BASE, ++ .end = IPROC_GMAC2_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac3_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC3_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC3_REG_BASE, ++ .end = IPROC_GMAC3_REG_BASE+0xbff, ++ }, ++}; ++ ++#if defined(BCMDBG) ++static uint32 msglevel = 0xdeadbeef; ++module_param(msglevel, uint, 0644); ++#endif /* defined(BCMDBG) */ ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++static bool brcm_tag=true; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++#ifdef ET_ALL_PASSIVE ++/* passive mode: 1: enable, 0: disable */ ++static int passivemode = 0; ++module_param(passivemode, int, 0); ++#endif /* ET_ALL_PASSIVE */ ++#ifdef ET_LIMIT_TXQ ++#define ET_TXQ_THRESH 0 ++static int et_txq_thresh = ET_TXQ_THRESH; ++module_param(et_txq_thresh, int, 0); ++#endif /* ET_LIMIT_TXQ */ ++ ++#ifdef HNDCTF ++//int32 ctf_init(void); ++void ctf_exit(void); ++ ++static void ++et_ctf_detach(ctf_t *ci, void *arg) ++{ ++ et_info_t *et = (et_info_t *)arg; ++ ++ et->cih = NULL; ++ ++#ifdef CTFPOOL ++ /* free the buffers in fast pool */ ++ osl_ctfpool_cleanup(et->osh); ++#endif /* CTFPOOL */ ++ ++ return; ++} ++#endif /* HNDCTF */ ++ ++static bool ++et_ctf_active(et_info_t *et) ++{ ++ bool retval=false; ++#if defined(CONFIG_IPROC_FA) ++ if (brcm_tag == true) { ++ if (et->etc->unit == 2) { ++ retval = true; ++ } ++ } ++#elif defined(CONFIG_MACH_NSP) ++ if (et->etc->unit == 2 || et->etc->unit == 3) { ++ retval = true; ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++ return retval; ++} ++ ++static bool ++et_ctf_pipeline_loopback(et_info_t *et) ++{ ++ if (et->etc->unit == 3) { ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++static int ++et_bcmtag_len(et_info_t *et) ++{ ++ if (et_ctf_pipeline_loopback(et)) ++ return 8; ++ if (et_ctf_active(et)) ++ return 4; ++ return 0; ++} ++ ++void *et_get_hndl(uint unit) ++{ ++ et_info_t *listptr; ++ void *roboptr; ++ ++ roboptr = NULL; ++ ++ for (listptr = et_list; listptr; listptr = listptr->next) { ++ if (listptr->etc->unit == unit) { ++ roboptr = listptr->etc->robo; ++ break; ++ } ++ } ++ ++ return roboptr; ++} ++ ++static void ++et_free(et_info_t *et) ++{ ++ et_info_t **prev; ++ osl_t *osh; ++ ++ if (et == NULL) ++ return; ++ ++ ET_TRACE(("et: et_free\n")); ++ ++ if (et->dev && et->dev->irq) ++ free_irq(et->dev->irq, et); ++ ++#ifdef NAPI2_POLL ++ napi_disable(&et->napi_poll); ++ netif_napi_del(&et->napi_poll); ++#endif /* NAPI2_POLL */ ++ ++#ifdef HNDCTF ++ if (et->cih) ++ ctf_dev_unregister(et->cih, et->dev); ++#endif /* HNDCTF */ ++ ++ if (et->dev) { ++ unregister_netdev(et->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ free_netdev(et->dev); ++#else ++ MFREE(et->osh, et->dev, sizeof(struct net_device)); ++#endif ++ et->dev = NULL; ++ } ++ ++#ifdef CTFPOOL ++ /* free the buffers in fast pool */ ++ osl_ctfpool_cleanup(et->osh); ++#endif /* CTFPOOL */ ++ ++#ifdef HNDCTF ++ /* free ctf resources */ ++ if (et->cih) ++ ctf_detach(et->cih); ++#endif /* HNDCTF */ ++ ++ /* free common resources */ ++ if (et->etc) { ++ etc_detach(et->etc); ++ et->etc = NULL; ++ } ++ ++ /* ++ * unregister_netdev() calls get_stats() which may read chip registers ++ * so we cannot unmap the chip registers until after calling unregister_netdev() . ++ */ ++ if (et->regsva) { ++ iounmap((void *)et->regsva); ++ et->regsva = NULL; ++ } ++ ++ /* remove us from the global linked list */ ++ for (prev = &et_list; *prev; prev = &(*prev)->next) ++ if (*prev == et) { ++ *prev = et->next; ++ break; ++ } ++ ++ osh = et->osh; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ free_netdev(et->dev); ++ et->dev = NULL; ++#else ++ MFREE(et->osh, et, sizeof(et_info_t)); ++#endif ++ ++ if (MALLOCED(osh)) { ++ ET_ERROR(("Memory leak of bytes %d\n", MALLOCED(osh))); ++ } ++ ASSERT(MALLOCED(osh) == 0); ++ ++ osl_detach(osh); ++} ++ ++static int ++et_open(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_open\n", et->etc->unit)); ++ ++ et->etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; ++ et->etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: et->etc->promisc; ++#ifdef GMAC_RATE_LIMITING ++ et->etc->rl_enabled = et_rx_rate_limit; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ ET_LOCK(et); ++ et_up(et); ++ ET_UNLOCK(et); ++ ++ OLD_MOD_INC_USE_COUNT; ++ ++ return (0); ++} ++ ++static int ++et_close(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_close\n", et->etc->unit)); ++ ++ et->etc->promisc = FALSE; ++ et->etc->allmulti = FALSE; ++ ++ ET_LOCK(et); ++ et_down(et, 1); ++ ET_UNLOCK(et); ++ ++ OLD_MOD_DEC_USE_COUNT; ++ ++ return (0); ++} ++ ++#if defined(BCMDMASGLISTOSL) ++/* ++ * Driver level checksum offload. This is being done so that we can advertise ++ * checksum offload support to Linux. ++ */ ++static void BCMFASTPATH_HOST ++et_cso(et_info_t *et, struct sk_buff *skb) ++{ ++ struct ethervlan_header *evh; ++ uint8 *th = skb_transport_header(skb); ++ uint16 thoff, eth_type, *check; ++ uint8 prot; ++ ++ ASSERT(!PKTISCTF(et->osh, skb)); ++ ++ evh = (struct ethervlan_header *)PKTDATA(et->osh, skb); ++ eth_type = ((evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) ? ++ evh->ether_type : evh->vlan_type); ++ ++ /* tcp/udp checksum calculation */ ++ thoff = (th - skb->data); ++ if (eth_type == HTON16(ETHER_TYPE_IP)) { ++ struct iphdr *ih = ip_hdr(skb); ++ prot = ih->protocol; ++ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); ++ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? ++ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); ++ *check = 0; ++ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); ++ *check = csum_tcpudp_magic(ih->saddr, ih->daddr, ++ skb->len - thoff, prot, skb->csum); ++ } else if (eth_type == HTON16(ETHER_TYPE_IPV6)) { ++ struct ipv6hdr *ih = ipv6_hdr(skb); ++ prot = IPV6_PROT(ih); ++ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); ++ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? ++ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); ++ *check = 0; ++ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); ++ *check = csum_ipv6_magic(&ih->saddr, &ih->daddr, ++ skb->len - thoff, prot, skb->csum); ++ } else { ++ return; ++ } ++ ++ if ((*check == 0) && (prot == IP_PROT_UDP)) ++ *check = CSUM_MANGLED_0; ++} ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++#ifdef ET_ALL_PASSIVE ++/* Schedule a completion handler to run at safe time */ ++static int ++et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context) ++{ ++ et_task_t *task; ++ ++ ET_TRACE(("et%d: et_schedule_task\n", et->etc->unit)); ++ ++ if (!(task = MALLOC(et->osh, sizeof(et_task_t)))) { ++ ET_ERROR(("et%d: et_schedule_task: out of memory, malloced %d bytes\n", ++ et->etc->unit, MALLOCED(et->osh))); ++ return -ENOMEM; ++ } ++ ++ MY_INIT_WORK(&task->work, (work_func_t)fn); ++ task->context = context; ++ ++ if (!schedule_work(&task->work)) { ++ ET_ERROR(("et%d: schedule_work() failed\n", et->etc->unit)); ++ MFREE(et->osh, task, sizeof(et_task_t)); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static void BCMFASTPATH ++et_txq_work(struct et_task *task) ++{ ++ et_info_t *et = (et_info_t *)task->context; ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_LOCK(et); ++#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ et_sendnext(et); ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_UNLOCK(et); ++#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ return; ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++#ifdef GMAC3 ++/* et_start counterpart (test performance of using a queue) */ ++static int BCMFASTPATH ++et_forward(struct sk_buff *skb, struct net_device *dev, int cnt) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++ void *p, *n; ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++ ++ et = ET_INFO(dev); ++ etc = et->etc; ++ ++ /* BUZZZ_DPL1(ET_FORWARD, 3, etc->unit, (uint32)skb, cnt); */ ++ ET_TRACE(("et%d: et_forward\n", etc->unit)); ++ ET_LOG("et%d: et_forward", etc->unit, 0); ++ ++ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); ++ ++ //p = PKTFRMFORWARD(etc->osh, skb, cnt); ++ p = PKTFRMNATIVE(etc->osh, skb); ++ ASSERT(p != NULL); ++ ++ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", ++ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) fwdpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ ++ /* ---------------------------------------- */ ++ /* ---------------------------------------- */ ++ ++ FOREACH_CHAINED_PKT(p, n) { ++ ++ PKTCLRCHAINED(et->osh, p); ++ if (n == NULL) ++ PKTCSETFLAG(p, 1); ++ (*etc->chops->tx)(etc->ch, p); ++ ++ etc->txframe++; ++ etc->txbyte += PKTLEN(et->osh, p); ++ } ++ /* BUZZZ_DPL2(ET_FORWARD_RTN, 0); */ ++ ++ return FWDER_SUCCESS; ++} ++#endif /* GMAC3 */ ++ ++ ++#if defined(BCMDMASGLISTOSL) ++/* ++ * Convert a non leaner packet to a linear packet ++ */ ++static int BCMFASTPATH ++et_convert2linear_skb(struct sk_buff *skb, et_info_t *et) ++{ ++ int copy_len, z; ++ unsigned char my_buff[100]; ++ unsigned char *to_buffer; ++ ++ if (skb_is_nonlinear(skb)) { ++ ++ copy_len = skb->data_len; ++ skb_header_pointer(skb, skb_headlen(skb), ++ skb->data_len, (void*)my_buff); ++ ++ /* Trim packet to only header, should make linear */ ++ if (__pskb_trim(skb, skb_headlen(skb))) { ++ ET_ERROR(("et%d: __pskb_trim() error\n", et->etc->unit)); ++ return -1; ++ } ++ ++ if (skb_is_nonlinear(skb)) { ++ ET_ERROR(("et%d: skb_is_nonlinear() error\n", et->etc->unit)); ++ return -1; ++ } else { ++ to_buffer = skb_put(skb, copy_len); ++ ++ for (z=0; z < copy_len; z++) { ++ to_buffer[z] = my_buff[z]; ++ } ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Calculate checksum ++ */ ++static int BCMFASTPATH ++et_linear_skb_cksum(struct sk_buff *skb, et_info_t *et, int brcmtag) ++{ ++ int ret; ++ void *usr_data; ++ int ip_hdr_len, ip_tot_len, tcp_hdr_len, udp_hdr_len, usr_data_len; ++ struct iphdr *iph = NULL; ++ int save_len; ++ int offset; ++ int brcm_tag_len, hdr_len, vlan_tag_len; ++ struct ethervlan_header *evh; ++ ++ brcm_tag_len=0; ++ if (brcmtag) { ++ brcm_tag_len = et_bcmtag_len(et); ++ } ++ evh = (struct ethervlan_header *)(skb->data+brcm_tag_len); ++ ++ iph = (struct iphdr *)skb->network_header; ++ ip_hdr_len = ip_hdr(skb)->ihl << 2; ++ ip_tot_len = ntohs(ip_hdr(skb)->tot_len); ++ tcp_hdr_len = tcp_hdr(skb)->doff << 2; ++ udp_hdr_len = 8; ++ vlan_tag_len = 0; ++ if (evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) { ++ /* add in vlan tags */ ++ vlan_tag_len = 4; ++ } ++ ++ /* Generate IPv4 checksum */ ++ ret = skb_checksum_help(skb); ++ ++ // printk(" ip done: skb len=%d ip_checksum=%x ret=%x (csum=%x tcp_checksum=%x)\n", ++ // skb->len, iph->check, ret, skb->csum, tcp_hdr(skb)->check); ++ ++ /* mark checksum mode */ ++ /* - clear partial checksum */ ++ skb->ip_summed = CHECKSUM_NONE; ++ skb->csum = 0; ++ ++ hdr_len=0; ++ /* build csum for user data */ ++ if (iph->protocol == IPPROTO_TCP) { ++ usr_data = skb->network_header + ip_hdr_len + tcp_hdr_len; ++ usr_data_len = ip_tot_len - ip_hdr_len - tcp_hdr_len; ++ hdr_len = 20; ++ } else { ++ usr_data = skb->network_header + ip_hdr_len + udp_hdr_len; ++ usr_data_len = ip_tot_len - ip_hdr_len - udp_hdr_len; ++ hdr_len = 8; ++ } ++ ++ /* offset = 12-mac, 2-etype, 20-ip, x-bcm, (20-tcp or 8-udp), [4-vlan] */ ++ offset = 34 + brcm_tag_len + hdr_len + vlan_tag_len; ++ if (usr_data != ((skb->data)+offset)) { ++ printk("et%d: FIXME usr_data not expected %p vs %p\n", ++ et->etc->unit, skb->data+offset, usr_data); ++ } ++ ++ skb->csum = csum_partial(usr_data, usr_data_len, 0); ++ // printk(" csum prep: skb_data at %x=%x, skb_csum=%x \n", ++ // (skb->data + 58), *(skb->data + 58), skb->csum); ++ ++ /* save skb length */ ++ save_len = skb->len; ++ ++ /* adjust skb->len to inlcude TCP header and user data */ ++ /* - use ip_hdr.tot_len - ip_hdr_len */ ++ skb->len = ip_tot_len - ip_hdr_len; ++ ++ /* offset = 12-mac, 2-etype, 20-ip, x-bcm, [4-vlan] */ ++ offset = 34 + brcm_tag_len + vlan_tag_len; ++ if (skb->len != save_len-offset) { ++ printk("et%d: FIXME sdk_len not expected %d vs %d\n", ++ et->etc->unit, skb->len, save_len-offset); ++ } ++ ++ // printk(" tcp prep: socket=%x inet=%x \n", skb->sk, inet_sk(skb->sk)); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ /* Generate TCP checksum */ ++ tcp_hdr(skb)->check = 0; ++ tcp_v4_send_check(skb->sk, skb); ++ } else { ++ /* udp checksum optional */ ++ udp_hdr(skb)->check = 0; ++ } ++ ++ /* restore skb length */ ++ skb->len = save_len; ++ ++ // printk(" tcp done: checksum=%x\n", tcp_hdr(skb)->check); ++ ++ return 0; ++} ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ ++/* ++ * Yeah, queueing the packets on a tx queue instead of throwing them ++ * directly into the descriptor ring in the case of dma is kinda lame, ++ * but this results in a unified transmit path for both dma and pio ++ * and localizes/simplifies the netif_*_queue semantics, too. ++ */ ++static int BCMFASTPATH ++et_start(struct sk_buff *skb, struct net_device *dev) ++{ ++ et_info_t *et; ++ uint32 q = 0; ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ int less68 = 0; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++#if (defined(CONFIG_IPROC_FA2_NAPT_BYPASS) || defined(BCMDMASGLISTOSL)) ++ struct iphdr *iph = NULL; ++#endif /* (defined(CONFIG_IPROC_FA2_NAPT_BYPASS) || defined(BCMDMASGLISTOSL)) */ ++#ifdef ET_LIMIT_TXQ ++ int qlen; ++#endif /* ET_LIMIT_TXQ */ ++ ++ et = ET_INFO(dev); ++ ++#if defined(BCMDMASGLISTOSL) ++ { ++ bool sw_cksum=true; ++ ++ if (!PKTSUMNEEDED(skb)) ++ sw_cksum=false; ++ ++ #if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++ if (et->etc->unit == 2) ++ sw_cksum=false; ++ #endif /* (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) */ ++ ++ #if !defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ /* can only update checksum once. */ ++ /* if checksum is updated later, don't do it here */ ++ iph = (struct iphdr *)skb->network_header; ++ if (((skb->len+et_bcmtag_len(et)) < MIN_PACKET_SIZE) && ++ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ sw_cksum=false; ++ } ++ #endif /* !defined(CONFIG_IPROC_FA2_CS_OFFLOAD) */ ++ ++ if (sw_cksum) { ++ et_cso(et, skb); ++ } ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ if (skb_is_nonlinear(skb)) ++ et->etc->txsgpkt++; ++ ++ if (skb->len > et->etc->txmaxlen) { ++ et->etc->txmaxlen = skb->len; ++ } ++ ++#if defined(CONFIG_MACH_NS) ++ if (ET_GMAC(et->etc) && (et->etc->qos)) ++ q = etc_up2tc(PKTPRIO(skb)); ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ET_TRACE(("et%d: et_start: len %d\n", et->etc->unit, skb->len)); ++ ET_LOG("et%d: et_start: len %d", et->etc->unit, skb->len); ++ ++ et->etc->txfrm++; ++#ifdef ET_LIMIT_TXQ ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_TXQ_LOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ qlen = skb_queue_len(&et->txq[q]); ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_TXQ_UNLOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ if (qlen > et->etc->txqlen) ++ et->etc->txqlen = qlen; ++ if (et_txq_thresh && (qlen >= et_txq_thresh)) { ++ //PKTCFREE(et->osh, skb, TRUE); ++ //return 0; ++ et->etc->txfrmdropped++; ++ /* schedule work */ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++#else ++ schedule_work(&et->txq_task.work); ++#endif ++ } ++#endif /* ET_ALL_PASSIVE */ ++ return NETDEV_TX_BUSY; ++ } ++#endif /* ET_LIMIT_TXQ */ ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) ++ ++ if (et_ctf_pipeline_loopback(et)) { ++ int bcm_hdr_size = 8; /* type 3 */ ++ ++ /* add brcm tag; tag is locate at offset 0-3 */ ++ ET_TRACE(("et%d %s: headroom(0x%x)\n", et->etc->unit, __FUNCTION__, skb_headroom(skb))); ++ ET_TRACE(("et%d: NOT enough headroom for BRCM tag.\n", et->etc->unit)); ++ if (skb_headroom(skb) < bcm_hdr_size) { ++ struct sk_buff *sk_tmp = skb; ++ skb = skb_realloc_headroom(sk_tmp, bcm_hdr_size); ++ PKTCFREE(et->osh, sk_tmp, TRUE); ++ if (!skb) { ++ ET_ERROR(("et%d: Failed to realloc headroom for BRCM tag; NOT transmitting frame.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ET_TRACE(("Adding BRCM TAG\n")); ++ __skb_push(skb, bcm_hdr_size); ++ ++ /* insert egress hdr type 3*/ ++ skb->data[0] = 0x60; /* opcode b011 */ ++ skb->data[1] = 0x00; ++ skb->data[2] = 0x00; ++ skb->data[3] = 0x00; ++ skb->data[4] = 0x00; ++ skb->data[5] = 0x00; ++ skb->data[6] = 0x00; ++ skb->data[7] = 0x28; /* fwd to AXI1, proc by SPU */ ++ ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ET_TRACE(("forcing skb->len (%d) to %d\n", skb->len, MIN_PACKET_SIZE)); ++ skb->len = MIN_PACKET_SIZE; ++ } ++ __pskb_trim(skb, skb->len); ++ ++ } else if (et_ctf_active(et)) { ++ int bcm_hdr_size = 4; ++ ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ bcm_hdr_size = 8; ++#endif ++ /* add brcm tag; tag is located at offset 0-3 */ ++ ET_TRACE(("et%d %s: headroom(0x%x)\n", et->etc->unit, __FUNCTION__, skb_headroom(skb))); ++ if (skb_headroom(skb) < bcm_hdr_size) { ++ struct sk_buff *sk_tmp = skb; ++ ++ ET_TRACE(("et%d: NOT enough headroom for BRCM tag.\n", et->etc->unit)); ++ skb = skb_realloc_headroom(sk_tmp, bcm_hdr_size); ++ PKTCFREE(et->osh, sk_tmp, TRUE); ++ if (!skb) { ++ ET_ERROR(("et%d: Failed to realloc headroom for BRCM tag; NOT transmitting frame.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ET_TRACE(("Adding BRCM TAG\n")); ++ __skb_push(skb, 4); ++ ++ /* insert ingress hdr type 0*/ ++ skb->data[0] = 0x00; ++ skb->data[1] = 0x00; ++ skb->data[2] = 0x00; ++ skb->data[3] = 0x00; ++ ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD) && \ ++ defined(CONFIG_IPROC_FA2_CS_OFFLOAD_SMALL_PKT_WA)) ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ int ret; ++ ret = skb_checksum_help(skb); ++ if (ret) { ++ ET_ERROR(("et%d: skb_checksum_help() returned error %d\n", et->etc->unit, ret)); ++ } ++ } ++ } ++#endif ++ ++#if defined(BCMDMASGLISTOSL) ++ iph = (struct iphdr *)skb->network_header; ++ if ((skb->len < MIN_PACKET_SIZE) && ++ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ /* convert nonlinear SKB to linear */ ++ et_convert2linear_skb(skb, et); ++ if (skb->sk) { ++ /* if socket - calculate checksum */ ++ et_linear_skb_cksum(skb, et, 1); ++ } ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ET_TRACE(("forcing skb->len (%d) to %d\n", skb->len, MIN_PACKET_SIZE)); ++ skb->len = MIN_PACKET_SIZE; ++ } ++ __pskb_trim(skb, skb->len); ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ iph = (struct iphdr *)skb->network_header; ++ if (!less68 &&((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ fa2_modify_header(skb); ++ /* Send pkt to AXI1 */ ++ et = et_get_eth3_info(); ++ if (!et->etc->up) { ++ ET_ERROR(("et%d: eth3 not up, exit.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ goto send_packet; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ++#if defined(CONFIG_IPROC_FA) ++ if(!gBypass) { ++ fc_transmit(skb); ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++#if defined(CONFIG_IPROC_FA2) ++ if(!gBypass) { ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ struct fa2_pkt_info pkt_info; ++ extern spinlock_t fa2_lock; ++ uint8_t p_op; ++ ++ //memset((void *)&pkt_info, 0x0, sizeof(pkt_info)); ++ /* Initialize pkt_info */ ++ pkt_info.mac = pkt_info.ipv4_or_ipv6 = pkt_info.tcp_or_udp = NULL; ++ ++ pkt_info.vlan_tag = pkt_info.vlan_tag_next = pkt_info.et_type = ++ pkt_info.eth_snapllc = pkt_info.need_hdr_bytes = ++ pkt_info.hdr_words[0] = pkt_info.hdr_words[1] = 0; ++ ++ pkt_info.proto = FA2_PROTO_NOT_SUPPORTED; ++ pkt_info.pkt_type = FA2_INVALID_PKT; ++ ++ spin_lock(&fa2_lock); ++ fa2_get_packet_info(skb, &pkt_info); ++ spin_unlock(&fa2_lock); ++ ++ /* Check if this packet can be processed by FA+ pipeline. ++ * If not, let the eth driver handle it. ++ * If yes, do fa+ processing ++ */ ++ if (pkt_info.proto != FA2_PROTO_NOT_SUPPORTED) { ++ if (pkt_info.pkt_type != FA2_FWD_PKT) { ++ ++ p_op = pkt_info.hdr_words[1] & FA2_BCMHDR_OP_3_PROC_OP; ++ ++ /* Check for proc_ops 0, 1, 2 and 5 */ ++ if ((p_op <= 0x2) || (p_op == 0x5)) { ++ ++ fa2_transmit(skb, &pkt_info); ++ } ++ } else { ++ fa2_transmit(skb, &pkt_info); ++ } ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD_SMALL_PKT_WA) ++ if (pkt_info.pkt_type == FA2_LOCAL_SMALL_TX_PKT) { ++ fa2_transmit(skb, &pkt_info); ++ } ++#endif ++ } ++ ++ /* If the packet is a L4 packet, and it is _not_ a forwarded packet, ++ * then add bcm hdr 0x3 bytes ++ */ ++ if ((pkt_info.proto != FA2_PROTO_NOT_SUPPORTED) && ++ (pkt_info.pkt_type == FA2_LOCAL_TX_PKT)) { ++ ++ /* Add Broadcom header bytes (8 bytes). Note 4 bytes were ++ * 'push'ed earlier ++ */ ++ __skb_push(skb, 4); ++ *((uint32_t *)skb->data) = htonl(pkt_info.hdr_words[0]); ++ *((uint32_t *)skb->data + 1) = htonl(pkt_info.hdr_words[1]); ++ __pskb_trim(skb, skb->len); ++ ++ /* Send pkt to AXI1 */ ++ et = et_get_eth3_info(); ++ if (!et->etc->up) { ++ ET_ERROR(("et%d: eth3 not up, exit.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ++#else ++ fa2_transmit(skb, NULL); ++#endif ++ } ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ } ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) */ ++ ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++send_packet: ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ++ /* put it on the tx queue and call sendnext */ ++ ET_TXQ_LOCK(et); ++ __skb_queue_tail(&et->txq[q], skb); ++ et->etc->txq_state |= (1 << q); ++ ET_TXQ_UNLOCK(et); ++ ++ if (!ET_ALL_PASSIVE_ENAB(et)) { ++ ET_LOCK(et); ++ et_sendnext(et); ++ ET_UNLOCK(et); ++ } ++#ifdef ET_ALL_PASSIVE ++ else ++#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++#else ++ schedule_work(&et->txq_task.work); ++#endif ++ ++#endif /* ET_ALL_PASSIVE */ ++ ++ ET_LOG("et%d: et_start ret\n", et->etc->unit, 0); ++ ++ return (0); ++} ++ ++static void BCMFASTPATH ++et_sendnext(et_info_t *et) ++{ ++ etc_info_t *etc; ++ struct sk_buff *skb; ++ void *p, *n; ++ uint32 priq = TX_Q0; ++#ifdef DMA ++ uint32 txavail; ++#endif ++#ifdef PRINT_PKT_SUM ++ int tagoff=12; ++#endif /* PRINT_PKT_SUM */ ++ ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++ ++ etc = et->etc; ++ ++ ET_TRACE(("et%d: et_sendnext\n", etc->unit)); ++ ET_LOG("et%d: et_sendnext", etc->unit, 0); ++ ++ /* dequeue packets from highest priority queue and send */ ++ while (1) { ++ ET_TXQ_LOCK(et); ++ ++ if (etc->txq_state == 0) ++ break; ++ ++ priq = etc_priq(etc->txq_state); ++ ++ ET_TRACE(("et%d: txq_state %x priq %d txavail %d\n", ++ etc->unit, etc->txq_state, priq, ++ *(uint *)etc->txavail[priq])); ++ ++ if ((skb = skb_peek(&et->txq[priq])) == NULL) { ++ etc->txq_state &= ~(1 << priq); ++ ET_TXQ_UNLOCK(et); ++ continue; ++ } ++ ++#ifdef DMA ++ /* current highest priority dma queue is full */ ++ txavail = *(uint *)(etc->txavail[priq]); ++ if ((PKTISCHAINED(skb) && (txavail < PKTCCNT(skb))) || (txavail == 0)) ++#else /* DMA */ ++ if (etc->pioactive != NULL) ++#endif /* DMA */ ++ { ++ etc->txdmafull++; ++ break; ++ } ++ ++ skb = __skb_dequeue(&et->txq[priq]); ++ ++ ET_TXQ_UNLOCK(et); ++ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); ++ ++#ifdef PRINT_PKT_SUM ++ tagoff = 16; ++ printf("et%d: txpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, ++ skb->data[tagoff], skb->data[tagoff+1], skb->data[tagoff+2], skb->data[tagoff+3]); ++#endif /* PRINT_PKT_SUM */ ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) txpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ /* convert the packet. */ ++ p = PKTFRMNATIVE(etc->osh, skb); ++ ASSERT(p != NULL); ++ ++ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", ++ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); ++ ++ ET_TX_LOCK(et); ++ FOREACH_CHAINED_PKT(p, n) { ++ /* replicate vlan header contents from curr frame */ ++ if (n != NULL) { ++ uint8 *n_evh; ++ n_evh = PKTPUSH(et->osh, n, VLAN_TAG_LEN); ++ *(struct ethervlan_header *)n_evh = ++ *(struct ethervlan_header *)PKTDATA(et->osh, p); ++ } ++ (*etc->chops->tx)(etc->ch, p); ++#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_LOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ etc->txframe++; ++ etc->txbyte += PKTLEN(et->osh, p); ++#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_UNLOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ } ++ ET_TX_UNLOCK(et); ++ } ++ ++ /* no flow control when qos is enabled */ ++ if (!et->etc->qos) { ++ /* stop the queue whenever txq fills */ ++ if ((skb_queue_len(&et->txq[TX_Q0]) > DATAHIWAT) && !netif_queue_stopped(et->dev)) { ++ et->etc->txqstop++; ++ netif_stop_queue(et->dev); ++ } ++ else if (netif_queue_stopped(et->dev) && ++ (skb_queue_len(&et->txq[TX_Q0]) < (DATAHIWAT/2))) { ++ netif_wake_queue(et->dev); ++ } ++ } else { ++ /* drop the frame if corresponding prec txq len exceeds hiwat ++ * when qos is enabled. ++ */ ++ if ((priq != TC_NONE) && (skb_queue_len(&et->txq[priq]) > DATAHIWAT)) { ++ skb = __skb_dequeue(&et->txq[priq]); ++ PKTCFREE(et->osh, skb, TRUE); ++ ET_ERROR(("et%d: %s: txqlen %d\n", et->etc->unit, ++ __FUNCTION__, skb_queue_len(&et->txq[priq]))); ++ } ++ } ++ ++ ET_TXQ_UNLOCK(et); ++} ++ ++void ++et_init(et_info_t *et, uint options) ++{ ++ ET_TRACE(("et%d: et_init\n", et->etc->unit)); ++ ET_LOG("et%d: et_init", et->etc->unit, 0); ++ ++ etc_init(et->etc, options); ++} ++ ++ ++void ++et_reset(et_info_t *et) ++{ ++ ET_TRACE(("et%d: et_reset\n", et->etc->unit)); ++ ++ etc_reset(et->etc); ++ ++ /* zap any pending dpc interrupt bits */ ++ et->events = 0; ++ ++ /* dpc will not be rescheduled */ ++ et->resched = 0; ++} ++ ++void ++et_up(et_info_t *et) ++{ ++ etc_info_t *etc; ++ ++ etc = et->etc; ++ ++ if (etc->up) ++ return; ++ ++ ET_TRACE(("et%d: et_up\n", etc->unit)); ++ ++ etc_up(etc); ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (et->set) { ++ /* This will happen if running watchdog to monitor mdio bus */ ++ /* and port not up */ ++ del_timer(&et->timer); ++ et->set = FALSE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++ /* schedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set=TRUE; ++ ++ netif_start_queue(et->dev); ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ et->etc->pktc = TRUE; ++ ++ /* ++ * Attach my transmit handler to UPSTREAM fwder instance on core=unit ++ * wl# MAC -> wl_sendup -> et_forward -> et::GMAC# ++ * and get the DNSTREAM direction transmit handler for use in sendup. ++ * et_sendup/chain -> et->fwdh->start_xmit=wl_start -> wl# MAC ++ */ ++ et->fwdh = fwder_attach(et_forward, et->dev, et->etc->unit, FWD_UPSTREAM); ++ /* fwder_dump_all(); */ ++ } ++#endif /* GMAC3 */ ++} ++ ++void ++et_down(et_info_t *et, int reset) ++{ ++ etc_info_t *etc; ++ struct sk_buff *skb; ++ int32 i; ++ bool stoptmr = TRUE; ++ ++ etc = et->etc; ++ ++ ET_TRACE(("et%d: et_down\n", etc->unit)); ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ et->fwdh = fwder_dettach(et->fwdh); ++ /* fwder_dump_all(); */ ++ } ++#endif /* GMAC3 */ ++ ++ netif_down(et->dev); ++ netif_stop_queue(et->dev); ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (gmac_has_mdio_access()) { ++ /* we have mdio bus don't stop timer so we can continue to monitor */ ++ stoptmr = FALSE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++ if ( stoptmr ) { ++ /* stop watchdog timer */ ++ del_timer(&et->timer); ++ et->set = FALSE; ++ } ++ ++#ifdef GMAC_RATE_LIMITING ++ /* stop ratelimiting timer */ ++ del_timer(&et->etc->rl_timer); ++ et->etc->rl_set = FALSE; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ etc_down(etc, reset); ++ ++ /* flush the txq(s) */ ++ for (i = 0; i < NUMTXQ; i++) ++ while ((skb = skb_dequeue(&et->txq[i]))) ++ PKTFREE(etc->osh, skb, TRUE); ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ /* kill dpc */ ++ ET_UNLOCK(et); ++ tasklet_kill(&et->tasklet); ++ ET_LOCK(et); ++#endif /* NAPI_POLL */ ++} ++ ++/* ++ * These are interrupt on/off entry points. Disable interrupts ++ * during interrupt state transition. ++ */ ++void ++et_intrson(et_info_t *et) ++{ ++ unsigned long flags; ++ INT_LOCK(et, flags); ++ (*et->etc->chops->intrson)(et->etc->ch); ++ INT_UNLOCK(et, flags); ++} ++ ++static void ++_et_watchdog(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_LOCK(et); ++ ++ etc_watchdog(et->etc); ++ ++ if (et->set) { ++ /* reschedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ } ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ /* this in case port when up then down before we released mdio */ ++ else if (gmac_has_mdio_access()) { ++ /* interface not up but we have mdio bus */ ++ /* reschedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set = TRUE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++#ifdef CTFPOOL ++ /* allocate and add a new skb to the pkt pool */ ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ if (CTF_ENAB(et->cih)) ++#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ osl_ctfpool_replenish(et->osh, CTFPOOL_REFILL_THRESH); ++#endif /* CTFPOOL */ ++ ET_UNLOCK(et); ++} ++ ++#ifdef ET_ALL_PASSIVE ++static void ++et_watchdog_task(et_task_t *task) ++{ ++ et_info_t *et = ET_INFO((struct net_device *)task->context); ++ ++ _et_watchdog((struct net_device *)task->context); ++ MFREE(et->osh, task, sizeof(et_task_t)); ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++static void ++et_watchdog(ulong data) ++{ ++ struct net_device *dev = (struct net_device *)data; ++#ifdef ET_ALL_PASSIVE ++ et_info_t *et = ET_INFO(dev); ++#endif /* ET_ALL_PASSIVE */ ++ ++ if (!ET_ALL_PASSIVE_ENAB(et)) ++ _et_watchdog(dev); ++#ifdef ET_ALL_PASSIVE ++ else ++ et_schedule_task(et, et_watchdog_task, dev); ++#endif /* ET_ALL_PASSIVE */ ++} ++ ++/* Rate limiting */ ++#ifdef GMAC_RATE_LIMITING ++static void et_release_congestion(ulong data) ++{ ++ struct net_device *dev = (struct net_device *)data; ++ et_info_t *et = ET_INFO(dev); ++ ++ if (!et) { ++ return; ++ } ++ if (et->etc->rl_stopping_broadcasts) { ++ //printf("et%d: %s: releasing broadcast packet congestion; dropped: 0x%x\n", et->etc->unit, __FUNCTION__, et->etc->rl_dropped_bc_packets); ++ et->etc->rl_stopping_broadcasts = 0; ++ /* clear the number of dropped broadcast packets */ ++ et->etc->rl_dropped_bc_packets = 0; ++ } ++ if (et->etc->rl_stopping_all_packets) { ++ //printf("et%d: %s: releasing all packet congestion; dropped: 0x%x\n", et->etc->unit, __FUNCTION__, et->etc->rl_dropped_all_packets); ++ et->etc->rl_stopping_all_packets = 0; ++ et->etc->rl_dropped_all_packets = 0; ++ } ++} ++#endif /* GMAC_RATE_LIMITING */ ++ ++ ++ ++static int ++et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ++{ ++ et_info_t *et = ET_INFO(dev); ++ ++ ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | ++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | ++ SUPPORTED_Autoneg | SUPPORTED_TP); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ ecmd->supported |= SUPPORTED_1000baseT_Full | SUPPORTED_Pause; ++#endif ++#if defined(CONFIG_MACH_HR2) ++ ecmd->supported |= SUPPORTED_Pause; ++#endif ++ ++ ecmd->advertising = ADVERTISED_TP; ++ ecmd->advertising |= (et->etc->advertise & ADV_10HALF) ? ++ ADVERTISED_10baseT_Half : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_10FULL) ? ++ ADVERTISED_10baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_100HALF) ? ++ ADVERTISED_100baseT_Half : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_100FULL) ? ++ ADVERTISED_100baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise2 & ADV_1000FULL) ? ++ ADVERTISED_1000baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise2 & ADV_1000HALF) ? ++ ADVERTISED_1000baseT_Half : 0; ++ ecmd->advertising |= (et->etc->forcespeed == ET_AUTO) ? ++ ADVERTISED_Autoneg : 0; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ ecmd->advertising |= ADVERTISED_Pause; ++#endif ++ if (et->etc->linkstate) { ++ ecmd->speed = (et->etc->speed == 1000) ? SPEED_1000 : ++ ((et->etc->speed == 100) ? SPEED_100 : SPEED_10); ++ ecmd->duplex = (et->etc->duplex == 1) ? DUPLEX_FULL : DUPLEX_HALF; ++ } else { ++ ecmd->speed = 0; ++ ecmd->duplex = 0; ++ } ++ ecmd->port = PORT_TP; ++ ecmd->phy_address = et->etc->phyaddr; ++ ecmd->transceiver = XCVR_INTERNAL; ++ ecmd->autoneg = (et->etc->forcespeed == ET_AUTO) ? AUTONEG_ENABLE : AUTONEG_DISABLE; ++ ecmd->maxtxpkt = 0; ++ ecmd->maxrxpkt = 0; ++ ++ return 0; ++} ++ ++static int ++et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ++{ ++ int speed[2]; ++ ++ et_info_t *et = ET_INFO(dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return (-EPERM); ++ ++ if (ecmd->autoneg == AUTONEG_ENABLE) { ++ speed[0] = ET_AUTO; ++ speed[1] = ecmd->advertising; ++ } else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) ++ speed[0] = ET_10HALF; ++ else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_10FULL; ++ else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) ++ speed[0] = ET_100HALF; ++ else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_100FULL; ++ else if (ecmd->speed == SPEED_1000 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_1000FULL; ++ else ++ return (-EINVAL); ++ ++ return etc_ioctl(et->etc, ETCSPEED, speed); ++} ++ ++static void ++et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info) ++{ ++ et_info_t *et = ET_INFO(dev); ++ bzero(info, sizeof(struct ethtool_drvinfo)); ++ info->cmd = ETHTOOL_GDRVINFO; ++ sprintf(info->driver, "et%d", et->etc->unit); ++ strncpy(info->version, EPI_VERSION_STR, sizeof(info->version)); ++ info->version[(sizeof(info->version))-1] = '\0'; ++} ++ ++#ifdef SIOCETHTOOL ++static int ++et_ethtool(et_info_t *et, struct ethtool_cmd *ecmd) ++{ ++ int ret = 0; ++ ++ ET_LOCK(et); ++ ++ switch (ecmd->cmd) { ++ case ETHTOOL_GSET: ++ ret = et_get_settings(et->dev, ecmd); ++ break; ++ case ETHTOOL_SSET: ++ ret = et_set_settings(et->dev, ecmd); ++ break; ++ case ETHTOOL_GDRVINFO: ++ et_get_driver_info(et->dev, (struct ethtool_drvinfo *)ecmd); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ ET_UNLOCK(et); ++ ++ return (ret); ++} ++#endif /* SIOCETHTOOL */ ++ ++static int ++et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ et_info_t *et; ++ int error; ++ char *buf; ++ int size, ethtoolcmd; ++ bool get = 0, set; ++ et_var_t *var = NULL; ++ void *buffer = NULL; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_ioctl: cmd 0x%x\n", et->etc->unit, cmd)); ++ ++ switch (cmd) { ++#ifdef SIOCETHTOOL ++ case SIOCETHTOOL: ++ if (copy_from_user(ðtoolcmd, ifr->ifr_data, sizeof(uint32))) ++ return (-EFAULT); ++ ++ if (ethtoolcmd == ETHTOOL_GDRVINFO) ++ size = sizeof(struct ethtool_drvinfo); ++ else ++ size = sizeof(struct ethtool_cmd); ++ get = TRUE; set = TRUE; ++ break; ++#endif /* SIOCETHTOOL */ ++ case SIOCGETCDUMP: ++ size = IOCBUFSZ; ++ get = TRUE; set = FALSE; ++ break; ++ case SIOCGETCPHYRD: ++ case SIOCGETCPHYRD2: ++ case SIOCGETCROBORD: ++ size = sizeof(int) * 2; ++ get = TRUE; set = TRUE; ++ break; ++ case SIOCSETCSPEED: ++ case SIOCSETCPHYWR: ++ case SIOCSETCPHYWR2: ++ case SIOCSETCROBOWR: ++ size = sizeof(int) * 2; ++ get = FALSE; set = TRUE; ++ break; ++ case SIOCSETGETVAR: ++ size = sizeof(et_var_t); ++ set = TRUE; ++ break; ++ default: ++ size = sizeof(int); ++ get = FALSE; set = TRUE; ++ break; ++ } ++ ++ if ((buf = MALLOC(et->osh, size)) == NULL) { ++ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", MALLOCED(et->osh))); ++ return (-ENOMEM); ++ } ++ ++ if (set && copy_from_user(buf, ifr->ifr_data, size)) { ++ MFREE(et->osh, buf, size); ++ return (-EFAULT); ++ } ++ ++ if (cmd == SIOCSETGETVAR) { ++ var = (et_var_t *)buf; ++ if (var->buf) { ++ if (!var->set) ++ get = TRUE; ++ ++ if (!(buffer = (void *) MALLOC(et->osh, var->len))) { ++ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", ++ MALLOCED(et->osh))); ++ MFREE(et->osh, buf, size); ++ return (-ENOMEM); ++ } ++ ++ if (copy_from_user(buffer, var->buf, var->len)) { ++ MFREE(et->osh, buffer, var->len); ++ MFREE(et->osh, buf, size); ++ return (-EFAULT); ++ } ++ } ++ } ++ ++ switch (cmd) { ++#ifdef SIOCETHTOOL ++ case SIOCETHTOOL: ++ error = et_ethtool(et, (struct ethtool_cmd *)buf); ++ break; ++#endif /* SIOCETHTOOL */ ++ case SIOCSETGETVAR: ++ ET_LOCK(et); ++ error = etc_iovar(et->etc, var->cmd, var->set, buffer); ++ ET_UNLOCK(et); ++ if (!error && get) ++ error = copy_to_user(var->buf, buffer, var->len); ++ ++ if (buffer) ++ MFREE(et->osh, buffer, var->len); ++ break; ++ default: ++ ET_LOCK(et); ++ error = etc_ioctl(et->etc, cmd - SIOCSETCUP, buf) ? -EINVAL : 0; ++ ET_UNLOCK(et); ++ break; ++ } ++ ++ if (!error && get) ++ error = copy_to_user(ifr->ifr_data, buf, size); ++ ++ MFREE(et->osh, buf, size); ++ ++ return (error); ++} ++ ++static struct net_device_stats * ++et_get_stats(struct net_device *dev) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++ struct net_device_stats *stats; ++ int locked = 0; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_get_stats\n", et->etc->unit)); ++ ++ if (!in_atomic()) { ++ locked = 1; ++ ET_LOCK(et); ++ } ++ ++ etc = et->etc; ++ stats = &et->stats; ++ bzero(stats, sizeof(struct net_device_stats)); ++ ++ /* refresh stats */ ++ if (et->etc->up) ++ (*etc->chops->statsupd)(etc->ch); ++ ++ /* SWAG */ ++ stats->rx_packets = etc->rxframe; ++ stats->tx_packets = etc->txframe; ++ stats->rx_bytes = etc->rxbyte; ++ stats->tx_bytes = etc->txbyte; ++ stats->rx_errors = etc->rxerror; ++ stats->tx_errors = etc->txerror; ++ ++ if (ET_GMAC(etc)) { ++ gmacmib_t *mib; ++ ++ mib = etc->mib; ++ stats->collisions = mib->tx_total_cols; ++ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); ++ stats->rx_crc_errors = mib->rx_crc_errs; ++ stats->rx_frame_errors = mib->rx_align_errs; ++ stats->rx_missed_errors = mib->rx_missed_pkts; ++ } else { ++ bcmenetmib_t *mib; ++ ++ mib = etc->mib; ++ stats->collisions = mib->tx_total_cols; ++ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); ++ stats->rx_crc_errors = mib->rx_crc_errs; ++ stats->rx_frame_errors = mib->rx_align_errs; ++ stats->rx_missed_errors = mib->rx_missed_pkts; ++ ++ } ++ ++ stats->rx_fifo_errors = etc->rxoflo; ++ stats->rx_over_errors = etc->rxoflo; ++ stats->tx_fifo_errors = etc->txuflo; ++ ++ //etc_robomib(etc); ++ ++ if (locked) ++ ET_UNLOCK(et); ++ ++ return (stats); ++} ++ ++static int ++et_set_mac_address(struct net_device *dev, void *addr) ++{ ++ et_info_t *et; ++ struct sockaddr *sa = (struct sockaddr *) addr; ++ ++ et = ET_INFO(dev); ++ ET_TRACE(("et%d: et_set_mac_address\n", et->etc->unit)); ++ ++ if (et->etc->up) ++ return -EBUSY; ++ ++ bcopy(sa->sa_data, dev->dev_addr, ETHER_ADDR_LEN); ++ bcopy(dev->dev_addr, &et->etc->cur_etheraddr, ETHER_ADDR_LEN); ++ ++ return 0; ++} ++ ++static void ++et_set_multicast_list(struct net_device *dev) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ struct dev_mc_list *mclist; ++#else ++ struct netdev_hw_addr *ha ; ++#endif ++ int i; ++ int locked = 0; ++ ++ et = ET_INFO(dev); ++ etc = et->etc; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ mclist = NULL ; /* fend off warnings */ ++#else ++ ha = NULL ; ++#endif ++ ++ ET_TRACE(("et%d: et_set_multicast_list\n", etc->unit)); ++ ++ if (!in_atomic()) { ++ locked = 1; ++ ET_LOCK(et); ++ } ++ ++ if (etc->up) { ++ etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; ++ etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: etc->promisc; ++ ++ /* copy the list of multicasts into our private table */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ for (i = 0, mclist = dev->mc_list; mclist && (i < dev->mc_count); ++ i++, mclist = mclist->next) { ++ if (i >= MAXMULTILIST) { ++ etc->allmulti = TRUE; ++ i = 0; ++ break; ++ } ++ etc->multicast[i] = *((struct ether_addr *)mclist->dmi_addr); ++ } ++#else /* >= 2.6.36 */ ++ i = 0; ++ netdev_for_each_mc_addr(ha, dev) { ++ i ++; ++ if (i >= MAXMULTILIST) { ++ etc->allmulti = TRUE; ++ i = 0; ++ break; ++ } ++ etc->multicast[i] = *((struct ether_addr *)ha->addr); ++ } /* for each ha */ ++#endif /* LINUX_VERSION_CODE */ ++ etc->nmulticast = i; ++ ++ /* LR: partial re-init, DMA is already initialized */ ++ et_init(et, ET_INIT_INTRON); ++ } ++ ++ if (locked) ++ ET_UNLOCK(et); ++} ++ ++#ifdef CONFIG_BCM_GRO_ENABLE ++void et_flush(void *dev_id) ++{ ++ et_info_t *et; ++ struct chops *chops; ++ void *ch; ++ osl_t *osh; ++ ++ et = (et_info_t *)dev_id; ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ /* guard against shared interrupts */ ++ if (!et->etc->up) { ++ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); ++ return; ++ } ++ if (!et->napi_poll.gro_list) { ++ return; ++ } ++ /* disable interrupts */ ++ (*chops->intrsoff)(ch); ++ ++ et->resched = TRUE; ++ ++ napi_gro_flush(&et->napi_poll); ++ ++ /* enable interrupts now */ ++ (*chops->intrson)(ch); ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++static irqreturn_t BCMFASTPATH ++et_isr(int irq, void *dev_id) ++#else ++static irqreturn_t BCMFASTPATH ++et_isr(int irq, void *dev_id, struct pt_regs *ptregs) ++#endif ++{ ++ et_info_t *et; ++ struct chops *chops; ++ void *ch; ++ uint events = 0; ++ osl_t *osh; ++ ++ et = (et_info_t *)dev_id; ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ /* guard against shared interrupts */ ++ if (!et->etc->up) { ++ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); ++ goto done; ++ } ++ ++ /* get interrupt condition bits */ ++ events = (*chops->getintrevents)(ch, TRUE); ++ ++ /* not for us */ ++ if (!(events & INTR_NEW)) ++ goto done; ++ ++ ET_TRACE(("et%d: et_isr: events 0x%x\n", et->etc->unit, events)); ++ ET_LOG("et%d: et_isr: events 0x%x", et->etc->unit, events); ++ ++#ifdef CONFIG_IPROC_2STAGE_RX ++ if (events & INTR_RX) { ++ et->rxinisr = true; ++ /* process a few RX interrupts */ ++ et_rxevent(osh, et, chops, ch, 1); ++ ++ et->rxinisr = false; ++ /* get interrupt condition bits */ ++ events = (*chops->getintrevents)(ch, TRUE); ++ et->resched = FALSE; ++ ++ /* not for us */ ++ if (!(events & INTR_NEW)) ++ goto done; ++ } ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++ ++ /* disable interrupts */ ++ (*chops->intrsoff)(ch); ++ ++ /* save intstatus bits */ ++ ASSERT(et->events == 0); ++ et->events = events; ++ ++ ASSERT(et->resched == FALSE); ++ ++#ifdef NAPI2_POLL ++ ++ napi_schedule(&et->napi_poll); ++ ++#elif defined(NAPI_POLL) ++ /* allow the device to be added to the cpu polling list if we are up */ ++ if (netif_rx_schedule_prep(et->dev)) { ++ /* tell the network core that we have packets to send up */ ++ __netif_rx_schedule(et->dev); ++ } else { ++ ET_ERROR(("et%d: et_isr: intr while in poll!\n", ++ et->etc->unit)); ++ (*chops->intrson)(ch); ++ } ++#else /* ! NAPI_POLL && ! NAPI2_POLL */ ++ /* schedule dpc */ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++ schedule_work(&et->dpc_task.work); ++ } else ++#endif /* ET_ALL_PASSIVE */ ++ tasklet_schedule(&et->tasklet); ++#endif /* NAPI_POLL */ ++ ++done: ++ ET_LOG("et%d: et_isr ret", et->etc->unit, 0); ++ ++ return IRQ_RETVAL(events & INTR_NEW); ++} ++ ++#ifdef GMAC3 ++static struct net_device * BCMFASTPATH ++et_find_dev(struct sk_buff *skb) { ++ ++ /* ----------------------------------------------- */ ++ /* ----------------------------------------------- */ ++ ++ return NULL; ++} ++#endif /* GMAC3 */ ++ ++#ifdef PKTC ++static void BCMFASTPATH ++et_sendup_chain(et_info_t *et, void *h) ++{ ++ struct sk_buff *skb; ++ uint sz = PKTCCNT(h); ++ ++ ASSERT(h != NULL); ++ ASSERT((sz > 0) && (sz <= PKTCBND)); ++ ET_TRACE(("et%d: %s: sending up packet chain of sz %d\n", ++ et->etc->unit, __FUNCTION__, sz)); ++ et->etc->chained += sz; ++ et->etc->currchainsz = sz; ++ et->etc->maxchainsz = MAX(et->etc->maxchainsz, sz); ++ ++#ifdef GMAC3 ++ /* Forward chain directly to wl transmit */ ++ if (DEV_FWDER(et->etc)) { ++ struct net_device * dev; ++ ++ //skb = PKTTOFORWARD(et->etc->osh, h, sz); ++ skb = PKTTONATIVE(et->etc->osh, h); ++ skb->dev = et->dev; ++ ++ dev = et_find_dev(skb); ++ ++ if (fwder_transmit(skb, dev, et->fwdh, sz) == FWDER_FAILURE) { ++ PKTCFREE(et->etc->osh, skb, FALSE); ++ } ++ } ++ else ++ ASSERT(DEV_NTKIF(et->etc)); ++#else /* !GMAC3 */ ++ ++ skb = PKTTONATIVE(et->etc->osh, h); ++ skb->dev = et->dev; ++ ++ /* send up the packet chain */ ++ ctf_forward(et->cih, h, et->dev); ++#endif /* !GMAC3 */ ++ ++} ++#endif /* PKTC */ ++ ++static inline int ++et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota) ++{ ++ uint processed = 0; ++ void *p, *h = NULL, *t = NULL; ++ struct sk_buff *skb; ++#ifdef PKTC ++ pktc_data_t cd[PKTCMC] = {{0}}; ++ uint8 *evh, prio; ++ int32 i = 0, cidx = 0; ++#ifdef GMAC3 ++ bool chaining = DEV_FWDER(et->etc); ++#else /* !GMAC3 */ ++ bool chaining = PKTC_ENAB(et); ++#endif /* !GMAC3 */ ++#endif ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ if ( et->etc->rl_enabled ) ++ etc_check_rate_limiting(et->etc, ch); ++#endif /* GMAC_RATE_LIMITING */ ++ ++ /* read the buffers first */ ++ while ((p = (*chops->rx)(ch))) { ++#ifdef PKTC ++ ASSERT(PKTCLINK(p) == NULL); ++ evh = PKTDATA(et->osh, p) + HWRXOFF; ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) ++ prio = IP_TOS46(evh + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ else ++#endif /* GMAC3 */ ++ prio = IP_TOS46(evh + ETHERVLAN_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ if (cd[0].h_da == NULL) { ++ cd[0].h_da = evh; cd[0].h_sa = evh + ETHER_ADDR_LEN; ++ cd[0].h_prio = prio; ++ } ++ ++ /* if current frame doesn't match cached src/dest/prio or has err flags ++ * set then stop chaining. ++ */ ++ if (chaining) { ++ for (i = 0; i <= cidx; i++) { ++ if (PKT_CHAINABLE(et, p, evh, prio, cd[i].h_sa, ++ cd[i].h_da, cd[i].h_prio)) ++ break; ++ else if ((i + 1 < PKTCMC) && (cd[i + 1].h_da == NULL)) { ++ cidx++; ++ cd[cidx].h_da = evh; ++ cd[cidx].h_sa = evh + ETHER_ADDR_LEN; ++ cd[cidx].h_prio = prio; ++ } ++ } ++ chaining = (i < PKTCMC); ++ } ++ ++ if (chaining) { ++ PKTCENQTAIL(cd[i].chead, cd[i].ctail, p); ++ /* strip off rxhdr */ ++ PKTPULL(et->osh, p, HWRXOFF); ++ ++ et->etc->rxframe++; ++ et->etc->rxbyte += PKTLEN(et->osh, p); ++ ++ /* strip off crc32 */ ++ PKTSETLEN(et->osh, p, PKTLEN(et->osh, p) - ETHER_CRC_LEN); ++ ++#ifndef GMAC3 ++ /* update header for non-first frames */ ++ if (cd[i].chead != p) ++ CTF_HOTBRC_L2HDR_PREP(et->osh, et->brc_hot, prio, ++ PKTDATA(et->osh, p), p); ++#endif /* !GMAC3 */ ++ ++ PKTCINCRCNT(cd[i].chead); ++ PKTSETCHAINED(et->osh, p); ++ PKTCADDLEN(cd[i].chead, PKTLEN(et->osh, p)); ++ } else ++ PKTCENQTAIL(h, t, p); ++#else /* PKTC */ ++ PKTSETLINK(p, NULL); ++ if (t == NULL) ++ h = t = p; ++ else { ++ PKTSETLINK(t, p); ++ t = p; ++ } ++#endif /* PKTC */ ++ ++ /* we reached quota already */ ++ if (++processed >= quota) { ++ /* reschedule et_dpc()/et_poll() */ ++ et->resched = TRUE; ++ et->etc->rxquota++; ++ break; ++ } ++ } ++ ++ /* prefetch the headers */ ++ if (h != NULL) ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); ++#else ++ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); ++#endif ++ ++ /* post more rx bufs */ ++ (*chops->rxfill)(ch); ++ ++#ifdef PKTC ++ /* send up the chain(s) at one fell swoop */ ++ ASSERT(cidx < PKTCMC); ++ for (i = 0; i <= cidx; i++) { ++ if (cd[i].chead != NULL) { ++#ifdef GMAC3 ++ PKTSETPRIO(cd[i].chead, cd[i].h_prio); ++#endif ++ et_sendup_chain(et, cd[i].chead); ++ } ++ } ++#endif ++ ++ while ((p = h) != NULL) { ++#ifdef PKTC ++ h = PKTCLINK(h); ++ PKTSETCLINK(p, NULL); ++#else ++ h = PKTLINK(h); ++ PKTSETLINK(p, NULL); ++#endif ++ /* prefetch the headers */ ++ if (h != NULL) ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); ++#else ++ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); ++#endif ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ uint8 *evh1; ++ //skb = PKTTOFORWARD(osh, p, 1); ++ skb = PKTTONATIVE(osh, p); ++ evh1 = skb->data + HWRXOFF; ++ skb->priority = IPV4_TOS(evh1 + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ } else ++#endif ++ skb = PKTTONATIVE(osh, p); ++ et->etc->unchained++; ++ et_sendup(et, skb); ++ } ++ ++ return (processed); ++} ++ ++#if defined(NAPI2_POLL) ++static int BCMFASTPATH ++et_poll(struct napi_struct *napi, int budget) ++{ ++ int quota = budget; ++ struct net_device *dev = napi->dev; ++ et_info_t *et = ET_INFO(dev); ++ ++#elif defined(NAPI_POLL) ++static int BCMFASTPATH ++et_poll(struct net_device *dev, int *budget) ++{ ++ int quota = min(RXBND, *budget); ++ et_info_t *et = ET_INFO(dev); ++#else /* NAPI_POLL */ ++static void BCMFASTPATH ++et_dpc(ulong data) ++{ ++ et_info_t *et = (et_info_t *)data; ++ #ifndef GMAC3 ++ int quota = PKTC_ENAB(et) ? et->etc->pktcbnd : RXBND; ++ #else /* GMAC3 */ ++ int quota = PKTC_ENAB(et) ? et->etc->pktcbnd : RXBND; ++ #endif /* GMAC3 */ ++#endif /* NAPI_POLL */ ++ struct chops *chops; ++ void *ch; ++ osl_t *osh; ++ uint nrx = 0; ++ ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ ET_TRACE(("et%d: et_dpc: events 0x%x\n", et->etc->unit, et->events)); ++ ET_LOG("et%d: et_dpc: events 0x%x", et->etc->unit, et->events); ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ ET_LOCK(et); ++#endif /* ! NAPIx_POLL */ ++ ++ if (!et->etc->up) ++ goto done; ++ ++ /* get interrupt condition bits again when dpc was rescheduled */ ++ if (et->resched) { ++ et->events = (*chops->getintrevents)(ch, FALSE); ++ et->resched = FALSE; ++ } ++ ++ if (et->events & INTR_RX) ++ nrx = et_rxevent(osh, et, chops, ch, quota); ++ ++ if (et->events & INTR_TX) { ++ (*chops->txreclaim)(ch, FALSE); ++ } ++ ++ (*chops->rxfill)(ch); ++ ++ /* handle error conditions, if reset required leave interrupts off! */ ++ if (et->events & INTR_ERROR) { ++ if ((*chops->errors)(ch)) { ++ printk("%s error, calling et_init() for et%d\n", __FUNCTION__, et->etc->unit); ++ et_init(et, ET_INIT_INTROFF); ++ } ++ else ++ if (nrx < quota) ++ nrx += et_rxevent(osh, et, chops, ch, quota); ++ } ++ ++ /* run the tx queue */ ++ if (et->etc->txq_state != 0) { ++ if (!ET_ALL_PASSIVE_ENAB(et)) { ++ et_sendnext(et); ++ } ++#ifdef ET_ALL_PASSIVE ++ else ++ #ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++ #else ++ schedule_work(&et->txq_task.work); ++ #endif ++ ++#endif /* ET_ALL_PASSIVE */ ++ } ++ ++ /* clear this before re-enabling interrupts */ ++ et->events = 0; ++ ++ /* something may bring the driver down */ ++ if (!et->etc->up) { ++ et->resched = FALSE; ++ goto done; ++ } ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ #ifdef ET_ALL_PASSIVE ++ if (et->resched) { ++ if (!ET_ALL_PASSIVE_ENAB(et)) ++ tasklet_schedule(&et->tasklet); ++ else ++ schedule_work(&et->dpc_task.work); ++ } ++ else ++ (*chops->intrson)(ch); ++ #else /* ET_ALL_PASSIVE */ ++ /* there may be frames left, reschedule et_dpc() */ ++ if (et->resched) ++ tasklet_schedule(&et->tasklet); ++ /* re-enable interrupts */ ++ else ++ (*chops->intrson)(ch); ++ #endif /* ET_ALL_PASSIVE */ ++#endif /* ! NAPIx_POLL */ ++ ++done: ++ ET_LOG("et%d: et_dpc ret", et->etc->unit, 0); ++ ++#if defined(NAPI_POLL) || defined(NAPI2_POLL) ++ #ifdef NAPI_POLL ++ /* update number of frames processed */ ++ *budget -= nrx; ++ dev->quota -= nrx; ++ ++ ET_TRACE(("et%d: et_poll: quota %d budget %d\n", ++ et->etc->unit, dev->quota, *budget)); ++ #else ++ ET_TRACE(("et%d: et_poll: budget %d\n", ++ et->etc->unit, budget)); ++ #endif ++ ++ /* we got packets but no quota */ ++ if (et->resched) ++ /* indicate that we are not done, don't enable ++ * interrupts yet. linux network core will call ++ * us again. ++ */ ++ return (1); ++ ++ #ifdef NAPI2_POLL ++ napi_complete(napi); ++ #else /* NAPI_POLL */ ++ netif_rx_complete(dev); ++ #endif ++ ++ /* enable interrupts now */ ++ (*chops->intrson)(ch); ++ ++ /* indicate that we are done */ ++ return (0); ++#else /* NAPI_POLL */ ++ ET_UNLOCK(et); ++ return; ++#endif /* NAPI_POLL */ ++} ++ ++#ifdef ET_ALL_PASSIVE ++static void BCMFASTPATH ++et_dpc_work(struct et_task *task) ++{ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ et_info_t *et = (et_info_t *)task->context; ++ et_dpc((unsigned long)et); ++#else ++ BUG_ON(1); ++#endif ++ return; ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++static void ++et_error(et_info_t *et, struct sk_buff *skb, void *rxh) ++{ ++ uchar eabuf[32]; ++ struct ether_header *eh; ++ ++ eh = (struct ether_header *)skb->data; ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, eabuf); ++ ++ if (RXH_OVERSIZE(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: over size packet from %s\n", et->etc->unit, eabuf)); ++ } ++ if (RXH_CRC(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: crc error from %s\n", et->etc->unit, eabuf)); ++ } ++ if (RXH_OVF(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: fifo overflow\n", et->etc->unit)); ++ } ++ if (RXH_NO(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: crc error (odd nibbles) from %s\n", ++ et->etc->unit, eabuf)); ++ } ++ if (RXH_RXER(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: symbol error from %s\n", et->etc->unit, eabuf)); ++ } ++} ++ ++static inline int32 ++et_ctf_forward(et_info_t *et, struct sk_buff *skb) ++{ ++#ifdef HNDCTF ++ /* use slow path if ctf is disabled */ ++ if (!CTF_ENAB(et->cih)) ++ return (BCME_ERROR); ++ ++ /* try cut thru first */ ++ if (ctf_forward(et->cih, skb, skb->dev) != BCME_ERROR) ++ return (BCME_OK); ++ ++ /* clear skipct flag before sending up */ ++ PKTCLRSKIPCT(et->osh, skb); ++#endif /* HNDCTF */ ++ ++#ifdef CTFPOOL ++ /* allocate and add a new skb to the pkt pool */ ++ if (PKTISFAST(et->osh, skb)) ++ osl_ctfpool_add(et->osh); ++ ++ /* clear fast buf flag before sending up */ ++ PKTCLRFAST(et->osh, skb); ++ ++ /* re-init the hijacked field */ ++ CTFPOOLPTR(et->osh, skb) = NULL; ++#endif /* CTFPOOL */ ++ ++ /* map the unmapped buffer memory before sending up */ ++ PKTCTFMAP(et->osh, skb); ++ ++ return (BCME_ERROR); ++} ++ ++void BCMFASTPATH ++et_sendup(et_info_t *et, struct sk_buff *skb) ++{ ++ etc_info_t *etc; ++ void *rxh; ++ uint16 flags; ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++#if defined(CONFIG_IPROC_FA2) ++ uint32 rcv_sts_word; ++#endif ++ ++ etc = et->etc; ++ ++ /* packet buffer starts with rxhdr */ ++ rxh = skb->data; ++ ++#if defined(CONFIG_IPROC_FA2) ++ rcv_sts_word = LTOH32(*((uint32 *)skb->data)); ++#endif ++ /* strip off rxhdr */ ++ __skb_pull(skb, HWRXOFF); ++ ++ ET_TRACE(("et%d: et_sendup: %d bytes\n", et->etc->unit, skb->len)); ++ ET_LOG("et%d: et_sendup: len %d", et->etc->unit, skb->len); ++ ++ etc->rxframe++; ++ etc->rxbyte += skb->len; ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) ++ if (et_ctf_active(et)) { ++#if defined(CONFIG_IPROC_FA) ++ if(!gBypass) { ++ if (fc_receive(skb) == -1) ++ goto err; ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++#if defined(CONFIG_IPROC_FA2) ++ if(!gBypass) { ++ ++ /* If pipeline did not indicate error, proceed with rx processing */ ++ if (!(RXH_CTFERROR(etc, rxh))) { ++ if (fa2_receive(skb) == FA2_PKT_DONE) { ++ goto drop_pkt; ++ } ++ } else { ++ /* ++ printk(KERN_DEBUG "\n=== rxstsword is 0x%08X\n", ++ rcv_sts_word); ++ */ ++ } ++ } ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ ++ /* remove brcm tag */ ++ ET_TRACE(("Removing BRCM TAG\n")); ++ /* size depends on egress tag opcode */ ++ switch ((skb->data[0] & 0xe0) >> 5) { ++ case 0: ++ case 1: ++ case 2: ++ skb_pull(skb, 4); ++ break; ++ case 3: ++ skb_pull(skb, 8); ++ break; ++ } ++ } ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) */ ++ ++ /* eh should now be aligned 2-mod-4 */ ++ ASSERT(((ulong)skb->data & 3) == 2); ++ ++ /* strip off crc32 */ ++ __skb_trim(skb, skb->len - ETHER_CRC_LEN); ++ ++ ET_PRHDR("rx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("rxpkt", skb->data, skb->len, etc->unit); ++#ifdef PRINT_PKT_SUM ++ printk("et%d: rxpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, ++ skb->data[12], skb->data[13], skb->data[14], skb->data[15]); ++#endif /* PRINT_PKT_SUM */ ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) rxpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ ++ /* get the error flags */ ++ flags = RXH_FLAGS(etc, rxh); ++ ++ /* check for reported frame errors */ ++ if (flags) ++ goto err; ++ ++ skb->dev = et->dev; ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ struct net_device * dev = et_find_dev(skb); ++ ++ if (fwder_transmit(skb, dev, et->fwdh, 1) == FWDER_FAILURE) { ++ PKTFRMNATIVE(etc->osh, skb); ++ PKTFREE(etc->osh, skb, FALSE); ++ } ++ return; ++ } ++#endif /* !GMAC3 */ ++ ++#ifdef HNDCTF ++ /* try cut thru' before sending up */ ++ if (et_ctf_forward(et, skb) != BCME_ERROR) ++ return; ++#endif /* HNDCTF */ ++ ++ ASSERT(!PKTISCHAINED(skb)); ++ ++ /* extract priority from payload and store it out-of-band ++ * in skb->priority ++ */ ++ if (et->etc->qos) ++ pktsetprio(skb, TRUE); ++ ++ skb->protocol = eth_type_trans(skb, et->dev); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ { ++ struct sk_buff *next = skb->next; ++ while (1) { ++ if (next != NULL) { ++ ++ prefetch_range(next, SKB_PREFETCH_LEN); ++ next = next->next; ++ } else { ++ break; ++ } ++ } ++ } ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif ++ ++ /* send it up */ ++#if defined(NAPI_POLL) || defined(NAPI2_POLL) ++#ifdef CONFIG_IPROC_2STAGE_RX ++ if (!et->rxinisr) ++ netif_receive_skb(skb); ++ else ++ netif_rx(skb); ++#else /* CONFIG_IPROC_2STAGE_RX */ ++ if (et->dev->features & NETIF_F_GRO) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { ++ skb = vlan_untag(skb); ++ if (unlikely(!skb)) { ++ goto err; ++ } ++ } ++ napi_gro_receive(&et->napi_poll, skb); ++ } else { ++ netif_receive_skb(skb); ++ } ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++ ++#else /* NAPI_POLL */ ++ netif_rx(skb); ++#endif /* NAPI_POLL */ ++ ++ ET_LOG("et%d: et_sendup ret", et->etc->unit, 0); ++ ++ return; ++ ++err: ++ et_error(et, skb, rxh); ++ ++#if defined(CONFIG_IPROC_FA2) ++drop_pkt: ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ PKTFRMNATIVE(etc->osh, skb); ++ PKTFREE(etc->osh, skb, FALSE); ++ ++ return; ++} ++ ++#ifdef HNDCTF ++void ++et_dump_ctf(et_info_t *et, struct bcmstrbuf *b) ++{ ++ ctf_dump(et->cih, b); ++} ++#endif ++ ++void ++et_dump(et_info_t *et, struct bcmstrbuf *b) ++{ ++ bcm_bprintf(b, "et%d: %s %s version %s\n", et->etc->unit, ++ __DATE__, __TIME__, EPI_VERSION_STR); ++ ++#ifdef HNDCTF ++#if defined(BCMDBG) ++ ctf_dump(et->cih, b); ++#endif ++#endif /* HNDCTF */ ++ ++ et_dumpet(et, b); ++ etc_dump(et->etc, b); ++ ++ bcm_bprintf(b, "txdfrm(%d); txdfrmropped(%d); txqlen(%d); txqstop(%d); txdmafull(%d) txmaxlen(%d) txsgpkt(%d)\n", ++ et->etc->txfrm, et->etc->txfrmdropped, et->etc->txqlen, et->etc->txqstop, et->etc->txdmafull, ++ et->etc->txmaxlen, et->etc->txsgpkt); ++ et->etc->txfrm=0; ++ et->etc->txfrmdropped=0; ++ et->etc->txqlen=0; ++ et->etc->txqstop=0; ++ et->etc->txdmafull=0; ++ et->etc->txmaxlen=0; ++ et->etc->txsgpkt=0; ++ ++ bcm_bprintf(b, "rxquota(%d); rxdmastopped(%d)\n", ++ et->etc->rxquota, et->etc->rxdmastopped); ++ et->etc->rxquota=0; ++ et->etc->rxdmastopped=0; ++#ifdef GMAC_RATE_LIMITING ++ bcm_bprintf(b, "rxd_dropped_packets(%d)\n", ++ et->etc->rl_dropped_packets); ++ et->etc->rl_dropped_packets=0; ++#endif /* GMAC_RATE_LIMITING */ ++ ++} ++ ++static void ++et_dumpet(et_info_t *et, struct bcmstrbuf *b) ++{ ++ bcm_bprintf(b, "et %p dev %p name %s tbusy %d txq[0].qlen %d malloced %d\n", ++ et, et->dev, et->dev->name, (uint)netif_queue_stopped(et->dev), et->txq[0].qlen, ++ MALLOCED(et->osh)); ++} ++ ++void ++et_link_up(et_info_t *et) ++{ ++ ET_ERROR(("et%d: link up (%d%s)\n", ++ et->etc->unit, et->etc->speed, (et->etc->duplex? "FD" : "HD"))); ++ printf("et%d Link Up: %d%s\n", et->etc->unit, et->etc->speed, et->etc->duplex?"FD":"HD"); ++ netif_carrier_on(et->dev); ++} ++ ++void ++et_link_down(et_info_t *et) ++{ ++ ET_ERROR(("et%d: link down\n", et->etc->unit)); ++ printf("et%d Link Down\n", et->etc->unit); ++ netif_carrier_off(et->dev); ++} ++ ++bool ++et_is_link_up(et_info_t *et) ++{ ++ return netif_carrier_ok(et->dev); ++} ++ ++int ++et_enable_device( uint idx ) ++{ ++ ulong flags; ++ uint coreidx, coreid; ++ int rc = -1; ++ ++ spin_lock_irqsave(&sih_lock, flags); ++ ++ si_setcore(sih, GMAC_CORE_ID, idx); ++ coreidx = si_coreidx(sih); ++ coreid = si_coreid(sih); ++ ++ //printk("%s coreidx(0x%x) coreid(0x%x)\n", __FUNCTION__, coreidx, coreid); ++ /* 2G_ENABLED: Enable IDM 250MHz for 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ si_core_reset(sih, 0x44, 0); ++#else ++ si_core_reset(sih, 0, 0); ++#endif ++ ++ /* Initialize USBHC core OK */ ++ rc = 0; ++ ++ si_setcoreidx(sih, coreidx); ++ spin_unlock_irqrestore(&sih_lock, flags); ++ ++ return rc; ++} ++ ++ ++/********************************************************************** ++ * bcm5301x_gmac_probe(device) ++ * ++ * The Platform Driver Probe function. ++ * ++ * Input parameters: ++ * device: The Device Context ++ * ++ * Return value: ++ * 0: Driver Probe is Succesful ++ * not 0: ERROR ++ **********************************************************************/ ++static int bcm5301x_gmac_probe(struct platform_device* pldev) ++{ ++ struct net_device *dev = NULL; ++ void __iomem *macbase = NULL; ++ struct resource *memres = NULL; ++ struct resource *irqres = NULL; ++ osl_t *osh = NULL; ++ et_info_t *et = NULL; ++ int unit = et_found; ++ int err = 0; ++ char name[128]; ++ int i; ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ char *var; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++ printk("%s enter name:%s; id:0x%x; unit:%d\n", __FUNCTION__, pldev->name, pldev->id, unit); ++ ++ /*Validation of platform device structure*/ ++ if (!pldev) { ++ ET_ERROR(("WRONG INPUT\nplatfrom_device ppointer should not be NULL.\n")); ++ return -EINVAL; ++ } ++ ++ et_found++; ++ ++ /* pre-qualify et unit, that can save the effort to do et_detach */ ++ ++ nvram_env_gmac_name(unit, name); ++ if (getvar(NULL, name) == NULL) { ++ printk("et%d: %s not found, ignore it\n", unit, name); ++ return -ENODEV; ++ } ++ ++ osh = osl_attach(pldev, PCI_BUS, FALSE); ++ ASSERT(osh); ++ ++ /* Get global SB handle */ ++ sih = si_kattach(SI_OSH); ++ ++ /* reset core */ ++ et_enable_device(unit); ++ ++ ET_TRACE(("%s call alloc_etherdev\n", __FUNCTION__)); ++ if ((dev = alloc_etherdev(sizeof( et_info_t ))) == NULL) { ++ ET_ERROR(("%s: alloc_etherdev() failed\n", __FUNCTION__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ et = ET_INFO(dev); ++ bzero(et, sizeof(et_info_t)); /* Is this needed in 2.6.36 ? -LR */ ++ et->dev = dev; ++ et->osh = osh; ++ ++ ET_TRACE(("%s get resources\n", __FUNCTION__)); ++ memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); ++ if (NULL == memres) { ++ ET_ERROR(("ERROR: Could not get Platform Resource MAC Register Memory Resurce\n")); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ if (!request_mem_region(memres->start, (memres->end - memres->start + 1), pldev->name)) { ++ ET_ERROR(("ERROR: Could not request mem region. In file %s, LN:%d\n", ++ __FILE__, __LINE__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0); ++ if (NULL == irqres) { ++ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register IRQ Resource\n")); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ dev->base_addr = memres->start; ++ dev->irq = irqres->start; ++ ++ printk("et%d: base_addr (0x%x) irq (%d)\n", unit, (uint32)dev->base_addr, dev->irq); ++ ++// if ((et->regsva = ioremap_nocache(dev->base_addr, PCI_BAR0_WINSZ)) == NULL) { ++ if ((et->regsva = ioremap_nocache(dev->base_addr, 0xc00)) == NULL) { ++ ET_ERROR(("et%d: ioremap() failed\n", unit)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ET_TRACE(("%s base_addr: 0x%x; regsva:0x%x\n", __FUNCTION__, (uint32)dev->base_addr, (uint32)et->regsva)); ++ ++ pldev->id = dev->base_addr; ++ dev_set_drvdata(&(pldev->dev), dev); ++ SET_NETDEV_DEV(dev, (&pldev->dev)); ++ ++ init_MUTEX(&et->sem); ++ spin_lock_init(&et->lock); ++ spin_lock_init(&et->txq_lock); ++ spin_lock_init(&et->tx_lock); ++ spin_lock_init(&et->isr_lock); ++ ++ for (i = 0; i < NUMTXQ; i++) ++ skb_queue_head_init(&et->txq[i]); ++ ++ /* common load-time initialization */ ++ et->etc = etc_attach((void *)et, VENDOR_BROADCOM, BCMIPROC_CHIP_ID, unit, osh, et->regsva); ++ if (et->etc == NULL) { ++ ET_ERROR(("et%d: etc_attach() failed\n", unit)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++#ifdef GMAC3 ++ et->fwdh = (fwder_t *)NULL; /* attached/dettached on et up/dn */ ++ /* The ethernet network interface uses "eth0". Use fwd0, fwd1 instead */ ++ if (DEV_FWDER(et->etc)) ++ strncpy(dev->name, DEV_FWDER_NAME, 3); ++ ++#endif /* GMAC3 */ ++ ++#ifdef HNDCTF ++ et->cih = ctf_attach(osh, dev->name, &et_msg_level, et_ctf_detach, et); ++ ++ if(et->cih) ++ { ++ printk("%s: et->cih not NULL \n", __FUNCTION__); ++ } ++ else ++ { ++ printk("%s: et->cih is NULL \n", __FUNCTION__); ++ } ++ printk("%s: CTF_ENAB(ci) = %d \n", __FUNCTION__, (CTF_ENAB(et->cih) ? 1 : 0)); ++ if (ctf_dev_register(et->cih, dev, FALSE) != BCME_OK) { ++ ET_ERROR(("et%d: ctf_dev_register() failed\n", unit)); ++ goto Exit; ++ } ++#endif /* HNDCTF */ ++ ++#ifdef CTFPOOL ++ /* create ctf packet pool with specified number of buffers */ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++if ((osl_ctfpool_init(unit, osh, CTFPOOLSZ, RXBUFSZ+BCMEXTRAHDROOM) < 0)) { ++ ET_ERROR(("et%d: chipattach: ctfpool alloc/init failed\n", unit)); ++ goto Exit; ++ } else { ++ printk("\net%d: chipattach: ctfpool alloc/init successful\n", unit); ++ } ++#else ++ if (CTF_ENAB(et->cih)) { ++ uint32 poolsz; ++ /* use large ctf poolsz for platforms with more memory */ ++ poolsz = ((num_physpages >= 32767) ? CTFPOOLSZ * 2 : ++ ((num_physpages >= 8192) ? CTFPOOLSZ : 0)); ++ if ((poolsz > 0) && ++ (osl_ctfpool_init(osh, poolsz, RXBUFSZ+BCMEXTRAHDROOM) < 0)) { ++ ET_ERROR(("et%d: chipattach: ctfpool alloc/init failed\n", unit)); ++ goto Exit; ++ } else { ++ printk("\net%d: chipattach: ctfpool alloc/init successful\n", unit); ++ } ++ } ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif /* CTFPOOL */ ++ ++ bcopy(&et->etc->cur_etheraddr, dev->dev_addr, ETHER_ADDR_LEN); ++ ++ /* init 1 second watchdog timer */ ++ init_timer(&et->timer); ++ et->timer.data = (ulong)dev; ++ et->timer.function = et_watchdog; ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ /* schedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set = TRUE; ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++#ifdef GMAC_RATE_LIMITING ++ /* init 1 second watchdog timer */ ++ init_timer(&et->etc->rl_timer); ++ et->etc->rl_timer.data = (ulong)dev; ++ et->etc->rl_timer.function = et_release_congestion; ++#endif /* GMAC_RATE_LIMITING */ ++ ++#ifdef NAPI2_POLL ++ netif_napi_add(dev, & et->napi_poll, et_poll, 64); ++ napi_enable(&et->napi_poll); ++#endif /* NAPI2_POLL */ ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ /* setup the bottom half handler */ ++ tasklet_init(&et->tasklet, et_dpc, (ulong)et); ++#endif /* NAPI_POLL */ ++ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++ MY_INIT_WORK(&et->dpc_task.work, (work_func_t)et_dpc_work); ++ et->dpc_task.context = et; ++ MY_INIT_WORK(&et->txq_task.work, (work_func_t)et_txq_work); ++ et->txq_task.context = et; ++ } ++ if (et_ctf_pipeline_loopback(et)) { ++ et->all_dispatch_mode = FALSE; ++ } else { ++ et->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE; ++ } ++#endif /* ET_ALL_PASSIVE */ ++ ++ ET_TRACE(("%s request irq\n", __FUNCTION__)); ++ /* register our interrupt handler */ ++ if (request_irq(dev->irq, et_isr, IRQF_SHARED, dev->name, et)) { ++ ET_ERROR(("%s: request_irq(%d) failed\n", __FUNCTION__, dev->irq)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ /* add us to the global linked list */ ++ et->next = et_list; ++ et_list = et; ++ ++#ifndef HAVE_NET_DEVICE_OPS ++ /* lastly, enable our entry points */ ++ dev->open = et_open; ++ dev->stop = et_close; ++ dev->hard_start_xmit = et_start; ++ dev->get_stats = et_get_stats; ++ dev->set_mac_address = et_set_mac_address; ++ dev->set_multicast_list = et_set_multicast_list; ++ dev->do_ioctl = et_ioctl; ++#ifdef NAPI_POLL ++ dev->poll = et_poll; ++ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); ++#endif /* NAPI_POLL */ ++#else /* HAVE_NET_DEVICE_OPS */ ++ /* Linux 2.6.36 and up. - LR */ ++ dev->netdev_ops = &et_netdev_ops ; ++#ifdef NAPI_POLL ++ dev->poll = et_poll; ++ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); ++#endif /* NAPI_POLL */ ++ ++#endif /* !HAVE_NET_DEVICE_OPS */ ++ ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++ if (et->etc->unit == 2) { ++ dev->features = (NETIF_F_IP_CSUM); ++ //dev->features = (NETIF_F_IP_CSUM | NETIF_F_SG); ++ //dev->hw_features = dev->features; ++ dev->vlan_features = (NETIF_F_IP_CSUM); ++ printk("\n Enabling checksum offload ...\n"); ++ } ++#endif /* CONFIG_IPROC_FA2 && CONFIG_IPROC_FA2_CS_OFFLOAD */ ++ ++#if defined(BCMDMASGLISTOSL) ++#ifdef CONFIG_BCM_GRO_ENABLE ++ dev->features = (NETIF_F_GRO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ dev->vlan_features = (NETIF_F_GRO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ printk("et%d: Enable Checksum-SG-GRO\n", unit); ++#else ++ dev->features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ dev->vlan_features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ printk("et%d: Enable Checksum-SG\n", unit); ++#endif ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ dev->ethtool_ops = &et_ethtool_ops; ++#endif ++ ++ /* Assign netdev name consistently, even if GMAC0 or 1 is disabled */ ++ { ++ unsigned char devname[8] = {0}; ++ snprintf(devname, 8, "eth%d", unit); ++ dev_alloc_name(dev, devname); ++ } ++ ++ ET_TRACE(("%s register netdev\n", __FUNCTION__)); ++ if (register_netdev(dev)) { ++ ET_ERROR(("%s register_netdev() failed\n", __FUNCTION__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ET_LOCK(et); ++ et->etc->linkstate = FALSE; ++ et_link_down(et); ++ ET_UNLOCK(et); ++ ++ /* print hello string */ ++ (*et->etc->chops->longname)(et->etc->ch, name, sizeof(name)); ++ printk("%s: %s %s\n", dev->name, name, EPI_VERSION_STR); ++ ++ eth_mac_proc_create(dev); ++ ++#ifdef HNDCTF ++ if (ctf_enable(et->cih, dev, TRUE, &et->brc_hot) != BCME_OK) { ++ ET_ERROR(("et%d: ctf_enable() failed\n", unit)); ++ goto Exit; ++ } ++#endif ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ /* check if brcm tag is turned off */ ++ var = getvar(NULL, "brcmtag"); ++ if (var) { ++ int tag = bcm_strtoul(var, NULL, 0); ++ if (tag==0) { ++ ET_ERROR(("BRCM TAG disabled\n")); ++ brcm_tag = false; ++ } ++ } ++ printk("BRCM TAG %sabled\n", brcm_tag?"en":"dis"); ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ printk("et_ctf_active %sabled\n", et_ctf_active(et)?"en":"dis"); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++ ++Exit: ++ if (macbase) { ++ iounmap(macbase); ++ macbase=NULL; ++ } ++ if (memres) { ++ release_mem_region(memres->start, (memres->end - memres->start + 1)); ++ memres=NULL; ++ } ++ if (dev) { ++ free_netdev(dev); ++ dev = NULL; ++ } ++ if (osh) { ++ osl_detach(osh); ++ osh=NULL; ++ } ++ if (et) { ++ etc_detach(et->etc); ++ et->dev = NULL; ++ et->osh = NULL; ++ et_free(et); ++ et=NULL; ++ } ++ return err; ++} ++ ++ ++/********************************************************************** ++ * bcm5301x_gmac_remove(device) ++ * ++ * The Removal of Platform Device, and un-initialize the previously ++ * added MAC, and it's MEM Regions and Resources. ++ * ++ * Input parameters: ++ * device: The Device Context ++ * ++ * Return value: ++ * 0: Driver Entry is Succesfull ++ **********************************************************************/ ++static int __exit bcm5301x_gmac_remove(struct platform_device *pldev) ++{ ++ struct net_device *dev = platform_get_drvdata(pldev); ++ int retVal = 0; ++ et_info_t *et = NULL; ++ struct resource *memres = NULL; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++#ifdef CONFIG_PM ++ bcm5301x_gmac_drv_suspend(pldev, PMSG_SUSPEND); ++#endif ++ ++ et = ET_INFO(dev); ++ ++ iounmap(et->regsva); ++ unregister_netdev(dev); ++ ++ memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); ++ if (memres) { ++ release_mem_region(memres->start, (memres->end - memres->start + 1)); ++ } else { ++ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register Memory Resource\n")); ++ retVal = -ENOMEM; ++ } ++ ++ free_netdev(dev); ++ ++ et->dev = NULL; ++ et_free(et); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return retVal; ++} ++ ++#ifdef CONFIG_PM ++static int bcm5301x_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ int ret; ++ char *filename = "/usr/sbin/ifdown"; ++ char *argv[] = {filename, "eth0", NULL}; ++ char *envp[] = {"HOME=/", ++ "TERM=linux", ++ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", ++ NULL}; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++} ++ ++static int bcm5301x_gmac_drv_resume(struct platform_device *pdev) ++{ ++ int ret; ++ char *filename = "/usr/sbin/ifup"; ++ char *argv[] = {filename, "eth0", NULL}; ++ char *envp[] = {"HOME=/", ++ "TERM=linux", ++ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", ++ NULL}; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++} ++#else ++#define bcm5301x_gmac_drv_suspend NULL ++#define bcm5301x_gmac_drv_resume NULL ++#endif ++ ++/********************************************************************** ++ * GMAC0 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac0_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac0_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC0 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac0_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac0_pdev = { ++ .name = bcm5301x_gmac0_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac0_string, ++ .dma_mask = &gmac0_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac0_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac0_resources), ++}; ++ ++/********************************************************************** ++ * GMAC1 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac1_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac1_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC1 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac1_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac1_pdev = { ++ .name = bcm5301x_gmac1_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac1_string, ++ .dma_mask = &gmac1_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac1_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac1_resources), ++}; ++ ++/********************************************************************** ++ * GMAC2 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac2_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac2_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC2 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac2_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac2_pdev = { ++ .name = bcm5301x_gmac2_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac2_string, ++ .dma_mask = &gmac2_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac2_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac2_resources), ++}; ++ ++/********************************************************************** ++ * GMAC3 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac3_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac3_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC3 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac3_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac3_pdev = { ++ .name = bcm5301x_gmac3_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac3_string, ++ .dma_mask = &gmac3_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac3_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac3_resources), ++}; ++ ++/********************************************************************** ++ * This function calls the device structure. ++ * Input Parameter: ++ * dev - pointer to the struct device ++ **********************************************************************/ ++ ++static void bcm5301x_gmac_release (struct device *dev) {} ++ ++/********************************************************************** ++ * bcm5301x_gmac_init_module(VOID) ++ * ++ * The Driver Entry Function ++ * ++ * Input parameters: ++ * None ++ * ++ * Return value: ++ * 0: Driver Entry is Succesful ++ * not 0: ERROR ++ **********************************************************************/ ++static int __init ++bcm5301x_gmac_init_module(void) ++{ ++ int err = -1; ++ int deverr = -1; ++ int idx; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ ++ spin_lock_init(&sih_lock); ++ ++#if defined(BCMDBG) ++ if (msglevel != 0xdeadbeef) ++ et_msg_level = msglevel; ++ else { ++ char *var = getvar(NULL, "et_msglevel"); ++ if (var) ++ et_msg_level = bcm_strtoul(var, NULL, 0); ++ } ++ ++ printk("%s: msglevel set to 0x%x\n", __FUNCTION__, et_msg_level); ++#endif /* defined(BCMDBG) */ ++ ++#ifdef ET_ALL_PASSIVE ++ { ++ char *var = getvar(NULL, "et_dispatch_mode"); ++ if (var) ++ passivemode = bcm_strtoul(var, NULL, 0); ++ printk("%s: passivemode set to 0x%x\n", __FUNCTION__, passivemode); ++ } ++#endif /* ET_ALL_PASSIVE */ ++#ifdef NAPI_POLL ++ printk("%s: NAPI_POLL mode\n", __FUNCTION__); ++#endif /* NAPI_POLL */ ++#ifdef NAPI2_POLL ++ printk("%s: NAPI2_POLL mode\n", __FUNCTION__); ++#endif /* NAPI2_POLL */ ++ ++#ifdef ET_LIMIT_TXQ ++ { ++ char *var = getvar(NULL, "et_txq_thresh"); ++ if (var) ++ et_txq_thresh = bcm_strtoul(var, NULL, 0); ++ printk("%s: et_txq_thresh set to 0x%x\n", __FUNCTION__, et_txq_thresh); ++ } ++#endif /* ET_LIMIT_TXQ */ ++#ifdef GMAC_RATE_LIMITING ++ { ++ char *var = getvar(NULL, "et_rx_rate_limit"); ++ if (var) ++ et_rx_rate_limit = bcm_strtoul(var, NULL, 0); ++ printk("%s: et_rx_rate_limit set to 0x%x\n", __FUNCTION__, et_rx_rate_limit); ++ } ++#endif /* GMAC_RATE_LIMITING */ ++ ++#ifdef GMAC3 ++ fwder_init(); ++ /* fwder_dump_all(); */ ++#endif /* GMAC3 */ ++ ++ /* keep track of which ones loaded */ ++ for (idx=0; idx1) { ++ /* load GMAC1 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac1_driver); ++ if (!err) { ++ /* load GMAC1 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac1_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac1_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[1] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>2) { ++ /* load GMAC2 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac2_driver); ++ if (!err) { ++ /* load GMAC2 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac2_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac2_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[2] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>3) { ++ /* load GMAC3 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac3_driver); ++ if (!err) { ++ /* load GMAC3 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac3_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac3_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[3] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return deverr; ++} ++ ++/********************************************************************** ++ * bcm5301x_gmac_cleanup_module(VOID) ++ * ++ * The Driver Exit Function ++ * ++ * Input parameters: ++ * None ++ * ++ * Return value: ++ * Nothing ++ **********************************************************************/ ++static void __exit ++bcm5301x_gmac_cleanup_module(void) ++{ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++ if ( gmac_pdev_loaded[0] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac0_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac0_driver); ++ } ++ ++ if (IPROC_NUM_GMACS>1) { ++ if ( gmac_pdev_loaded[1] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac1_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac1_driver); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>2) { ++ if ( gmac_pdev_loaded[2] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac2_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac2_driver); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>3) { ++ if ( gmac_pdev_loaded[3] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac3_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac3_driver); ++ } ++ } ++ ++ //clean up the proc directory ++ eth_mac_proc_remove(); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return; ++} ++ ++static int get_fa_bypass(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ unsigned int len=0; ++ len += sprintf(page+len, "\n\n## Current FA Bypass setting = 0x%x, %s ##\n\n",gBypass, gBypass?"enabled":"disabled"); ++ *eof = 1; ++ return len; ++} ++ ++static int set_fa_bypass(struct file *file, const char *buffer, unsigned long count, void *data) ++{ ++ unsigned int len=1; ++ unsigned char debug_buffer[2]; ++ int bypass =0; ++ ++ //printk("count %x ## \n\n",(unsigned int) count); ++ if (count != 2) ++ { ++ ET_ERROR(("Please pass (one:1) digit FA bypass value only, 0=disable FA bypass, 1 = enable FA bypass\n")); ++ return -EINVAL; ++ } ++ ++ // Last buffer byte will be LF or CR only ++ if(copy_from_user(&debug_buffer[0], buffer, len)) ++ { ++ ET_ERROR(("Problem in copying invalid user buffer\n")); ++ return -EFAULT; ++ } ++ ++ debug_buffer[len]='\0'; // Only one byte value is available now ++ if ( sscanf(debug_buffer,"%d",&bypass) != 1) ++ { ++ ET_ERROR(("\n##Invalid value :%s: is passed ##\n",debug_buffer)); ++ return -EINVAL; ++ } ++ if (!((bypass >=DISABLE_FA_BYPASS) && (bypass <= ENABLE_FA_BYPASS))) ++ { ++ ET_ERROR(("\n##Passed value :%d: is not in valid range %d-%d \n",bypass,DISABLE_FA_BYPASS,ENABLE_FA_BYPASS)); ++ return -EINVAL; ++ } ++ ET_TRACE(("\n##set_fa_bypass(): Previous: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); ++ gBypass = bypass; ++ ET_TRACE(("\n##set_fa_bypass(): New: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); ++ return count; ++} ++ ++ ++static char* bcm5301x_eth_proc_root="bcm5301x_eth"; ++static struct proc_dir_entry *bcm5301x_eth_root_dir ; // BCM5892 eth proc root directory ++ ++static int eth_mac_proc_create(struct net_device *dev ) ++{ ++ struct proc_dir_entry *dent, *ent; ++ et_info_t *et; ++ etc_info_t *etc; ++ char fname[32]; ++ ++ et = ET_INFO(dev); ++ if (et != NULL) { ++ etc = et->etc; ++ } ++ ++ if ((et == NULL) || (etc == NULL)) { ++ printk("%s: error: Unit probably not initialized by probe function." ++ " et=0x%pm etc=0x%p\n", __FUNCTION__, et, etc); ++ return -1; ++ } ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++ snprintf(fname, 32, "%s%u", bcm5301x_eth_proc_root, etc->unit); ++ ++ dent = proc_mkdir(fname,bcm5301x_eth_root_dir); ++ if (dent) { ++ /* unit 2 has FA connectivity, create bypass path only for unit 2 */ ++ if (etc->unit == 2) { ++ printk("\nCreating fa bypass proc entry\n"); ++ ++ ent = create_proc_entry("fa_bypass", S_IFREG|S_IRUGO, dent); ++ if (ent) { ++ ent->read_proc = get_fa_bypass; ++ ent->write_proc = set_fa_bypass; ++ } ++ else { ++ printk("Error creating proc_entry, returning\n"); ++ return -1; ++ } ++ } ++ } ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return 0; ++} ++ ++static void eth_mac_proc_remove(void) ++{ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ remove_proc_entry(bcm5301x_eth_proc_root,NULL); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++} ++ ++ ++#if defined(CONFIG_IPROC_FA2) ++int et_fa2_spu_tx(struct sk_buff *skb) ++{ ++ struct net_device *dev = platform_get_drvdata(&bcm5301x_gmac3_pdev); ++ return et_start(skb, dev); ++} ++ ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++static et_info_t *et_get_eth3_info() ++{ ++ et_info_t *et; ++ struct net_device *d = platform_get_drvdata(&bcm5301x_gmac3_pdev); ++ ++ et = ET_INFO(d); ++ ++ if (et == NULL) { ++ printk(KERN_INFO "\net for dev3 is NULL, using dev2\n"); ++ // NOTEet = ET_INFO(dev); ++ ++ } ++ ++ return(et); ++} ++#endif /* CONFIG_IPROC_FA2_CS_OFFLOAD */ ++#endif /* CONFIG_IPROC_FA2 */ ++ ++ ++module_init(bcm5301x_gmac_init_module); ++module_exit(bcm5301x_gmac_cleanup_module); ++ ++MODULE_DESCRIPTION("Broadcom Northstar Ethernet Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h +new file mode 100755 +index 0000000..68b4de8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch new file mode 100644 index 00000000..a9a5e0ea --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch @@ -0,0 +1,74 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux device driver tunables for ++ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver ++ * ++ * $Id: et_linux.h 320789 2012-03-13 04:01:27Z $ ++ */ ++ ++#ifndef _et_linux_h_ ++#define _et_linux_h_ ++ ++/* tunables */ ++#define NTXD 512 /* # tx dma ring descriptors (must be ^2) */ ++#define NRXD 512 /* # rx dma ring descriptors (must be ^2) */ ++#if defined(CONFIG_RAM_SIZE) && (CONFIG_RAM_SIZE <= 16) ++#define NRXBUFPOST 256 /* try to keep this # rbufs posted to the chip */ ++#else ++#define NRXBUFPOST 420 /* try to keep this # rbufs posted to the chip */ ++#endif ++#ifdef CONFIG_JUMBO_FRAME ++#define BCM_ETHER_MAX_LEN 2500 ++#else ++#define BCM_ETHER_MAX_LEN 1518 //ETHER_MAX_LEN (1518) ++#endif /* CONFIG_JUMBO_FRAME */ ++#define RXBUFSZ (BCM_ETHER_MAX_LEN + HWRXOFF + BCMEXTRAHDROOM) /* receive buffer size */ ++ ++#ifndef RXBND ++#define RXBND 64 //32 /* max # rx frames to process in dpc */ ++#endif ++ ++#if defined(ILSIM) || defined(__arch_um__) ++#undef NTXD ++#define NTXD 16 ++#undef NRXD ++#define NRXD 16 ++#undef NRXBUFPOST ++#define NRXBUFPOST 2 ++#endif ++ ++#define PKTCBND 48 ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define CTFPOOLSZ (2048) ++#else ++#define CTFPOOLSZ 768 ++#endif ++ ++#define PREFSZ 96 ++#ifndef PKTC ++#define ETPREFHDRS(h, sz) OSL_PREF_RANGE_ST((h), (sz)) ++#else ++#define ETPREFHDRS(h, sz) ++#endif ++ ++#endif /* _et_linux_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etc.c b/drivers/bcmdrivers/gmac/src/et/sys/etc.c +new file mode 100755 +index 0000000..a356421 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch new file mode 100644 index 00000000..7420f10a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch @@ -0,0 +1,905 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etc.c +@@ -0,0 +1,899 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Common [OS-independent] portion of ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Device Driver. ++ * ++ * $Id: etc.c 323634 2012-03-26 10:26:11Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef ETROBO ++#ifndef _siutils_h_ ++typedef const struct si_pub si_t; ++#endif ++#include ++#endif /* ETROBO */ ++ ++uint32 et_msg_level = ++#ifdef BCMDBG ++ 1; ++#else ++ 0; ++#endif /* BCMDBG */ ++ ++uint8 ethup=0; ++uint8 ethupmask=0; ++etc_info_t *ethupetcptr[IPROC_NUM_GMACS]; ++ ++/* local prototypes */ ++static void etc_loopback(etc_info_t *etc, int on); ++static void etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b); ++int etc_gmac_speed(int gmac); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++extern void gmac_set_amac_mdio(int en); ++extern int gmac_has_mdio_access(void); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++void gmac_serdes_asym_mode(etc_info_t *etcptrs[]); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++ ++/* 802.1d priority to traffic class mapping. queues correspond one-to-one ++ * with traffic classes. ++ */ ++uint32 up2tc[NUMPRIO] = { ++ TC_BE, /* 0 BE TC_BE Best Effort */ ++ TC_BK, /* 1 BK TC_BK Background */ ++ TC_BK, /* 2 -- TC_BK Background */ ++ TC_BE, /* 3 EE TC_BE Best Effort */ ++ TC_CL, /* 4 CL TC_CL Controlled Load */ ++ TC_CL, /* 5 VI TC_CL Controlled Load */ ++ TC_VO, /* 6 VO TC_VO Voice */ ++ TC_VO /* 7 NC TC_VO Voice */ ++}; ++ ++uint32 priq_selector[] = { ++ [0x0] = TC_NONE, [0x1] = TC_BK, [0x2] = TC_BE, [0x3] = TC_BE, ++ [0x4] = TC_CL, [0x5] = TC_CL, [0x6] = TC_CL, [0x7] = TC_CL, ++ [0x8] = TC_VO, [0x9] = TC_VO, [0xa] = TC_VO, [0xb] = TC_VO, ++ [0xc] = TC_VO, [0xd] = TC_VO, [0xe] = TC_VO, [0xf] = TC_VO ++}; ++ ++/* find the chip opsvec for this chip */ ++struct chops* ++etc_chipmatch(uint vendor, uint device) ++{ ++#ifdef CFG_GMAC ++ { ++ extern struct chops bcmgmac_et_chops; ++ ++ if (bcmgmac_et_chops.id(vendor, device)) ++ return (&bcmgmac_et_chops); ++ } ++#endif /* CFG_GMAC */ ++ return (NULL); ++} ++ ++void* ++etc_attach(void *et, uint vendor, uint device, uint unit, void *osh, void *regsva) ++{ ++ etc_info_t *etc; ++ char *var; ++ ++ ET_TRACE(("et%d: etc_attach: vendor 0x%x device 0x%x\n", unit, vendor, device)); ++ ++ /* some code depends on packed structures */ ++ ASSERT(sizeof(struct ether_addr) == ETHER_ADDR_LEN); ++ ASSERT(sizeof(struct ether_header) == ETHER_HDR_LEN); ++ ++ /* allocate etc_info_t state structure */ ++ if ((etc = (etc_info_t*) MALLOC(osh, sizeof(etc_info_t))) == NULL) { ++ ET_ERROR(("et%d: etc_attach: out of memory, malloced %d bytes\n", unit, ++ MALLOCED(osh))); ++ return (NULL); ++ } ++ bzero((char*)etc, sizeof(etc_info_t)); ++ ++ etc->et = et; ++ etc->unit = unit; ++ etc->osh = osh; ++ etc->vendorid = (uint16) vendor; ++ etc->deviceid = (uint16) device; ++ etc->forcespeed = etc_gmac_speed(unit); ++ etc->linkstate = FALSE; ++ etc->mdio_init_time = 5; /* number of seconds to wait before release mdio bus */ ++ var = getvar(NULL, "eth_init_time"); ++ if (var) ++ etc->mdio_init_time = bcm_strtoul(var, NULL, 0); ++ printk("%s() mdio_init_time = %d\n", __FUNCTION__, etc->mdio_init_time); ++ ethupmask |= 1<unit; ++ ethupetcptr[unit] = etc; ++ ++#ifdef PKTC ++ /* initialize default pktc values */ ++ etc->pktcbnd = MAX(PKTCBND, RXBND); ++#endif ++ ++ /* set chip opsvec */ ++ etc->chops = etc_chipmatch(vendor, device); ++ ASSERT(etc->chops); ++ ++ /* chip attach */ ++ if ((etc->ch = (*etc->chops->attach)(etc, osh, regsva)) == NULL) { ++ ET_ERROR(("et%d: chipattach error\n", unit)); ++ goto fail; ++ } ++ ++ return ((void*)etc); ++ ++fail: ++ etc_detach(etc); ++ return (NULL); ++} ++ ++void ++etc_detach(etc_info_t *etc) ++{ ++ if (etc == NULL) ++ return; ++ ++ /* free chip private state */ ++ if (etc->ch) { ++ (*etc->chops->detach)(etc->ch); ++ etc->chops = etc->ch = NULL; ++ } ++ ++ MFREE(etc->osh, etc, sizeof(etc_info_t)); ++} ++ ++void ++etc_reset(etc_info_t *etc) ++{ ++ ET_TRACE(("et%d: etc_reset\n", etc->unit)); ++ ++ etc->reset++; ++ ++ /* reset the chip */ ++ (*etc->chops->reset)(etc->ch); ++ ++ /* free any posted tx packets */ ++ (*etc->chops->txreclaim)(etc->ch, TRUE); ++ ++#ifdef DMA ++ /* free any posted rx packets */ ++ (*etc->chops->rxreclaim)(etc->ch); ++#endif /* DMA */ ++} ++ ++void ++etc_init(etc_info_t *etc, uint options) ++{ ++ ET_TRACE(("et%d: etc_init\n", etc->unit)); ++ ++ ASSERT(etc->pioactive == NULL); ++ ASSERT(!ETHER_ISNULLADDR(&etc->cur_etheraddr)); ++ ASSERT(!ETHER_ISMULTI(&etc->cur_etheraddr)); ++ ++ /* init the chip */ ++ (*etc->chops->init)(etc->ch, options); ++ /* init the PM change mode and linkstate */ ++ etc->pm_modechange = FALSE; ++} ++ ++/* mark interface up */ ++void ++etc_up(etc_info_t *etc) ++{ ++ etc->up = TRUE; ++ ++ /* enable the port phy */ ++ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 1); ++ ++ et_init(etc->et, ET_INIT_FULL | ET_INIT_INTRON); ++} ++ ++/* mark interface down */ ++uint ++etc_down(etc_info_t *etc, int reset) ++{ ++ uint callback; ++ ++ callback = 0; ++ ++ ET_FLAG_DOWN(etc); ++ ++ /* disable the port phy */ ++ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 0); ++ ++ if (reset) ++ et_reset(etc->et); ++ ++ /* suppress link state changes during power management mode changes */ ++ if (etc->linkstate) { ++ etc->linkstate = FALSE; ++ if (!etc->pm_modechange) ++ et_link_down(etc->et); ++ } ++ ++ return (callback); ++} ++ ++/* common iovar handler. return 0=ok, -1=error */ ++int ++etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg) ++{ ++ int error; ++ uint *vecarg; ++#if defined(ETROBO) && !defined(_CFE_) ++ int i; ++ robo_info_t *robo = etc->robo; ++#endif /* ETROBO && _CFE_ */ ++ ++ error = 0; ++ vecarg = (uint *)arg; ++ ET_TRACE(("et%d: etc_iovar: cmd 0x%x\n", etc->unit, cmd)); ++ ++ switch (cmd) { ++#if defined(ETROBO) && !defined(_CFE_) ++ case IOV_ET_POWER_SAVE_MODE: ++ if (set) ++ error = robo_power_save_mode_set(robo, vecarg[1], vecarg[0]); ++ else { ++ /* get power save mode of all the phys */ ++ if (vecarg[0] == MAX_NO_PHYS) { ++ for (i = 0; i < MAX_NO_PHYS; i++) ++ vecarg[i] = robo_power_save_mode_get(robo, i); ++ break; ++ } ++ ++ /* get power save mode of the phy */ ++ error = robo_power_save_mode_get(robo, vecarg[0]); ++ if (error != -1) { ++ vecarg[1] = error; ++ error = 0; ++ } ++ } ++ break; ++ ++ case IOV_ET_ROBO_DEVID: ++ error = -1; ++ ++ if (robo != NULL) { ++ *vecarg = robo->devid; ++ error = 0; ++ } ++ break; ++#endif /* ETROBO && !_CFE_ */ ++#ifdef BCMDBG ++ case IOV_ET_CLEAR_DUMP: ++ if (set) { ++ uint size = ((char *)(&etc->rxbadlen) - (char *)(&etc->txframe)); ++ ++ bzero((char *)&etc->txframe, size + sizeof(etc->rxbadlen)); ++ (*etc->chops->dumpmib)(etc->ch, NULL, TRUE); ++ error = 0; ++ } ++ break; ++#endif /* BCMDBG */ ++ case IOV_PKTC: ++ if (set) ++ etc->pktc = *vecarg; ++ else ++ *vecarg = (uint)etc->pktc; ++ break; ++ ++ case IOV_PKTCBND: ++ if (set) ++ etc->pktcbnd = MAX(*vecarg, 32); ++ else ++ *vecarg = etc->pktcbnd; ++ break; ++ ++ case IOV_COUNTERS: ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ etc_dumpetc(etc, &b); ++ } ++ break; ++ ++#ifdef HNDCTF ++ case IOV_DUMP_CTF: ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ et_dump_ctf(etc->et, &b); ++ } ++ break; ++#endif /* HNDCTF */ ++ ++ default: ++ error = -1; ++ } ++ ++ return (error); ++} ++ ++/* common ioctl handler. return: 0=ok, -1=error */ ++int ++etc_ioctl(etc_info_t *etc, int cmd, void *arg) ++{ ++ int error; ++ int val; ++ int *vec = (int*)arg; ++ ++ error = 0; ++ ++ val = arg ? *(int*)arg : 0; ++ ++ ET_TRACE(("et%d: etc_ioctl: cmd 0x%x\n", etc->unit, cmd)); ++ ++ switch (cmd) { ++ case ETCUP: ++ et_up(etc->et); ++ break; ++ ++ case ETCDOWN: ++ et_down(etc->et, TRUE); ++ break; ++ ++ case ETCLOOP: ++ etc_loopback(etc, val); ++ break; ++ ++ case ETCDUMP: ++ if (et_msg_level & 0x10000) ++ bcmdumplog((char *)arg, IOCBUFSZ); ++ else ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ et_dump(etc->et, &b); ++ } ++ break; ++ ++ case ETCSETMSGLEVEL: ++ et_msg_level = val; ++ break; ++ ++ case ETCPROMISC: ++ etc_promisc(etc, val); ++ break; ++ ++ case ETCQOS: ++ etc_qos(etc, val); ++ break; ++ ++ case ETCSPEED: ++ if (vec) { ++ if (vec[0] == ET_1000FULL) { ++ etc->speed = 1000; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_1000HALF) { ++ etc->speed = 1000; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_100FULL) { ++ etc->speed = 100; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_100HALF) { ++ etc->speed = 100; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_10FULL) { ++ etc->speed = 10; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_10HALF) { ++ etc->speed = 10; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_AUTO) ++ ; ++ else ++ goto err; ++ ++ etc->forcespeed = vec[0]; ++ ++ /* explicitly reset the phy */ ++ (*etc->chops->phyreset)(etc->ch, etc->phyaddr); ++ ++ /* request restart autonegotiation if we're reverting to adv mode */ ++ etc->advertise = etc->advertise2 = 0; ++ if (etc->forcespeed == ET_AUTO) { ++ if (vec[1] & ADVERTISED_10baseT_Half) ++ etc->advertise |= ADV_10HALF; ++ if (vec[1] & ADVERTISED_10baseT_Full) ++ etc->advertise |= ADV_10FULL; ++ if (vec[1] & ADVERTISED_100baseT_Half) ++ etc->advertise |= ADV_100HALF; ++ if (vec[1] & ADVERTISED_100baseT_Full) ++ etc->advertise |= ADV_100FULL; ++ if (vec[1] & ADVERTISED_1000baseT_Full) ++ etc->advertise2 |= ADV_1000FULL; ++ etc->needautoneg = TRUE; ++ } else { ++ etc->needautoneg = FALSE; ++ } ++ et_init(etc->et, ET_INIT_INTRON); ++ } ++ break; ++ ++ case ETCPHYRD: ++ if (vec) { ++ vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]); ++ ET_TRACE(("etc_ioctl: ETCPHYRD of reg 0x%x => 0x%x\n", vec[0], vec[1])); ++ } ++ break; ++ ++ case ETCPHYRD2: ++ if (vec) { ++ uint phyaddr, reg; ++ phyaddr = vec[0] >> 16; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ if (phyaddr < MAXEPHY) { ++#else ++ if (1) { ++#endif ++ reg = vec[0] & 0xffff; ++ vec[1] = (*etc->chops->phyrd)(etc->ch, phyaddr, reg); ++ ET_TRACE(("etc_ioctl: ETCPHYRD2 of phy 0x%x, reg 0x%x => 0x%x\n", ++ phyaddr, reg, vec[1])); ++ } ++ } ++ break; ++ ++ case ETCPHYWR: ++ if (vec) { ++ ET_TRACE(("etc_ioctl: ETCPHYWR to reg 0x%x <= 0x%x\n", vec[0], vec[1])); ++ (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], (uint16)vec[1]); ++ } ++ break; ++ ++ case ETCPHYWR2: ++ if (vec) { ++ uint phyaddr, reg; ++ phyaddr = vec[0] >> 16; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ if (phyaddr < MAXEPHY) { ++#else ++ if (1) { ++#endif ++ reg = vec[0] & 0xffff; ++ (*etc->chops->phywr)(etc->ch, phyaddr, reg, (uint16)vec[1]); ++ ET_TRACE(("etc_ioctl: ETCPHYWR2 to phy 0x%x, reg 0x%x <= 0x%x\n", ++ phyaddr, reg, vec[1])); ++ } ++ } ++ break; ++ ++#ifdef ETROBO ++ case ETCROBORD: ++ if (etc->robo && vec) { ++ uint page, reg; ++ uint16 val; ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++ ++ page = vec[0] >> 16; ++ reg = vec[0] & 0xffff; ++ val = -1; ++ robo->ops->read_reg(etc->robo, page, reg, &val, 2); ++ vec[1] = val; ++ ET_TRACE(("etc_ioctl: ETCROBORD of page 0x%x, reg 0x%x => 0x%x\n", ++ page, reg, val)); ++ } ++ break; ++ ++ case ETCROBOWR: ++ if (etc->robo && vec) { ++ uint page, reg; ++ uint16 val; ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++ ++ page = vec[0] >> 16; ++ reg = vec[0] & 0xffff; ++ val = vec[1]; ++ robo->ops->write_reg(etc->robo, page, vec[0], &val, 2); ++ ET_TRACE(("etc_ioctl: ETCROBOWR to page 0x%x, reg 0x%x <= 0x%x\n", ++ page, reg, val)); ++ } ++ break; ++#endif /* ETROBO */ ++ ++ ++ default: ++ err: ++ error = -1; ++ } ++ ++ return (error); ++} ++ ++/* called once per second */ ++void ++etc_watchdog(etc_info_t *etc) ++{ ++ uint16 status; ++ uint16 lpa; ++#if defined(ETROBO) ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++#endif ++#if defined(ETROBO) && !defined(_CFE_) ++ static uint32 sleep_timer = PWRSAVE_SLEEP_TIME, wake_timer; ++#endif /* ETROBO && !_CFE_ */ ++ uint16 phyaddrflag=0; ++ ++ etc->now++; ++ ++#if defined(ETROBO) ++ /* BCM53125 EEE IOP WAR for some other vendor's wrong EEE implementation. */ ++ if (robo) ++ robo_watchdog(robo); ++#endif ++ ++#if defined(ETROBO) && !defined(_CFE_) ++ /* Every PWRSAVE_WAKE_TIME sec the phys that are in manual mode ++ * is taken out of that mode and link status is checked after ++ * PWRSAVE_SLEEP_TIME sec to see if any of the links is up ++ * to take that port is taken out of the manual power save mode ++ */ ++ if (robo) { ++ if (ROBO_IS_PWRSAVE_MANUAL(robo)) { ++ if (etc->now == sleep_timer) { ++ robo_power_save_toggle(robo, FALSE); ++ wake_timer = sleep_timer + PWRSAVE_WAKE_TIME; ++ } else if (etc->now == wake_timer) { ++ robo_power_save_toggle(robo, TRUE); ++ sleep_timer = wake_timer + PWRSAVE_SLEEP_TIME; ++ } ++ } ++ ++ /* Apply the auto configuration from the nvram variable in the beginning */ ++ if ((etc->now == PWRSAVE_WAKE_TIME) && ROBO_IS_PWRSAVE_AUTO(robo)) { ++ robo_power_save_mode_update(robo); ++ } ++ } ++#endif /* ETROBO && !_CFE_ */ ++ ++ /* no local phy registers */ ++ if (etc->phyaddr == EPHY_NOREG) { ++ etc->linkstate = TRUE; ++ etc->duplex = 1; ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ return; ++ } ++ ++ if (etc->up && etc->linkstate) { ++ if (!(ethup & 1<unit)) ++ printf("et%d Interface up\n", etc->unit); ++ ethup |= 1<unit; ++ } ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++ if ( !gmac_has_mdio_access()) { ++ /* we can't monitor link so force link up */ ++ /* if GMAC does not have access to MDIO then exit */ ++ if (!etc->linkstate) { ++ etc->linkstate = TRUE; ++ etc->duplex = 1; ++ etc->speed = 1000; ++ } ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ if (!et_is_link_up(etc->et)) { ++ printf("%s can't access PHY, forcing link up\n", __FUNCTION__); ++ et_link_up(etc->et); ++ } ++ return; ++ } ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ /* access external phy */ ++ phyaddrflag = 0; ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++ ++ status = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 1); ++ /* check for bad mdio read */ ++ if (status == 0xffff) { ++ ET_ERROR(("et%d: etc_watchdog: bad mdio read: phyaddr %d mdcport %d\n", ++ etc->unit, etc->phyaddr, etc->mdcport)); ++ return; ++ } ++ ++ if (etc->forcespeed == ET_AUTO) { ++ uint16 adv, adv2 = 0, status2 = 0, estatus; ++ ++ adv = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 4); ++ lpa = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 5); ++ ++ /* read extended status register. if we are 1000BASE-T ++ * capable then get our advertised capabilities and the ++ * link partner capabilities from 1000BASE-T control and ++ * status registers. ++ */ ++ estatus = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 15); ++ if ((estatus != 0xffff) && (estatus & EST_1000TFULL)) { ++ /* read 1000BASE-T control and status registers */ ++ adv2 = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 9); ++ status2 = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 10); ++ } ++ ++ /* update current speed and duplex */ ++ if ((adv2 & ADV_1000FULL) && (status2 & LPA_1000FULL)) { ++ etc->speed = 1000; ++ etc->duplex = 1; ++ } else if ((adv2 & ADV_1000HALF) && (status2 & LPA_1000HALF)) { ++ etc->speed = 1000; ++ etc->duplex = 0; ++ } else if ((adv & ADV_100FULL) && (lpa & LPA_100FULL)) { ++ etc->speed = 100; ++ etc->duplex = 1; ++ } else if ((adv & ADV_100HALF) && (lpa & LPA_100HALF)) { ++ etc->speed = 100; ++ etc->duplex = 0; ++ } else if ((adv & ADV_10FULL) && (lpa & LPA_10FULL)) { ++ etc->speed = 10; ++ etc->duplex = 1; ++ } else { ++ etc->speed = 10; ++ etc->duplex = 0; ++ } ++ } ++ ++ /* monitor link state */ ++ if (!etc->linkstate && (status & STAT_LINK)) { ++ etc->linkstate = TRUE; ++ if (etc->pm_modechange) ++ etc->pm_modechange = FALSE; ++ else { ++ et_link_up(etc->et); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ (*etc->chops->forcespddpx)(etc->ch); ++#endif /* (!defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ } ++ } else if (etc->linkstate && !(status & STAT_LINK)) { ++ etc->linkstate = FALSE; ++ if (!etc->pm_modechange) ++ et_link_down(etc->et); ++ } ++ ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ ++ /* check for remote fault error */ ++ if (status & STAT_REMFAULT) { ++ ET_ERROR(("et%d: remote fault\n", etc->unit)); ++ } ++ ++ /* check for jabber error */ ++ if (status & STAT_JAB) { ++ ET_ERROR(("et%d: jabber\n", etc->unit)); ++ } ++ ++ /* ++ * Read chip mib counters occationally before the 16bit ones can wrap. ++ * We don't use the high-rate mib counters. ++ */ ++ if ((etc->now % 30) == 0) ++ (*etc->chops->statsupd)(etc->ch); ++} ++ ++static void ++etc_loopback(etc_info_t *etc, int on) ++{ ++ ET_TRACE(("et%d: etc_loopback: %d\n", etc->unit, on)); ++ ++ etc->loopbk = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_promisc(etc_info_t *etc, uint on) ++{ ++ ET_TRACE(("et%d: etc_promisc: %d\n", etc->unit, on)); ++ ++ etc->promisc = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_qos(etc_info_t *etc, uint on) ++{ ++ ET_TRACE(("et%d: etc_qos: %d\n", etc->unit, on)); ++ ++ etc->qos = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_dump(etc_info_t *etc, struct bcmstrbuf *b) ++{ ++ etc_dumpetc(etc, b); ++ (*etc->chops->dump)(etc->ch, b); ++} ++ ++static void ++etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b) ++{ ++ char perm[32], cur[32]; ++ uint i; ++ ++ bcm_bprintf(b, "etc 0x%x et 0x%x unit %d msglevel %d speed/duplex %d%s\n", ++ (ulong)etc, (ulong)etc->et, etc->unit, et_msg_level, ++ etc->speed, (etc->duplex ? "full": "half")); ++ bcm_bprintf(b, "up %d promisc %d loopbk %d forcespeed %d advertise 0x%x " ++ "advertise2 0x%x needautoneg %d\n", ++ etc->up, etc->promisc, etc->loopbk, etc->forcespeed, ++ etc->advertise, etc->advertise2, etc->needautoneg); ++ bcm_bprintf(b, "piomode %d pioactive 0x%x nmulticast %d allmulti %d qos %d\n", ++ etc->piomode, (ulong)etc->pioactive, etc->nmulticast, etc->allmulti, etc->qos); ++ bcm_bprintf(b, "vendor 0x%x device 0x%x rev %d coreunit %d phyaddr %d mdcport %d\n", ++ etc->vendorid, etc->deviceid, etc->chiprev, ++ etc->coreunit, etc->phyaddr, etc->mdcport); ++ ++ bcm_bprintf(b, "perm_etheraddr %s cur_etheraddr %s\n", ++ bcm_ether_ntoa(&etc->perm_etheraddr, perm), ++ bcm_ether_ntoa(&etc->cur_etheraddr, cur)); ++ ++ if (etc->nmulticast) { ++ bcm_bprintf(b, "multicast: "); ++ for (i = 0; i < etc->nmulticast; i++) ++ bcm_bprintf(b, "%s ", bcm_ether_ntoa(&etc->multicast[i], cur)); ++ bcm_bprintf(b, "\n"); ++ } ++ ++ bcm_bprintf(b, "linkstate %d\n", etc->linkstate); ++ bcm_bprintf(b, "\n"); ++ ++ /* refresh stat counters */ ++ (*etc->chops->statsupd)(etc->ch); ++ ++ /* summary stat counter line */ ++ /* use sw frame and byte counters -- hw mib counters wrap too quickly */ ++ bcm_bprintf(b, "txframe %d txbyte %d txerror %d rxframe %d rxbyte %d rxerror %d\n", ++ etc->txframe, etc->txbyte, etc->txerror, ++ etc->rxframe, etc->rxbyte, etc->rxerror); ++ ++ /* transmit & receive stat counters */ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ (*etc->chops->dumpmib)(etc->ch, b, FALSE); ++ ++ bcm_bprintf(b, "txnobuf %d reset %d dmade %d dmada %d dmape %d\n", ++ etc->txnobuf, etc->reset, etc->dmade, etc->dmada, etc->dmape); ++ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ bcm_bprintf(b, "rxnobuf %d rxdmauflo %d rxoflo %d rxbadlen %d " ++ "rxgiants %d rxoflodiscards %d\n", ++ etc->rxnobuf, etc->rxdmauflo, etc->rxoflo, etc->rxbadlen, ++ etc->rxgiants, etc->rxoflodiscards); ++ ++ bcm_bprintf(b, "chained %d chainedsz1 %d unchained %d maxchainsz %d currchainsz %d\n", ++ etc->chained, etc->chainedsz1, etc->unchained, etc->maxchainsz, ++ etc->currchainsz); ++ ++ bcm_bprintf(b, "\n"); ++} ++ ++uint ++etc_totlen(etc_info_t *etc, void *p) ++{ ++ uint total; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(etc->osh, p)) ++ total += PKTLEN(etc->osh, p); ++ return (total); ++} ++ ++#ifdef BCMDBG ++void ++etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit) ++{ ++ char da[32], sa[32]; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("et%d: %s: ", unit, msg); ++ else ++ printf("et%d: ", unit); ++ ++ printf("dst %s src %s type 0x%04X len %d\n", ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_dhost, da), ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, sa), ++ ntoh16(eh->ether_type), ++ len); ++} ++void ++etc_prhex(char *msg, uchar *buf, uint nbytes, int unit) ++{ ++ if (msg && (msg[0] != '\0')) ++ printf("et%d: %s:\n", unit, msg); ++ else ++ printf("et%d:\n", unit); ++ ++ prhex(NULL, buf, nbytes); ++} ++#endif /* BCMDBG */ ++ ++ ++#ifdef ETROBO ++extern void robo_dump_mib(robo_info_t *robo); ++extern void robo_reset_mib(robo_info_t *robo); ++#endif ++extern void etc_chip_mib(etc_info_t *etc); ++void ++etc_robomib(etc_info_t *etc) ++{ ++#ifdef ETROBO ++ if (etc->robo) { ++ robo_dump_mib(etc->robo); ++ robo_reset_mib(etc->robo); ++ } ++#endif ++ ++ etc_chip_mib(etc); ++} ++ ++int ++etc_gmac_speed(int gmac) ++{ ++ char name[16], *speed; ++ sprintf(name, "et%dspeed", gmac); ++ ++ speed = nvram_get(name); ++ if (speed == NULL) { ++ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); ++ return ET_AUTO; ++ } ++ ++ if (!strcmp(speed, "2500")) { ++ printf("%s specifing GMAC%d speed: 2500\n", __FUNCTION__, gmac); ++ return ET_2500FULL; ++ } ++ else if (!strcmp(speed, "1000")) { ++ printf("%s specifing GMAC%d speed: 1000\n", __FUNCTION__, gmac); ++ return ET_1000FULL; ++ } ++ else if (!strcmp(speed, "100")) { ++ printf("%s specifing GMAC%d speed: 100\n", __FUNCTION__, gmac); ++ return ET_100FULL; ++ } ++ else if (!strcmp(speed, "10")) { ++ printf("%s specifing GMAC%d speed: 10\n", __FUNCTION__, gmac); ++ return ET_10FULL; ++ } ++ ++ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); ++ return ET_AUTO; ++} +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etc.h b/drivers/bcmdrivers/gmac/src/et/sys/etc.h +new file mode 100755 +index 0000000..c31ce8a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch new file mode 100644 index 00000000..ed0cafc6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch @@ -0,0 +1,323 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etc.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Common [OS-independent] header file for ++ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver ++ * ++ * $Id: etc.h 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#ifndef _etc_h_ ++#define _etc_h_ ++ ++#include ++ ++#define MAXMULTILIST 32 ++ ++#ifndef ch_t ++#define ch_t void ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define NUMTXQ 4 ++#else ++#define NUMTXQ 1 ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ++#define TXREC_THR 8 ++ ++#if defined(__ECOS) ++#define IOCBUFSZ 4096 ++#elif defined(__linux__) ++#define IOCBUFSZ 16384 ++#else ++#define IOCBUFSZ 4096 ++#endif ++ ++struct etc_info; /* forward declaration */ ++struct bcmstrbuf; /* forward declaration */ ++ ++/* each chip type supports a set of chip-type-specific ops */ ++struct chops { ++ bool (*id)(uint vendor, uint device); /* return true if match */ ++ void *(*attach)(struct etc_info *etc, void *dev, void *regs); ++ void (*detach)(ch_t *ch); /* free chip private state */ ++ void (*reset)(ch_t *ch); /* chip reset */ ++ void (*init)(ch_t *ch, uint options); /* chip init */ ++ bool (*tx)(ch_t *ch, void *p); /* transmit frame */ ++ void *(*rx)(ch_t *ch); /* receive frame */ ++ void (*rxfill)(ch_t *ch); /* post dma rx buffers */ ++ int (*getintrevents)(ch_t *ch, bool in_isr); /* return intr events */ ++ bool (*errors)(ch_t *ch); /* handle chip errors */ ++ void (*intrson)(ch_t *ch); /* enable chip interrupts */ ++ void (*intrsoff)(ch_t *ch); /* disable chip interrupts */ ++ void (*txreclaim)(ch_t *ch, bool all); /* reclaim transmit resources */ ++ void (*rxreclaim)(ch_t *ch); /* reclaim receive resources */ ++ void (*statsupd)(ch_t *ch); /* update sw stat counters */ ++ void (*dumpmib)(ch_t *ch, struct bcmstrbuf *, bool clear); /* get sw mib counters */ ++ void (*enablepme)(ch_t *ch); /* enable PME */ ++ void (*disablepme)(ch_t *ch); /* disable PME */ ++ void (*phyreset)(ch_t *ch, uint phyaddr); /* reset phy */ ++ uint16 (*phyrd)(ch_t *ch, uint phyaddr, uint reg); /* read phy register */ ++ void (*phywr)(ch_t *ch, uint phyaddr, uint reg, uint16 val); /* write phy register */ ++ void (*dump)(ch_t *ch, struct bcmstrbuf *b); /* debugging output */ ++ void (*longname)(ch_t *ch, char *buf, uint bufsize); /* return descriptive name */ ++ void (*duplexupd)(ch_t *ch); /* keep mac duplex consistent */ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ void (*forcespddpx)(ch_t *ch); /* force the speed and duplex */ ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ void (*phyenable)(ch_t *ch, uint eth_num, uint phyaddr, int enable); /* enable phy */ ++}; ++ ++/* ++ * "Common" os-independent software state structure. ++ */ ++typedef struct etc_info { ++#ifdef GMAC3 ++ bool gmac_fwd; /* gmac forwarding */ ++#endif /* GMAC3 */ ++ void *et; /* pointer to os-specific private state */ ++ uint unit; /* device instance number */ ++ void *osh; /* pointer to os handler */ ++ bool pktc; /* packet chaining enabled or not */ ++ int pktcbnd; /* max # of packets to chain */ ++ void *mib; /* pointer to s/w maintained mib counters */ ++ bool up; /* interface up and running */ ++ bool promisc; /* promiscuous destination address */ ++ bool qos; /* QoS priority determination on rx */ ++ bool loopbk; /* loopback override mode */ ++ ++ int forcespeed; /* disable autonegotiation and force speed/duplex */ ++ uint advertise; /* control speed/duplex advertised caps */ ++ uint advertise2; /* control gige speed/duplex advertised caps */ ++ bool needautoneg; /* request restart autonegotiation */ ++ int speed; /* current speed: 10, 100 */ ++ int duplex; /* current duplex: 0=half, 1=full */ ++ ++ bool piomode; /* enable programmed io (!dma) */ ++ void *pioactive; /* points to pio packet being transmitted */ ++ volatile uint *txavail[NUMTXQ]; /* dma: # tx descriptors available */ ++ ++ uint16 vendorid; /* pci function vendor id */ ++ uint16 deviceid; /* pci function device id */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint coreid; /* core id */ ++ uint corerev; /* core revision */ ++ ++ bool nicmode; /* is this core using its own pci i/f */ ++ ++ struct chops *chops; /* pointer to chip-specific opsvec */ ++ void *ch; /* pointer to chip-specific state */ ++ void *robo; /* optional robo private data */ ++ ++ uint txq_state; /* tx queues state bits */ ++ uint coreunit; /* sb chips: chip enet instance # */ ++ uint phyaddr; /* sb chips: mdio 5-bit phy address */ ++ uint mdcport; /* sb chips: which mii to use (enet core #) to access phy */ ++ ++ struct ether_addr cur_etheraddr; /* our local ethernet address */ ++ struct ether_addr perm_etheraddr; /* original sprom local ethernet address */ ++ ++ struct ether_addr multicast[MAXMULTILIST]; ++ uint nmulticast; ++ bool allmulti; /* enable all multicasts */ ++ ++ bool linkstate; /* link integrity state */ ++ bool pm_modechange; /* true if mode change is to due pm */ ++ ++ uint32 now; /* elapsed seconds */ ++ ++ uint32 boardflags; /* board flags */ ++ uint32 txrec_thresh; /* # of tx frames after which reclaim is done */ ++ ++ uint32 mdio_init_time; /* # of seconds to wait before release mdio bus */ ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ bool rl_enabled; /* enable rate limiting logic */ ++ struct timer_list rl_timer; /* one second ratelimiting timer */ ++ bool rl_set; /* indicate the timer is set or not */ ++ uint32 rl_stopping_all_packets; ++ uint32 rl_stopping_broadcasts; ++ uint32 rl_dropped_all_packets; ++ uint32 rl_dropped_bc_packets; ++ uint32 rl_dropped_packets; ++ uint32 rl_prior_jiffies; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ /* sw-maintained stat counters */ ++ uint32 txframes[NUMTXQ]; /* transmitted frames on each tx fifo */ ++ uint32 txframe; /* transmitted frames */ ++ uint32 txbyte; /* transmitted bytes */ ++ uint32 rxframe; /* received frames */ ++ uint32 rxbyte; /* received bytes */ ++ uint32 txerror; /* total tx errors */ ++ uint32 txnobuf; /* tx out-of-buffer errors */ ++ uint32 rxerror; /* total rx errors */ ++ uint32 rxgiants; /* total rx giant frames */ ++ uint32 rxnobuf; /* rx out-of-buffer errors */ ++ uint32 reset; /* reset count */ ++ uint32 dmade; /* pci descriptor errors */ ++ uint32 dmada; /* pci data errors */ ++ uint32 dmape; /* descriptor protocol error */ ++ uint32 rxdmauflo; /* receive descriptor underflow */ ++ uint32 rxoflo; /* receive fifo overflow */ ++ uint32 txuflo; /* transmit fifo underflow */ ++ uint32 rxoflodiscards; /* frames discarded during rx fifo overflow */ ++ uint32 rxbadlen; /* 802.3 len field != read length */ ++ uint32 chained; /* number of frames chained */ ++ uint32 chainedsz1; /* number of chain size 1 frames */ ++ uint32 unchained; /* number of frames not chained */ ++ uint32 maxchainsz; /* max chain size so far */ ++ uint32 currchainsz; /* current chain size */ ++ /* my counters */ ++ uint32 txfrm; /* tx frames */ ++ uint32 txfrmdropped; /* tx dropped frames */ ++ uint32 txqlen; ++ uint32 txqstop; ++ uint32 txdmafull; ++ uint32 txmaxlen; ++ uint32 txsgpkt; ++ uint32 rxquota; ++ uint32 rxdmastopped; ++} etc_info_t; ++ ++/* interrupt event bitvec */ ++#define INTR_TX 0x1 ++#define INTR_RX 0x2 ++#define INTR_ERROR 0x4 ++#define INTR_TO 0x8 ++#define INTR_NEW 0x10 ++ ++/* forcespeed values */ ++#define ET_AUTO -1 ++#define ET_10HALF 0 ++#define ET_10FULL 1 ++#define ET_100HALF 2 ++#define ET_100FULL 3 ++#define ET_1000HALF 4 ++#define ET_1000FULL 5 ++#define ET_2500FULL 6 /* 2.5Gigabit */ ++ ++/* init options */ ++#define ET_INIT_FULL 0x1 ++#define ET_INIT_INTRON 0x2 ++ ++/* Specific init options for et_init */ ++#define ET_INIT_DEF_OPTIONS (ET_INIT_FULL | ET_INIT_INTRON) ++#define ET_INIT_INTROFF (ET_INIT_FULL) ++#define ET_INIT_PARTIAL (0) ++ ++/* macro to safely clear the UP flag */ ++#define ET_FLAG_DOWN(x) (*(x)->chops->intrsoff)((x)->ch); \ ++ (x)->up = FALSE; ++ ++/* ++ * Least-common denominator rxbuf start-of-data offset: ++ * Must be >= size of largest rxhdr ++ * Must be 2-mod-4 aligned so IP is 0-mod-4 ++ */ ++#define HWRXOFF 30 ++ ++#define TC_BK 0 /* background traffic class */ ++#define TC_BE 1 /* best effort traffic class */ ++#define TC_CL 2 /* controlled load traffic class */ ++#define TC_VO 3 /* voice traffic class */ ++#define TC_NONE -1 /* traffic class none */ ++ ++#define RX_Q0 0 /* receive DMA queue */ ++#define NUMRXQ 1 /* gmac has one rx queue */ ++ ++#define TX_Q0 TC_BK /* DMA txq 0 */ ++#define TX_Q1 TC_BE /* DMA txq 1 */ ++#define TX_Q2 TC_CL /* DMA txq 2 */ ++#define TX_Q3 TC_VO /* DMA txq 3 */ ++ ++static inline uint32 ++etc_up2tc(uint32 up) ++{ ++ extern uint32 up2tc[]; ++ ++ return (up2tc[up]); ++} ++ ++static inline uint32 ++etc_priq(uint32 txq_state) ++{ ++ extern uint32 priq_selector[]; ++ ++ return (priq_selector[txq_state]); ++} ++ ++/* rx header flags bits */ ++#define RXH_FLAGS(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ ((((bcmgmacrxh_t *)(rxh))->flags) & htol16(GRXF_CRC | GRXF_OVF | GRXF_OVERSIZE)) : \ ++ ((((bcmenetrxh_t *)(rxh))->flags) & htol16(RXF_NO | RXF_RXER | RXF_CRC | RXF_OV))) ++ ++#define RXH_OVERSIZE(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVERSIZE) : FALSE) ++ ++#define RXH_PT(etc, rxh) (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_PT_MASK) ++ ++#define RXH_CRC(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_CRC) : \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_CRC)) ++ ++#define RXH_OVF(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVF) : \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_OV)) ++ ++#define RXH_RXER(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_RXER)) ++ ++#define RXH_NO(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_NO)) ++ ++/* Used for fa+ error determination */ ++#define RXH_CTFERROR(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & (GRXF_CTFERR | GRXF_CRC | GRXF_OVF)) : FALSE) ++ ++#ifdef CFG_GMAC ++#define ET_GMAC(etc) ((etc)->coreid == GMAC_CORE_ID) ++#else ++#define ET_GMAC(etc) (0) ++#endif /* CFG_GMAC */ ++ ++/* exported prototypes */ ++extern struct chops *etc_chipmatch(uint vendor, uint device); ++extern void *etc_attach(void *et, uint vendor, uint device, uint unit, void *dev, void *regsva); ++extern void etc_detach(etc_info_t *etc); ++extern void etc_reset(etc_info_t *etc); ++extern void etc_init(etc_info_t *etc, uint options); ++extern void etc_up(etc_info_t *etc); ++extern uint etc_down(etc_info_t *etc, int reset); ++extern int etc_ioctl(etc_info_t *etc, int cmd, void *arg); ++extern int etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg); ++extern void etc_promisc(etc_info_t *etc, uint on); ++extern void etc_qos(etc_info_t *etc, uint on); ++extern void etc_dump(etc_info_t *etc, struct bcmstrbuf *b); ++extern void etc_watchdog(etc_info_t *etc); ++extern uint etc_totlen(etc_info_t *etc, void *p); ++extern void etc_robomib(etc_info_t *etc); ++ ++#endif /* _etc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c +new file mode 100755 +index 0000000..eff478e diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch new file mode 100644 index 00000000..3d5909de --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch @@ -0,0 +1,2573 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c +@@ -0,0 +1,2567 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Gigabit Ethernet MAC (Unimac) core. ++ * This file implements the chip-specific routines for the GMAC core. ++ * ++ * $Id: etcgmac.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* for et_phyxx() routines */ ++#include ++#include ++#include ++#include ++ ++#ifdef ETROBO ++#include ++#endif /* ETROBO */ ++#ifdef GMAC3 ++#include /* GMAC3 */ ++#endif /* GMAC3 */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "mach/socregs_ing_open.h" ++#endif ++#if defined(CONFIG_MACH_KT2) ++#include "mach/socregs_ing_open.h" ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "bcmiproc_serdes.h" ++#include "bcmiproc_phy5461s.h" ++#endif ++#if defined(CONFIG_MACH_HR2) ++#include "bcmiproc_phy5221.h" ++#endif ++#if defined(CONFIG_MACH_NSP) ++#include ++#include "bcmiproc_robo_serdes.h" ++#endif ++ ++struct bcmgmac; /* forward declaration */ ++#define ch_t struct bcmgmac ++#include ++ ++extern int nvram_env_gmac_name(int gmac, char *name); ++ ++#ifdef ETROBO ++extern void robo_reset_mib(robo_info_t *robo); ++extern void robo_dump_mib(robo_info_t *robo); ++#endif ++ ++/* private chip state */ ++struct bcmgmac { ++ void *et; /* pointer to et private state */ ++ etc_info_t *etc; /* pointer to etc public state */ ++ ++ gmac_commonregs_t *regscomm; /* pointer to GMAC COMMON registers */ ++ gmacregs_t *regs; /* pointer to chip registers */ ++ osl_t *osh; /* os handle */ ++ ++ void *etphy; /* pointer to et for shared mdc/mdio contortion */ ++ ++ uint32 intstatus; /* saved interrupt condition bits */ ++ uint32 intmask; /* current software interrupt mask */ ++ uint32 def_intmask; /* default interrupt mask */ ++ ++ hnddma_t *di[NUMTXQ]; /* dma engine software state */ ++ ++ bool mibgood; /* true once mib registers have been cleared */ ++ gmacmib_t mib; /* mib statistic counters */ ++ si_t *sih; /* si utils handle */ ++ ++ char *vars; /* sprom name=value */ ++ uint vars_size; ++ ++ void *adm; /* optional admtek private data */ ++ mcfilter_t mf; /* multicast filter */ ++}; ++ ++/* local prototypes */ ++static bool chipid(uint vendor, uint device); ++static void *chipattach(etc_info_t *etc, void *osh, void *regsva); ++static void chipdetach(ch_t *ch); ++static void chipreset(ch_t *ch); ++static void chipinit(ch_t *ch, uint options); ++static bool chiptx(ch_t *ch, void *p); ++static void *chiprx(ch_t *ch); ++static void chiprxfill(ch_t *ch); ++static int chipgetintrevents(ch_t *ch, bool in_isr); ++static bool chiperrors(ch_t *ch); ++static void chipintrson(ch_t *ch); ++static void chipintrsoff(ch_t *ch); ++static void chiptxreclaim(ch_t *ch, bool all); ++static void chiprxreclaim(ch_t *ch); ++static void chipstatsupd(ch_t *ch); ++static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear); ++static void chipenablepme(ch_t *ch); ++static void chipdisablepme(ch_t *ch); ++static void chipphyreset(ch_t *ch, uint phyaddr); ++static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg); ++static void chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v); ++static void chipdump(ch_t *ch, struct bcmstrbuf *b); ++static void chiplongname(ch_t *ch, char *buf, uint bufsize); ++static void chipduplexupd(ch_t *ch); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++static void chipforcespddpx(ch_t *ch); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++static void chipphyinit(ch_t *ch, uint phyaddr); ++static void chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v); ++static void chipphyforce(ch_t *ch, uint phyaddr); ++static void chipphyadvertise(ch_t *ch, uint phyaddr); ++static void chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable); ++static void chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b); ++static void gmac_mf_cleanup(ch_t *ch); ++static int gmac_speed(ch_t *ch, uint32 speed); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void gmac_serdes_init(ch_t *ch); ++#endif ++static void gmac_miiconfig(ch_t *ch); ++ ++struct chops bcmgmac_et_chops = { ++ chipid, ++ chipattach, ++ chipdetach, ++ chipreset, ++ chipinit, ++ chiptx, ++ chiprx, ++ chiprxfill, ++ chipgetintrevents, ++ chiperrors, ++ chipintrson, ++ chipintrsoff, ++ chiptxreclaim, ++ chiprxreclaim, ++ chipstatsupd, ++ chipdumpmib, ++ chipenablepme, ++ chipdisablepme, ++ chipphyreset, ++ chipphyrd, ++ chipphywr, ++ chipdump, ++ chiplongname, ++ chipduplexupd, ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ chipforcespddpx, ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ chipphyenable ++}; ++ ++static uint devices[] = { ++ BCM47XX_GMAC_ID, ++ BCM4716_CHIP_ID, ++ BCM4748_CHIP_ID, ++ BCM53010_CHIP_ID, ++ BCM56150_CHIP_ID, ++ BCM56340_CHIP_ID, ++ BCM53020_CHIP_ID, ++ BCM56450_CHIP_ID, ++ 0x0000 ++}; ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void *wrapaddr = 0; ++void gmac_set_amac_mdio(int en) ++{ ++ u32 tmp; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL; ++ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL; ++#else ++ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL; ++ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL; ++#endif ++ u32 iproc_mdio_sel= IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL; ++ ++ if (en) { ++ /* Get register base address */ ++ wrapaddr = ioremap(IPROC_WRAP_MISC_CONTROL, 0x10); ++ //printf("%s IPROC_WRAP_MISC_CONTROL(0x%x) remaps to 0x%x\n", __FUNCTION__, IPROC_WRAP_MISC_CONTROL, (u32)wrapaddr); ++ } ++ ++ tmp = ioread32(wrapaddr); ++ //printf("%s read (0x%x) from IPROC_WRAP_MISC_CONTROL(0x%x)\n", __FUNCTION__, tmp, (u32)wrapaddr); ++ if (en) { ++ /* set bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL, ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL & ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL ++ so AMAC can access the Serdes and Phy */ ++ tmp |= ((1 << mdio_sel) | (1 << ctrl_sel) | (1 << iproc_mdio_sel)); ++ } else { ++ /* clear bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL & ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL ++ so CMIC can access the Serdes and Phy */ ++ tmp &= ~((1 << mdio_sel) | (1 << iproc_mdio_sel)); ++ } ++ //printf("%s write 0x%x to IPROC_WRAP_MISC_CONTROL(0x%x)\n", __FUNCTION__, tmp, (u32)wrapaddr); ++ iowrite32(tmp, wrapaddr); ++ ++ if (!en) { ++ /* unmap register base address */ ++ //printf("%s unmap(0x%x)\n", __FUNCTION__, (u32)wrapaddr); ++ iounmap(wrapaddr); ++ wrapaddr=0; ++ } ++} ++ ++ ++int gmac_has_mdio_access(void) ++{ ++ u32 tmp; ++ u32 regmsk = (1 << IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL) | ++ (1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL)); ++#else ++ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL) | ++ (1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL)); ++#endif ++ ++ if (wrapaddr==0) { ++ /* if no wrapaddr then no access */ ++ return 0; ++ } ++ ++ tmp = ioread32(wrapaddr); ++ tmp &= ~regmsk; ++ if (tmp == regmsk) { ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/* This api will determine if this unit specified is the last interface. */ ++bool gmac_last_interface(int unit) ++{ ++ char name[128]; ++ int idx; ++ ++ /* if interface 2 or greater then must be last */ ++ if (unit>=2) ++ return true; ++ ++ /* Look to see if there is a next interface specified */ ++ for (idx=unit+1; idx<=2; idx++) { ++ nvram_env_gmac_name(idx, name); ++ if (getvar(NULL, name) != NULL) { ++ /* there is a next interface */ ++ return false; ++ } ++ } ++ /* no other interfaces */ ++ return true; ++} ++ ++ ++static bool ++chipid(uint vendor, uint device) ++{ ++ int i; ++ ++ if (vendor != VENDOR_BROADCOM) { ++ ET_ERROR(("%s ERROR: NOT a BROADCOM Vendor ID (0x%x)\n", __FUNCTION__, vendor)); ++ return (FALSE); ++ } ++ ++ for (i = 0; devices[i]; i++) { ++ if (device == devices[i]) ++ return (TRUE); ++ } ++ ++ ET_ERROR(("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device)); ++ printk("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device); ++ return (FALSE); ++} ++ ++static void * ++chipattach(etc_info_t *etc, void *osh, void *regsva) ++{ ++ ch_t *ch; ++ gmacregs_t *regs; ++ uint i; ++ char name[16]; ++ char *var; ++ uint boardflags, boardtype; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ uint reset; ++#endif ++#ifdef ETROBO ++ char *pet; ++ int initsw=0; ++#endif ++ ++ ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva)); ++ ++ if ((ch = (ch_t *)MALLOC(osh, sizeof(ch_t))) == NULL) { ++ ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit, ++ MALLOCED(osh))); ++ return (NULL); ++ } ++ bzero((char *)ch, sizeof(ch_t)); ++ ++ ch->etc = etc; ++ ch->et = etc->et; ++ ch->osh = osh; ++ ++ /* store the pointer to the sw mib */ ++ etc->mib = (void *)&ch->mib; ++ ++ /* get si handle */ ++ if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars, ++ &ch->vars_size)) == NULL) { ++ ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit)); ++ goto fail; ++ } ++ ++ if ((etc->corerev = si_corerev(ch->sih)) == GMAC_4706B0_CORE_REV && ++ (ch->regscomm = (gmac_commonregs_t *)si_setcore(ch->sih, ++ GMAC_COMMON_4706_CORE_ID, 0)) == NULL) { ++ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC common\n", etc->unit)); ++ goto fail; ++ } ++ ++ if ((regs = (gmacregs_t *)si_setcore(ch->sih, GMAC_CORE_ID, etc->unit)) == NULL) { ++ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC\n", etc->unit)); ++ goto fail; ++ } ++ ++ ch->regs = regs; ++ etc->chip = ch->sih->chip; ++ etc->chiprev = ch->sih->chiprev; ++ etc->coreid = si_coreid(ch->sih); ++ etc->nicmode = !(ch->sih->bustype == SI_BUS); ++ etc->coreunit = si_coreunit(ch->sih); ++#ifdef GMAC3 ++ etc->gmac_fwd = FALSE; /* GMAC3 */ ++#endif /* GMAC3 */ ++ etc->boardflags = getintvar(ch->vars, "boardflags"); ++ ++ boardflags = etc->boardflags; ++ boardtype = ch->sih->boardtype; ++ ++#ifdef PKTC ++ etc->pktc = (getintvar(ch->vars, "pktc_disable") == 0); ++#endif ++ ++ /* get our local ether addr */ ++ nvram_env_gmac_name(etc->coreunit, name); ++ var = getvar(ch->vars, name); ++ if (var == NULL) { ++ ET_ERROR(("et%d: chipattach: getvar(%s) not found\n", etc->unit, name)); ++ goto fail; ++ } ++ bcm_ether_atoe(var, &etc->perm_etheraddr); ++ ++#ifdef GMAC3 ++ /* ++ * Select GMAC mode of operation: ++ * If a valid MAC address is present, it operates as an Ethernet Network ++ * interface, otherwise it operates as a forwarding GMAC interface. ++ */ ++ //if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) ++ if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { ++ etc->gmac_fwd = TRUE; ++ printk("%s GMAC forward enabled\n", __FUNCTION__); ++ } ++#else /* !GMAC3 */ ++ if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { ++ ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var)); ++ goto fail; ++ } ++#endif /* !GMAC3 */ ++ ++ bcopy((char *)&etc->perm_etheraddr, (char *)&etc->cur_etheraddr, ETHER_ADDR_LEN); ++ ++ ++ /* ++ * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" . ++ * Instead, explicitly require the environment var "etphyaddr=". ++ */ ++ ++ /* get our phyaddr value */ ++ sprintf(name, "et%dphyaddr", etc->coreunit); ++ var = getvar(NULL, name); ++ if (var == NULL) { ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ etc->phyaddr = EPHY_NOREG; ++#else ++ etc->phyaddr = etc->unit+1; ++#endif ++ ET_ERROR(("et%d: chipattach: getvar(%s) not found set to %d\n", etc->unit, name, etc->phyaddr)); ++ } else { ++ etc->phyaddr = bcm_atoi(var) & EPHY_MASK; ++ } ++ printf("et%d: chipattach: phyaddr(0x%x)\n", etc->unit, etc->phyaddr); ++ ++ /* nvram says no phy is present */ ++ if (etc->phyaddr == EPHY_NONE) { ++ ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit)); ++ goto fail; ++ } ++ ++ /* reset the gmac core */ ++ chipreset(ch); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (wrapaddr == 0) { ++ /* flip switch so AMAC can access serdes */ ++ gmac_set_amac_mdio(1); ++ } ++ ++ if (etc->unit == 0) { ++ void *amacidmaddr; ++ uint32 tmp; ++ ++ /* Get register base address */ ++ amacidmaddr = ioremap(AMAC_IDM0_IO_CONTROL_DIRECT, 0x10); ++ tmp = ioread32(amacidmaddr); ++ ++ //printf("%s read AMAC_IDM0_IO_CONTROL_DIRECT: 0x%x\n", __FUNCTION__, tmp); ++ tmp &= ~(1<unit == 1) { ++ void *amacidmaddr; ++ uint32 tmp; ++ ++ /* Get register base address */ ++ amacidmaddr = ioremap(AMAC_IDM1_IO_CONTROL_DIRECT, 0x10); ++ tmp = ioread32(amacidmaddr); ++ ++ //printf("%s read AMAC_IDM1_IO_CONTROL_DIRECT: 0x%x\n", __FUNCTION__, tmp); ++ tmp &= ~(1<=1000) { ++ printf("%s ERROR: PLL failed to lock\n", __FUNCTION__); ++ } ++ /* CRU_LCPLL2_CONTROL0 post_resetb=1 */ ++ tmp = ioread32(lcplladdr); ++ tmp |= (1<coreunit); ++ ++ /* allocate dma resources for txqs */ ++ /* TX: TC_BK, RX: RX_Q0 */ ++ ch->di[0] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q0), ++ DMAREG(ch, DMA_RX, RX_Q0), ++ NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF, ++ &et_msg_level); ++ ++#if defined(CONFIG_MACH_NS) ++ /* TX: TC_BE, RX: UNUSED */ ++ ch->di[1] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q1), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++ ++ /* TX: TC_CL, RX: UNUSED */ ++ ch->di[2] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q2), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++ ++ /* TX: TC_VO, RX: UNUSED */ ++ ch->di[3] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q3), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] == NULL) { ++ ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit)); ++ goto fail; ++ } ++ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] != NULL) ++ etc->txavail[i] = (uint *)&ch->di[i]->txavail; ++ ++ /* set default sofware intmask */ ++ sprintf(name, "et%d_no_txint", etc->coreunit); ++ if (getintvar(ch->vars, name)) { ++ /* if no_txint variable is non-zero we disable tx interrupts. ++ * we do the tx buffer reclaim once every few frames. ++ */ ++ ch->def_intmask = (DEF_INTMASK & ~(I_XI0 | I_XI1 | I_XI2 | I_XI3)); ++ etc->txrec_thresh = (((NTXD >> 2) > TXREC_THR) ? TXREC_THR - 1 : 1); ++ } else ++ ch->def_intmask = DEF_INTMASK; ++ ++ ch->intmask = ch->def_intmask; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ /* reset the external phy */ ++ if ((reset = getgpiopin(ch->vars, "ephy_reset", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ reset = 1 << reset; ++ ++ /* Keep RESET low for 2 us */ ++ si_gpioout(ch->sih, reset, 0, GPIO_DRV_PRIORITY); ++ si_gpioouten(ch->sih, reset, reset, GPIO_DRV_PRIORITY); ++ OSL_DELAY(2); ++ ++ /* Keep RESET high for at least 2 us */ ++ si_gpioout(ch->sih, reset, reset, GPIO_DRV_PRIORITY); ++ OSL_DELAY(2); ++ ++ /* if external phy is present enable auto-negotation and ++ * advertise full capabilities as default config. ++ */ ++ ASSERT(etc->phyaddr != EPHY_NOREG); ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ etc->advertise2 = ADV_1000FULL; ++ } ++#endif ++ ++ /* reset phy: reset it once now */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (ch->etc->unit == 0) { ++ serdes_reset_core(ch->etc->unit, etc->phyaddr); ++ } ++#endif ++ ++ chipphyreset(ch, etc->phyaddr); ++ ++#ifdef ETROBO ++ /* ++ * Broadcom Robo ethernet switch. ++ */ ++ pet = getvar(NULL, "swgmacet"); ++ sprintf(name, "et%d", etc->coreunit); ++ if (pet) { ++ if (bcmp(pet, name, strlen(pet)) == 0) ++ initsw = 1; ++ } ++ ++ if ((boardflags & BFL_ENETROBO) && initsw) { ++ ET_TRACE(("et%d: chipattach: Calling robo attach\n", etc->unit)); ++ printk("et%d: chipattach: Calling robo attach\n", etc->unit); ++ ++ /* Attach to the switch */ ++ if (!(etc->robo = bcm_robo_attach(ch->sih, ch, ch->vars, ++ (miird_f)bcmgmac_et_chops.phyrd, ++ (miiwr_f)bcmgmac_et_chops.phywr))) { ++ ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit)); ++ goto fail; ++ } ++ if (etc->switch_mode) { ++ printf("et%d: %s: bringing up robo switch\n", ch->etc->unit, __FUNCTION__); ++ /* Enable the switch and set it to a known good state */ ++ if (bcm_robo_enable_device(etc->robo)) { ++ ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit)); ++ goto fail; ++ } ++ /* Configure the switch to do VLAN */ ++ if ((boardflags & BFL_ENETVLAN) && ++ bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) { ++ ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit)); ++ goto fail; ++ } ++ /* Enable switching/forwarding */ ++ if (bcm_robo_enable_switch(etc->robo)) { ++ ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit)); ++ goto fail; ++ } ++ robo_reset_mib(etc->robo); ++ } ++ } ++#endif /* ETROBO */ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (gmac_last_interface(etc->unit)) { ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(etc->unit, 3); ++ serdes_start_pll(etc->unit, 1); ++ } ++ ++ if (etc->forcespeed == ET_AUTO) { ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ etc->advertise2 = ADV_1000FULL; ++ } ++#endif ++#if defined(CONFIG_MACH_HR2) ++ if (etc->forcespeed == ET_AUTO) { ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ } ++#endif ++ return ((void *) ch); ++ ++fail: ++ chipdetach(ch); ++ return (NULL); ++} ++ ++static void ++chipdetach(ch_t *ch) ++{ ++ int32 i; ++ ++ ET_TRACE(("et%d: chipdetach\n", ch->etc->unit)); ++ ++ if (ch == NULL) ++ return; ++ ++#ifdef ETROBO ++ /* free robo state */ ++ if (ch->etc->robo) ++ bcm_robo_detach(ch->etc->robo); ++#endif /* ETROBO */ ++ ++ /* free dma state */ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] != NULL) { ++ dma_detach(ch->di[i]); ++ ch->di[i] = NULL; ++ } ++ ++ /* put the core back into reset */ ++ if (ch->sih) ++ si_core_disable(ch->sih, 0); ++ ++ if (ch->etc) ++ if (ch->etc->mib) ++ ch->etc->mib = NULL; ++ ++ /* free si handle */ ++ if (ch->sih) { ++ si_detach(ch->sih); ++ ch->sih = NULL; ++ } ++ ++ /* free vars */ ++ if (ch->vars) ++ MFREE(ch->osh, ch->vars, ch->vars_size); ++ ++ /* free chip private state */ ++ MFREE(ch->osh, ch, sizeof(ch_t)); ++} ++ ++static void ++chiplongname(ch_t *ch, char *buf, uint bufsize) ++{ ++ char *s; ++ ++ switch (ch->etc->deviceid) { ++ case BCM53010_CHIP_ID: ++ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM53020_CHIP_ID: ++ s = "Broadcom BCM5302x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM56150_CHIP_ID: ++ s = "Broadcom BCM5615x 10/100 Mbps Ethernet Controller"; ++ break; ++ case BCM56340_CHIP_ID: ++ s = "Broadcom BCM5634x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM56450_CHIP_ID: ++ s = "Broadcom BCM5645x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM47XX_GMAC_ID: ++ case BCM4716_CHIP_ID: ++ case BCM4748_CHIP_ID: ++ default: ++ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ } ++ ++ strncpy(buf, s, bufsize); ++ buf[bufsize - 1] = '\0'; ++} ++ ++#ifdef ETROBO ++extern void robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b); ++#endif ++ ++static void ++chipdump(ch_t *ch, struct bcmstrbuf *b) ++{ ++ /* int32 i; */ ++ ++ bcm_bprintf(b, "regs 0x%lx etphy 0x%lx ch->intstatus 0x%x intmask 0x%x\n", ++ (ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask); ++ bcm_bprintf(b, "\n"); ++ ++ ++ /* registers */ ++ chipdumpregs(ch, ch->regs, b); ++ bcm_bprintf(b, "\n"); ++ ++ /* switch registers */ ++#ifdef ETROBO ++ if (ch->etc->robo) { ++ robo_dump_regs(ch->etc->robo, b); ++ robo_bprintf_mib(ch->etc->robo, b); ++ } ++ ++#endif /* ETROBO */ ++} ++ ++ ++#define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->name)) ++#define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->mib.name)) ++ ++static void ++chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b) ++{ ++ uint phyaddr; ++ ++ phyaddr = ch->etc->phyaddr; ++ ++ PRREG(devcontrol); PRREG(devstatus); ++ bcm_bprintf(b, "\n"); ++ PRREG(biststatus); ++ bcm_bprintf(b, "\n"); ++ PRREG(intstatus); PRREG(intmask); PRREG(gptimer); ++ bcm_bprintf(b, "\n"); ++ PRREG(intrecvlazy); ++ bcm_bprintf(b, "\n"); ++ PRREG(flowctlthresh); PRREG(wrrthresh); PRREG(gmac_idle_cnt_thresh); ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRREG(phyaccess); PRREG(phycontrol); ++ bcm_bprintf(b, "\n"); ++ } ++ PRREG(txqctl); PRREG(rxqctl); ++ bcm_bprintf(b, "\n"); ++ PRREG(gpioselect); PRREG(gpio_output_en); ++ bcm_bprintf(b, "\n"); ++ PRREG(clk_ctl_st); PRREG(pwrctl); ++ bcm_bprintf(b, "\n"); ++ ++ /* unimac registers */ ++ PRREG(hdbkpctl); ++ bcm_bprintf(b, "\n"); ++ PRREG(cmdcfg); ++ bcm_bprintf(b, "\n"); ++ PRREG(macaddrhigh); PRREG(macaddrlow); ++ bcm_bprintf(b, "\n"); ++ PRREG(rxmaxlength); PRREG(pausequanta); PRREG(macmode); ++ bcm_bprintf(b, "\n"); ++ PRREG(outertag); PRREG(innertag); PRREG(txipg); PRREG(pausectl); ++ bcm_bprintf(b, "\n"); ++ PRREG(txflush); PRREG(rxstatus); PRREG(txstatus); ++ bcm_bprintf(b, "\n"); ++ ++ /* mib registers */ ++ PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols); ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts); ++ bcm_bprintf(b, "\n"); ++ } ++ ++ PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_jabber_pkts); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize); ++ } ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts); ++ bcm_bprintf(b, "\n"); ++ } ++ if (phyaddr != EPHY_NOREG) { ++ /* print a few interesting phy registers */ ++ bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n", ++ chipphyrd(ch, phyaddr, 0), ++ chipphyrd(ch, phyaddr, 1), ++ chipphyrd(ch, phyaddr, 2), ++ chipphyrd(ch, phyaddr, 3)); ++ bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n", ++ chipphyrd(ch, phyaddr, 4), ++ chipphyrd(ch, phyaddr, 5), ++ chipphyrd(ch, phyaddr, 24), ++ chipphyrd(ch, phyaddr, 25)); ++ } ++ ++} ++ ++static void ++gmac_clearmib(ch_t *ch) ++{ ++ volatile uint32 *ptr; ++ ++ if (ch->etc->corerev == GMAC_4706B0_CORE_REV) ++ return; ++ ++ /* enable clear on read */ ++ OR_REG(ch->osh, &ch->regs->devcontrol, DC_MROR); ++ ++ for (ptr = &ch->regs->mib.tx_good_octets; ptr <= &ch->regs->mib.rx_uni_pkts; ptr++) { ++ (void)R_REG(ch->osh, ptr); ++ if (ptr == &ch->regs->mib.tx_q3_octets_high) ++ ptr++; ++ } ++ ++ return; ++} ++ ++static void ++gmac_init_reset(ch_t *ch) ++{ ++ OR_REG(ch->osh, &ch->regs->cmdcfg, CC_SR); ++ OSL_DELAY(GMAC_RESET_DELAY); ++} ++ ++static void ++gmac_clear_reset(ch_t *ch) ++{ ++ AND_REG(ch->osh, &ch->regs->cmdcfg, ~CC_SR); ++ OSL_DELAY(GMAC_RESET_DELAY); ++} ++ ++static void ++gmac_reset(ch_t *ch) ++{ ++ uint32 ocmdcfg, cmdcfg; ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* initialize default config */ ++ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | ++ CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | CC_PAD_EN | CC_PF); ++ cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= (CC_AE | CC_OT | CC_OR); ++#endif ++ ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ cmdcfg |= 0xc; ++#endif ++ ++ if (cmdcfg != ocmdcfg) ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static void ++gmac_promisc(ch_t *ch, bool mode) ++{ ++ uint32 cmdcfg; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* enable or disable promiscuous mode */ ++ if (mode) ++ cmdcfg |= CC_PROM; ++ else ++ cmdcfg &= ~CC_PROM; ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static int ++gmac_speed(ch_t *ch, uint32 speed) ++{ ++ uint32 cmdcfg; ++ uint32 hd_ena = 0; ++ ++ switch (speed) { ++ case ET_10HALF: ++ hd_ena = CC_HD; ++ /* FALLTHRU */ ++ ++ case ET_10FULL: ++ speed = 0; ++ break; ++ ++ case ET_100HALF: ++ hd_ena = CC_HD; ++ /* FALLTHRU */ ++ ++ case ET_100FULL: ++ speed = 1; ++ break; ++ ++ case ET_1000FULL: ++ speed = 2; ++ break; ++ ++ case ET_1000HALF: ++ ET_ERROR(("et%d: gmac_speed: supports 1000 mbps full duplex only\n", ++ ch->etc->unit)); ++ return (FAILURE); ++ ++ case ET_2500FULL: ++ speed = 3; ++ break; ++ ++ default: ++ ET_ERROR(("et%d: gmac_speed: speed %d not supported\n", ++ ch->etc->unit, speed)); ++ return (FAILURE); ++ } ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* set the speed */ ++ cmdcfg &= ~(CC_ES_MASK | CC_HD); ++ cmdcfg |= ((speed << CC_ES_SHIFT) | hd_ena); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= CC_AE; ++#endif ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ return (SUCCESS); ++} ++ ++static void ++gmac_macloopback(ch_t *ch, bool on) ++{ ++ uint32 ocmdcfg, cmdcfg; ++ ++ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* set/clear the mac loopback mode */ ++ if (on) ++ cmdcfg |= CC_ML; ++ else ++ cmdcfg &= ~CC_ML; ++ ++ if (cmdcfg != ocmdcfg) ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static int ++gmac_loopback(ch_t *ch, uint32 mode) ++{ ++ switch (mode) { ++ case LOOPBACK_MODE_DMA: ++ /* to enable loopback for any channel set the loopback ++ * enable bit in xmt0control register. ++ */ ++ dma_fifoloopbackenable(ch->di[TX_Q0]); ++ break; ++ ++ case LOOPBACK_MODE_MAC: ++ gmac_macloopback(ch, TRUE); ++ break; ++ ++ case LOOPBACK_MODE_NONE: ++ gmac_macloopback(ch, FALSE); ++ break; ++ ++ default: ++ ET_ERROR(("et%d: gmac_loopaback: Unknown loopback mode %d\n", ++ ch->etc->unit, mode)); ++ return (FAILURE); ++ } ++ ++ return (SUCCESS); ++} ++ ++static void ++gmac_enable(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ gmacregs_t *regs; ++ ++ regs = ch->regs; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ cmdcfg |= CC_SR; ++ ++ /* first deassert rx_ena and tx_ena while in reset */ ++ cmdcfg &= ~(CC_RE | CC_TE); ++ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ /* enable the mac transmit and receive paths now */ ++ OSL_DELAY(2); ++ cmdcfg &= ~CC_SR; ++ cmdcfg |= (CC_RE | CC_TE); ++ ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ cmdcfg |= 0xc; ++#endif ++ ++ /* assert rx_ena and tx_ena when out of reset to enable the mac */ ++ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); ++ ++ /* request ht clock */ ++ OR_REG(ch->osh, ®s->clk_ctl_st, CS_FH); ++ ++ return; ++} ++ ++static void ++gmac_txflowcontrol(ch_t *ch, bool on) ++{ ++ uint32 cmdcfg; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* to enable tx flow control clear the rx pause ignore bit */ ++ if (on) ++ cmdcfg &= ~CC_RPI; ++ else ++ cmdcfg |= CC_RPI; ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void ++gmac_serdes_init(ch_t *ch) ++{ ++ uint32_t sdctl, sdstat0, sdstat1; ++ gmacregs_t *regs; ++ ++ regs = ch->regs; ++ ++ ET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); ++ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); ++ //printf("et%d: %s read sdstat0(0x%x); sdstat1(0x%x)\n", ch->etc->unit, __FUNCTION__, sdstat0, sdstat1); ++ ++ /* ++ * Bring up both digital and analog clocks ++ * ++ * NOTE: Many MAC registers are not accessible until the PLL is locked. ++ * An S-Channel timeout will occur before that. ++ */ ++ ++ sdctl = 0; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ sdctl |= (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL|SC_REFSEL_VAL|SC_REF_TERM_SEL_MASK); ++#else ++ sdctl |= (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL|SC_REF_TERM_SEL_MASK); ++#endif /* (defined(CONFIG_MACH_HX4) */ ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_IDDQ_MASK|SC_PWR_DOWN_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl &= ~(SC_IDDQ_MASK|SC_PWR_DOWN_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ /* Bring hardware out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_HW_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ /* Bring MDIOREGS out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_MDIOREGS_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ /* Bring PLL out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_PLL_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); ++ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); ++ //printf("et%d: %s read sdstat0(0x%x); sdstat1(0x%x)\n", ch->etc->unit, __FUNCTION__, sdstat0, sdstat1); ++ ++ return; ++} ++#endif ++ ++static void ++gmac_miiconfig(ch_t *ch) ++{ ++ /* BCM53010 GMAC DevStatus register has different definition of "Interface Mode" ++ * Bit 12:8 "interface_mode" This field is programmed through IDM control bits [6:2] ++ * ++ * Bit 0 : SOURCE_SYNC_MODE_EN - If set, Rx line clock input will be used by Unimac for ++ * sampling data.If this is reset, PLL reference clock (Clock 250 or Clk 125 based ++ * on CLK_250_SEL) will be used as receive side line clock. ++ * Bit 1 : DEST_SYNC_MODE_EN - If this is reset, PLL reference clock input (Clock 250 or ++ * Clk 125 based on CLK_250_SEL) will be used as transmit line clock. ++ * If this is set, TX line clock input (from external switch/PHY) is used as ++ * transmit line clock. ++ * Bit 2 : TX_CLK_OUT_INVERT_EN - If set, this will invert the TX clock out of AMAC. ++ * Bit 3 : DIRECT_GMII_MODE - If direct gmii is set to 0, then only 25 MHz clock needs to ++ * be fed at 25MHz reference clock input, for both 10/100 Mbps speeds. ++ * Unimac will internally divide the clock to 2.5 MHz for 10 Mbps speed ++ * Bit 4 : CLK_250_SEL - When set, this selects 250Mhz reference clock input and hence ++ * Unimac line rate will be 2G. ++ * If reset, this selects 125MHz reference clock input. ++ */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ if (ch->etc->forcespeed == ET_AUTO) ++#if defined(CONFIG_MACH_HR2) ++ gmac_speed(ch, ET_100FULL); ++#elif (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++ gmac_speed(ch, ET_2500FULL); ++#else ++ gmac_speed(ch, ET_1000FULL); ++#endif ++ else ++ gmac_speed(ch, ch->etc->forcespeed); ++ } ++} ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++void ++gmac_serdes_asym_mode(etc_info_t *etcptrs[]) ++{ ++ etc_info_t *etc; ++ ++ etc = etcptrs[0]; ++ ++ /* initialize serdes */ ++ gmac_serdes_init(etc->ch); ++ serdes_reset_core(etc->unit, etc->phyaddr); ++ ++ /* initialize lane 0 */ ++ //printk("et%d %s() phyaddr=%d, speed=%d, dpx=%d\n", etc->unit, __FUNCTION__, etc->phyaddr, etc->speed, etc->duplex); ++ serdes_set_asym_mode(etc->unit, etc->phyaddr); ++ serdes_init(etc->unit, etc->phyaddr); ++ serdes_speeddpx_set(etc->unit, etc->phyaddr, etc->speed, etc->duplex); ++ /* initialize lane 1 */ ++ etc = etcptrs[1]; ++ if (etc->linkstate) { ++ //printk("et%d %s() phyaddr=%d, speed=%d, dpx=%d\n", etc->unit, __FUNCTION__, etc->phyaddr, etc->speed, etc->duplex); ++ serdes_set_asym_mode(etc->unit, etc->phyaddr); ++ serdes_init(etc->unit, etc->phyaddr); ++ serdes_speeddpx_set(etc->unit, etc->phyaddr, etc->speed, etc->duplex); ++ } ++ ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(etc->unit, 3); ++ ++ /* start PLL */ ++ serdes_start_pll(etc->unit, 1); ++} ++#endif /* (!defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++static void ++chipreset(ch_t *ch) ++{ ++ gmacregs_t *regs; ++ uint32 i, sflags, flagbits = 0; ++ ++ ET_TRACE(("et%d: chipreset\n", ch->etc->unit)); ++ ++ regs = ch->regs; ++ ++ if (!si_iscoreup(ch->sih)) { ++ /* power on reset: reset the enet core */ ++ goto chipinreset; ++ } ++ ++ /* Northstar, reset other three GMAC cores if needed */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ int ns_gmac; ++ for (ns_gmac = 0; ns_gmac < IPROC_NUM_GMACS; ns_gmac++) { ++ /* As northstar requirement, we have to reset all GAMCs before accessing them. ++ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. ++ * then the other three GAMC didn't reset. ++ * We do it here. ++ */ ++ si_setcore(ch->sih, GMAC_CORE_ID, ns_gmac); ++ if (!si_iscoreup(ch->sih)) { ++ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, ns_gmac)); ++ si_core_reset(ch->sih, flagbits, 0); ++ } ++ } ++ si_setcore(ch->sih, GMAC_CORE_ID, 0); ++ } ++ ++ /* update software counters before resetting the chip */ ++ if (ch->mibgood) ++ chipstatsupd(ch); ++ ++ /* reset the tx dma engines */ ++ for (i = 0; i < NUMTXQ; i++) { ++ if (ch->di[i]) { ++ ET_TRACE(("et%d: resetting tx dma%d\n", ch->etc->unit, i)); ++ dma_txreset(ch->di[i]); ++ } ++ } ++ ++ /* set gmac into loopback mode to ensure no rx traffic */ ++ gmac_loopback(ch, LOOPBACK_MODE_MAC); ++ OSL_DELAY(1); ++ ++ /* reset the rx dma engine */ ++ if (ch->di[RX_Q0]) { ++ ET_TRACE(("et%d: resetting rx dma\n", ch->etc->unit)); ++ dma_rxreset(ch->di[RX_Q0]); ++ } ++ ++ /* clear the multicast filter table */ ++ gmac_mf_cleanup(ch); ++ ++chipinreset: ++ sflags = si_core_sflags(ch->sih, 0, 0); ++ if (sflags & SISF_SW_ATTACHED) { ++ ET_TRACE(("et%d: internal switch attached\n", ch->etc->unit)); ++ flagbits = SICF_SWCLKE; ++ if (!ch->etc->robo) { ++ ET_TRACE(("et%d: reseting switch\n", ch->etc->unit)); ++ flagbits |= SICF_SWRST; ++ } ++ } ++ ++ /* reset all GMAC cores */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ int ns_gmac; ++ for (ns_gmac = 0; ns_gmac < IPROC_NUM_GMACS; ns_gmac++) { ++ /* As northstar requirement, we have to reset all GAMCs before accessing them. ++ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. ++ * then the other three GAMC didn't reset. ++ * We do it here. ++ */ ++ si_setcore(ch->sih, GMAC_CORE_ID, ns_gmac); ++ if (!si_iscoreup(ch->sih)) { ++ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, ns_gmac)); ++ si_core_reset(ch->sih, flagbits, 0); ++ } ++ } ++ si_setcore(ch->sih, GMAC_CORE_ID, 0); ++ } ++ ++ if ((sflags & SISF_SW_ATTACHED) && (!ch->etc->robo)) { ++ ET_TRACE(("et%d: taking switch out of reset\n", ch->etc->unit)); ++ si_core_cflags(ch->sih, SICF_SWRST, 0); ++ } ++ ++ /* reset gmac */ ++ gmac_reset(ch); ++ ++ /* clear mib */ ++ gmac_clearmib(ch); ++ ch->mibgood = TRUE; ++ ++ /* set mdc_transition_en */ ++ OR_REG(ch->osh, ®s->phycontrol, PC_MTE); ++ ++ /* Read the devstatus to figure out the configuration mode of ++ * the interface. Set the speed to 100 if the switch interface ++ * is mii/rmii. ++ */ ++ gmac_miiconfig(ch); ++ ++// /* gmac doesn't have internal phy */ ++// chipphyinit(ch, ch->etc->phyaddr); ++ ++ /* clear persistent sw intstatus */ ++ ch->intstatus = 0; ++} ++ ++/* ++ * Lookup a multicast address in the filter hash table. ++ */ ++static int ++gmac_mf_lkup(ch_t *ch, struct ether_addr *mcaddr) ++{ ++ mflist_t *ptr; ++ ++ /* find the multicast address */ ++ for (ptr = ch->mf.bucket[GMAC_MCADDR_HASH(mcaddr)]; ptr != NULL; ptr = ptr->next) { ++ if (!ETHER_MCADDR_CMP(&ptr->mc_addr, mcaddr)) ++ return (SUCCESS); ++ } ++ ++ return (FAILURE); ++} ++ ++/* ++ * Add a multicast address to the filter hash table. ++ */ ++static int ++gmac_mf_add(ch_t *ch, struct ether_addr *mcaddr) ++{ ++ uint32 hash; ++ mflist_t *entry; ++#ifdef BCMDBG ++ char mac[ETHER_ADDR_STR_LEN]; ++#endif /* BCMDBG */ ++ ++ /* add multicast addresses only */ ++ if (!ETHER_ISMULTI(mcaddr)) { ++ ET_ERROR(("et%d: adding invalid multicast address %s\n", ++ ch->etc->unit, bcm_ether_ntoa(mcaddr, mac))); ++ return (FAILURE); ++ } ++ ++ /* discard duplicate add requests */ ++ if (gmac_mf_lkup(ch, mcaddr) == SUCCESS) { ++ ET_ERROR(("et%d: adding duplicate mcast filter entry\n", ch->etc->unit)); ++ return (FAILURE); ++ } ++ ++ /* allocate memory for list entry */ ++ entry = MALLOC(ch->osh, sizeof(mflist_t)); ++ if (entry == NULL) { ++ ET_ERROR(("et%d: out of memory allocating mcast filter entry\n", ch->etc->unit)); ++ return (FAILURE); ++ } ++ ++ /* add the entry to the hash bucket */ ++ ether_copy(mcaddr, &entry->mc_addr); ++ hash = GMAC_MCADDR_HASH(mcaddr); ++ entry->next = ch->mf.bucket[hash]; ++ ch->mf.bucket[hash] = entry; ++ ++ return (SUCCESS); ++} ++ ++/* ++ * Cleanup the multicast filter hash table. ++ */ ++static void ++gmac_mf_cleanup(ch_t *ch) ++{ ++ mflist_t *ptr, *tmp; ++ int32 i; ++ ++ for (i = 0; i < GMAC_HASHT_SIZE; i++) { ++ ptr = ch->mf.bucket[i]; ++ while (ptr) { ++ tmp = ptr; ++ ptr = ptr->next; ++ MFREE(ch->osh, tmp, sizeof(mflist_t)); ++ } ++ ch->mf.bucket[i] = NULL; ++ } ++} ++ ++/* ++ * Initialize all the chip registers. If dma mode, init tx and rx dma engines ++ * but leave the devcontrol tx and rx (fifos) disabled. ++ */ ++static void ++chipinit(ch_t *ch, uint options) ++{ ++ etc_info_t *etc; ++ gmacregs_t *regs; ++ uint idx; ++ uint i; ++#ifdef CONFIG_BCM_CUSTOM_RECVFILE_MAX_PERF ++ uint bp_clk; ++ uint32_t fpi = 8; ++#endif ++ ++ regs = ch->regs; ++ etc = ch->etc; ++ idx = 0; ++ ++ ET_TRACE(("et%d: chipinit\n", etc->unit)); ++ ++#ifdef CONFIG_BCM_CUSTOM_RECVFILE_MAX_PERF ++ /* enable rx lazy interrupt. set frame count and timeout */ ++ bp_clk = si_clock(ch->sih) / 1000000; ++ W_REG(ch->osh, ®s->intrecvlazy, (fpi << IRL_FC_SHIFT) | (48 * bp_clk)); ++#else ++ /* enable one rx interrupt per received frame */ ++ W_REG(ch->osh, ®s->intrecvlazy, (1 << IRL_FC_SHIFT)); ++#endif ++ ++ /* enable 802.3x tx flow control (honor received PAUSE frames) */ ++ gmac_txflowcontrol(ch, TRUE); ++ ++ /* enable/disable promiscuous mode */ ++ gmac_promisc(ch, etc->promisc); ++ ++ /* set our local address */ ++ W_REG(ch->osh, ®s->macaddrhigh, ++ hton32(*(uint32 *)&etc->cur_etheraddr.octet[0])); ++ W_REG(ch->osh, ®s->macaddrlow, ++ hton16(*(uint16 *)&etc->cur_etheraddr.octet[4])); ++ ++ if (!etc->promisc) { ++ /* gmac doesn't have a cam, hence do the multicast address filtering ++ * in the software ++ */ ++ /* allmulti or a list of discrete multicast addresses */ ++ if (!etc->allmulti && etc->nmulticast) ++ for (i = 0; i < etc->nmulticast; i++) ++ (void)gmac_mf_add(ch, &etc->multicast[i]); ++ } ++ ++ /* optionally enable mac-level loopback */ ++ if (etc->loopbk) ++ gmac_loopback(ch, LOOPBACK_MODE_MAC); ++ else ++ gmac_loopback(ch, LOOPBACK_MODE_NONE); ++ ++ /* set max frame lengths - account for possible vlan tag */ ++ W_REG(ch->osh, ®s->rxmaxlength, BCM_ETHER_MAX_LEN); ++ ++ /* ++ * Optionally, disable phy autonegotiation and force our speed/duplex ++ * or constrain our advertised capabilities. ++ */ ++ if (etc->forcespeed != ET_AUTO) { ++ gmac_speed(ch, etc->forcespeed); ++ chipphyforce(ch, etc->phyaddr); ++ } else if (etc->advertise && etc->needautoneg) ++ chipphyadvertise(ch, etc->phyaddr); ++ ++ /* enable the overflow continue feature and disable parity */ ++ dma_ctrlflags(ch->di[0], DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */, ++ DMA_CTRL_ROC /* value */); ++ ++ if (options & ET_INIT_FULL) { ++ /* initialize the tx and rx dma channels */ ++ for (i = 0; i < NUMTXQ; i++) ++ dma_txinit(ch->di[i]); ++ dma_rxinit(ch->di[RX_Q0]); ++ ++ /* post dma receive buffers */ ++ dma_rxfill(ch->di[RX_Q0]); ++ ++ /* lastly, enable interrupts */ ++ if (options & ET_INIT_INTRON) ++ et_intrson(etc->et); ++ } ++ else ++ dma_rxenable(ch->di[RX_Q0]); ++ ++ /* turn on the emac */ ++ gmac_enable(ch); ++} ++ ++/* dma transmit */ ++static bool BCMFASTPATH ++chiptx(ch_t *ch, void *p0) ++{ ++ int error, len; ++ uint32 q = TX_Q0; ++ ++ ET_TRACE(("et%d: chiptx\n", ch->etc->unit)); ++ ET_LOG("et%d: chiptx", ch->etc->unit, 0); ++ ++ len = PKTLEN(ch->osh, p0); ++ ++ /* check tx max length */ ++ if (len > BCM_ETHER_MAX_LEN) { ++ ET_ERROR(("et%d: chiptx: max frame length exceeded\n", ++ ch->etc->unit)); ++ PKTFREE(ch->osh, p0, TRUE); ++ return FALSE; ++ } ++ ++ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) ++ PKTSETLEN(ch->osh, p0, GMAC_MIN_FRAMESIZE); ++ ++#if defined(CONFIG_MACH_NS) ++ /* queue the packet based on its priority */ ++#ifdef GMAC3 ++ //q = (ch->etc->txQId++) % NUMTXQ; ++ //q = ch->etc->unit; ++ if (DEV_FWDER(ch->etc)) { ++ q = TX_Q0; ++ } else { ++ if (ch->etc->qos) ++ q = etc_up2tc(PKTPRIO(p0)); ++ else ++ q = TX_Q0; ++ } ++#else /* !GMAC3 */ ++ if (ch->etc->qos) ++ q = etc_up2tc(PKTPRIO(p0)); ++#endif /* !GMAC3 */ ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ASSERT(q < NUMTXQ); ++ ++ /* if tx completion intr is disabled then do the reclaim ++ * once every few frames transmitted. ++ */ ++ if ((ch->etc->txframes[q] & ch->etc->txrec_thresh) == 1) ++ dma_txreclaim(ch->di[q], HNDDMA_RANGE_TRANSMITTED); ++ ++ error = dma_txfast(ch->di[q], p0, TRUE); ++ ++ if (error) { ++ ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit)); ++ ch->etc->txnobuf++; ++ return FALSE; ++ } ++ ++ ch->etc->txframes[q]++; ++ ++ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) { ++ if (skb_is_nonlinear((struct sk_buff*)p0)) ++ printk("Modified nonlinear skb (et_ctf_pipeline_loopback) - not calling skb_trim\n"); ++ else ++ /* set back the orig length */ ++ PKTSETLEN(ch->osh, p0, len); ++ } ++ ++ return TRUE; ++} ++ ++/* reclaim completed transmit descriptors and packets */ ++static void BCMFASTPATH ++chiptxreclaim(ch_t *ch, bool forceall) ++{ ++ int32 i; ++ ++ ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit)); ++ ++ for (i = 0; i < NUMTXQ; i++) { ++ dma_txreclaim(ch->di[i], forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED); ++ ch->intstatus &= ~(I_XI0 << i); ++ } ++} ++ ++/* dma receive: returns a pointer to the next frame received, or NULL if there are no more */ ++static void * BCMFASTPATH ++chiprx(ch_t *ch) ++{ ++ void *p; ++ struct ether_addr *da; ++ ++ ET_TRACE(("et%d: chiprx\n", ch->etc->unit)); ++ ET_LOG("et%d: chiprx", ch->etc->unit, 0); ++ ++ if (dma_rxstopped(ch->di[RX_Q0])) { ++ ch->etc->rxdmastopped++; ++ } ++ ++ /* gmac doesn't have a cam to do address filtering. so we implement ++ * the multicast address filtering here. ++ */ ++ while ((p = dma_rx(ch->di[RX_Q0])) != NULL) { ++ /* check for overflow error packet */ ++ if (RXH_FLAGS(ch->etc, PKTDATA(ch->osh, p)) & GRXF_OVF) { ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rxoflodiscards++; ++ continue; ++ } ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ //printf("et%d: chiprx RXH_PT(0x%x)\n", ch->etc->unit, RXH_PT(ch->etc, PKTDATA(ch->osh, p))); ++ if (ch->etc->rl_stopping_broadcasts) { ++ /* check if broadcast packet */ ++ if (RXH_PT(ch->etc, PKTDATA(ch->osh, p)) == 2) { ++ /* broadcast packet */ ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rl_dropped_bc_packets++; ++ ch->etc->rl_dropped_packets++; ++ continue; ++ } ++ } else if (ch->etc->rl_stopping_all_packets) { ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rl_dropped_all_packets++; ++ ch->etc->rl_dropped_packets++; ++ continue; ++ } ++#endif /* GMAC_RATE_LIMITING */ ++ ++ if (ch->etc->allmulti) { ++ return (p); ++ } ++ else { ++ /* skip the rx header */ ++ PKTPULL(ch->osh, p, HWRXOFF); ++ ++ /* do filtering only for multicast packets when allmulti is false */ ++ da = (struct ether_addr *)PKTDATA(ch->osh, p); ++ if (!ETHER_ISMULTI(da) || ++ (gmac_mf_lkup(ch, da) == SUCCESS) || ETHER_ISBCAST(da)) { ++ PKTPUSH(ch->osh, p, HWRXOFF); ++ return (p); ++ } ++ PKTFREE(ch->osh, p, FALSE); ++ } ++ } ++ ++ ch->intstatus &= ~I_RI; ++ ++ /* post more rx buffers since we consumed a few */ ++ dma_rxfill(ch->di[RX_Q0]); ++ ++ return (NULL); ++} ++ ++/* reclaim completed dma receive descriptors and packets */ ++static void ++chiprxreclaim(ch_t *ch) ++{ ++ ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit)); ++ dma_rxreclaim(ch->di[RX_Q0]); ++ ch->intstatus &= ~I_RI; ++} ++ ++/* allocate and post dma receive buffers */ ++static void BCMFASTPATH ++chiprxfill(ch_t *ch) ++{ ++ ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit)); ++ ET_LOG("et%d: chiprxfill", ch->etc->unit, 0); ++ dma_rxfill(ch->di[RX_Q0]); ++} ++ ++ ++/* get current and pending interrupt events */ ++static int BCMFASTPATH ++chipgetintrevents(ch_t *ch, bool in_isr) ++{ ++ uint32 intstatus; ++ int events; ++ ++ events = 0; ++ ++ /* read the interrupt status register */ ++ intstatus = R_REG(ch->osh, &ch->regs->intstatus); ++ ++ /* defer unsolicited interrupts */ ++ intstatus &= (in_isr ? ch->intmask : ch->def_intmask); ++ ++ if (intstatus != 0) ++ events = INTR_NEW; ++ ++ /* or new bits into persistent intstatus */ ++ intstatus = (ch->intstatus |= intstatus); ++ ++ /* return if no events */ ++ if (intstatus == 0) ++ return (0); ++ ++ /*check_errs(ch);*/ ++ ++ /* convert chip-specific intstatus bits into generic intr event bits */ ++ if (intstatus & I_RI) ++ events |= INTR_RX; ++ if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) ++ events |= INTR_TX; ++ if (intstatus & I_ERRORS) ++ events |= INTR_ERROR; ++ ++ return (events); ++} ++ ++/* enable chip interrupts */ ++static void BCMFASTPATH ++chipintrson(ch_t *ch) ++{ ++ ch->intmask = ch->def_intmask; ++ W_REG(ch->osh, &ch->regs->intmask, ch->intmask); ++} ++ ++/* disable chip interrupts */ ++static void BCMFASTPATH ++chipintrsoff(ch_t *ch) ++{ ++ /* disable further interrupts from gmac */ ++ W_REG(ch->osh, &ch->regs->intmask, 0); ++ (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */ ++ ch->intmask = 0; ++ ++ /* clear the interrupt conditions */ ++ W_REG(ch->osh, &ch->regs->intstatus, ch->intstatus); ++} ++ ++/* return true of caller should re-initialize, otherwise false */ ++static bool BCMFASTPATH ++chiperrors(ch_t *ch) ++{ ++ uint32 intstatus; ++ etc_info_t *etc; ++ ++ etc = ch->etc; ++ ++ intstatus = ch->intstatus; ++ ch->intstatus &= ~(I_ERRORS); ++ ++ ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus)); ++ ++ if (intstatus & I_PDEE) { ++ ET_ERROR(("et%d: descriptor error\n", etc->unit)); ++ etc->dmade++; ++ } ++ ++ if (intstatus & I_PDE) { ++ ET_ERROR(("et%d: data error\n", etc->unit)); ++ etc->dmada++; ++ } ++ ++ if (intstatus & I_DE) { ++ ET_ERROR(("et%d: descriptor protocol error\n", etc->unit)); ++ etc->dmape++; ++ } ++ ++ if (intstatus & I_RDU) { ++ ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit)); ++ etc->rxdmauflo++; ++ } ++ ++ if (intstatus & I_RFO) { ++ ET_TRACE(("et%d: receive fifo overflow\n", etc->unit)); ++ etc->rxoflo++; ++ } ++ ++ if (intstatus & I_XFU) { ++ ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit)); ++ etc->txuflo++; ++ } ++ ++ /* if overflows or decriptors underflow, don't report it ++ * as an error and provoque a reset ++ */ ++ if (intstatus & ~(I_RDU | I_RFO) & I_ERRORS) ++ return (TRUE); ++ ++ return (FALSE); ++} ++ ++static void ++chipstatsupd(ch_t *ch) ++{ ++ etc_info_t *etc; ++ gmacregs_t *regs; ++ volatile uint32 *s; ++ uint32 *d; ++ ++ etc = ch->etc; ++ regs = ch->regs; ++ ++ /* read the mib counters and update the driver maintained software ++ * counters. ++ */ ++ if (etc->corerev != GMAC_4706B0_CORE_REV) { ++ OR_REG(ch->osh, ®s->devcontrol, DC_MROR); ++ for (s = ®s->mib.tx_good_octets, d = &ch->mib.tx_good_octets; ++ s <= ®s->mib.rx_uni_pkts; s++, d++) { ++ *d += R_REG(ch->osh, s); ++ if (s == &ch->regs->mib.tx_q3_octets_high) { ++ s++; ++ d++; ++ } ++ } ++ } ++ ++ ++ /* ++ * Aggregate transmit and receive errors that probably resulted ++ * in the loss of a frame are computed on the fly. ++ * ++ * We seem to get lots of tx_carrier_lost errors when flipping ++ * speed modes so don't count these as tx errors. ++ * ++ * Arbitrarily lump the non-specific dma errors as tx errors. ++ */ ++ etc->txerror = ch->mib.tx_jabber_pkts + ch->mib.tx_oversize_pkts ++ + ch->mib.tx_underruns + ch->mib.tx_excessive_cols ++ + ch->mib.tx_late_cols + etc->txnobuf + etc->dmade ++ + etc->dmada + etc->dmape + etc->txuflo; ++ etc->rxerror = ch->mib.rx_jabber_pkts + ch->mib.rx_oversize_pkts ++ + ch->mib.rx_missed_pkts + ch->mib.rx_crc_align_errs ++ + ch->mib.rx_undersize + ch->mib.rx_crc_errs ++ + ch->mib.rx_align_errs + ch->mib.rx_symbol_errs ++ + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen; ++ etc->rxgiants = (ch->di[RX_Q0])->rxgiants; ++} ++ ++static void ++chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear) ++{ ++ gmacmib_t *m; ++ ++ m = &ch->mib; ++ ++ if (clear) { ++ bzero((char *)m, sizeof(gmacmib_t)); ++ return; ++ } ++ ++ bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d " ++ "tx_oversize_pkts %d\n", ++ m->tx_broadcast_pkts, m->tx_multicast_pkts, ++ m->tx_jabber_pkts, ++ m->tx_oversize_pkts); ++ bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n", ++ m->tx_fragment_pkts, m->tx_underruns); ++ bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d " ++ "tx_excessive_cols %d\n", ++ m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols, ++ m->tx_excessive_cols); ++ bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n", ++ m->tx_late_cols, m->tx_defered, m->tx_carrier_lost, ++ m->tx_pause_pkts); ++ ++ /* receive stat counters */ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d " ++ "rx_oversize_pkts %d\n", ++ m->rx_broadcast_pkts, m->rx_multicast_pkts, ++ m->rx_jabber_pkts, m->rx_oversize_pkts); ++ bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d " ++ "rx_undersize %d\n", ++ m->rx_fragment_pkts, m->rx_missed_pkts, ++ m->rx_crc_align_errs, m->rx_undersize); ++ bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n", ++ m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs); ++ bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n", ++ m->rx_pause_pkts, m->rx_nonpause_pkts); ++} ++ ++void ++etc_chip_mib(etc_info_t *etc) ++{ ++ uint32 *d; ++ ch_t *ch = (ch_t*)etc->ch; ++ ++ chipstatsupd(ch); ++ printk("et%d: txframe:0x%x, txbyte:0x%x txerror:0x%x\n", ch->etc->unit, ++ ch->etc->txframe, ch->etc->txbyte, ch->etc->txerror); ++ printk("et%d: rxframe:0x%x, rxbyte:0x%x rxerror:0x%x\n", ch->etc->unit, ++ ch->etc->rxframe, ch->etc->rxbyte, ch->etc->rxerror); ++ printk("et%d: RXDMA: ctrl(0x%x), ptr(0x%x), addrl(0x%x), addrh(0x%x) st0(0x%x), st1(0x%x)\n", ++ ch->etc->unit, ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.control), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.ptr), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.addrlow), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.addrhigh), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status0), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status1)); ++ ++ /* clear counters */ ++ for (d = &ch->mib.tx_good_octets; d <= &ch->mib.rx_uni_pkts; d++) { ++ *d = 0; ++ if (d == &ch->mib.tx_q3_octets_high) { ++ d++; ++ } ++ } ++} ++ ++static void ++chipenablepme(ch_t *ch) ++{ ++ return; ++} ++ ++static void ++chipdisablepme(ch_t *ch) ++{ ++ return; ++} ++ ++static void ++chipduplexupd(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ int32 duplex, speed; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* check if duplex mode changed */ ++ if (ch->etc->duplex && (cmdcfg & CC_HD)) ++ duplex = 0; ++ else if (!ch->etc->duplex && ((cmdcfg & CC_HD) == 0)) ++ duplex = CC_HD; ++ else ++ duplex = -1; ++ ++ /* check if the speed changed */ ++ speed = ((cmdcfg & CC_ES_MASK) >> CC_ES_SHIFT); ++ if ((ch->etc->speed == 1000) && (speed != 2)) ++ speed = 2; ++ else if ((ch->etc->speed == 100) && (speed != 1)) ++ speed = 1; ++ else if ((ch->etc->speed == 10) && (speed != 0)) ++ speed = 0; ++ else ++ speed = -1; ++ ++ /* no duplex or speed change required */ ++ if ((speed == -1) && (duplex == -1)) { ++ return; ++ } ++ ++ /* update the speed */ ++ if (speed != -1) { ++ cmdcfg &= ~CC_ES_MASK; ++ cmdcfg |= (speed << CC_ES_SHIFT); ++ } ++ ++ /* update the duplex mode */ ++ if (duplex != -1) { ++ cmdcfg &= ~CC_HD; ++ cmdcfg |= duplex; ++ } ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= CC_AE; ++#endif ++ ++ ET_TRACE(("chipduplexupd: updating speed & duplex %x\n", cmdcfg)); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++static void ++chipforcespddpx(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ int32 duplex=0, speed; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* set duplex */ ++ if (!ch->etc->duplex) ++ duplex = CC_HD; ++ ++ /* set speed */ ++ if (ch->etc->speed == 10) ++ speed = 0; ++ else if (ch->etc->speed == 100) ++ speed = 1; ++ else ++ speed = 2; ++ ++ /* update the speed */ ++ cmdcfg &= ~CC_ES_MASK; ++ cmdcfg |= (speed << CC_ES_SHIFT); ++ ++ /* update the duplex mode */ ++ cmdcfg &= ~CC_HD; ++ cmdcfg |= duplex; ++ ++ ET_TRACE(("chipforcespddpx: forcing speed & duplex %x\n", cmdcfg)); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ if (ch->etc->up) { ++ serdes_speeddpx_set(ch->etc->unit, ch->etc->phyaddr, ch->etc->speed, ch->etc->duplex); ++ } ++} ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++static uint16 ++chipphyrd(ch_t *ch, uint phyaddr, uint reg) ++{ ++ uint32 tmp = 0xffffffff; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ gmacregs_t *regs; ++ uint32 *phycontrol_addr, *phyaccess_addr; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ASSERT(reg < MAXPHYREG); ++ ++ regs = ch->regs; ++ ++ phycontrol_addr = (uint32 *)®s->phycontrol; ++ phyaccess_addr = (uint32 *)®s->phyaccess; ++ ++ /* issue the read */ ++ tmp = R_REG(ch->osh, phycontrol_addr); ++ tmp &= ~0x1f; ++ tmp |= phyaddr; ++ W_REG(ch->osh, phycontrol_addr, tmp); ++ W_REG(ch->osh, phyaccess_addr, ++ (PA_START | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT))); ++ ++ /* wait for it to complete */ ++ SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000); ++ tmp = R_REG(ch->osh, phyaccess_addr); ++ if (tmp & PA_START) { ++ ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit)); ++ tmp = 0xffff; ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ uint32 addr, int_bus, bank, flags; ++ uint16 tmp16; ++ ++ addr = phyaddr&0xf; ++ int_bus = phyaddr&0xf0; ++ bank = (phyaddr&0x1f00)>>8; ++ flags = (phyaddr&0x10000)?SOC_PHY_REG_1000X:0; ++ ++ if (int_bus) { ++ /* internal serdes */ ++ tmp = serdes_rd_reg(ch->etc->unit, addr, reg); ++ } else { ++ /* external phy */ ++ phy5461_rd_reg(ch->etc->unit, addr, flags, bank, reg, &tmp16); ++ tmp = tmp16; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ uint32 addr, bank; ++ uint16 tmp16; ++ ++ addr = phyaddr&0xf; ++ bank = (phyaddr&0x1f00)>>8; ++ ++ phy5221_rd_reg(ch->etc->unit, addr, bank, reg, &tmp16); ++ tmp = tmp16; ++#endif /* defined(CONFIG_MACH_HR2) */ ++ ++ return (tmp & PA_DATA_MASK); ++} ++ ++static void ++chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v) ++{ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ uint32 tmp; ++ gmacregs_t *regs; ++ uint32 *phycontrol_addr, *phyaccess_addr; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ASSERT(reg < MAXPHYREG); ++ ++ regs = ch->regs; ++ ++ phycontrol_addr = (uint32 *)®s->phycontrol; ++ phyaccess_addr = (uint32 *)®s->phyaccess; ++ ++ /* clear mdioint bit of intstatus first */ ++ tmp = R_REG(ch->osh, phycontrol_addr); ++ tmp &= ~0x1f; ++ tmp |= phyaddr; ++ W_REG(ch->osh, phycontrol_addr, tmp); ++ W_REG(ch->osh, ®s->intstatus, I_MDIO); ++ ASSERT((R_REG(ch->osh, ®s->intstatus) & I_MDIO) == 0); ++ ++ /* issue the write */ ++ W_REG(ch->osh, phyaccess_addr, ++ (PA_START | PA_WRITE | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT) | v)); ++ ++ /* wait for it to complete */ ++ SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000); ++ if (R_REG(ch->osh, phyaccess_addr) & PA_START) { ++ ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit)); ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ uint32 addr, int_bus, bank, flags; ++ ++ addr = phyaddr&0xf; ++ int_bus = phyaddr&0xf0; ++ bank = (phyaddr&0x1f00)>>8; ++ flags = (phyaddr&0x10000)?SOC_PHY_REG_1000X:0; ++ ++ if (int_bus) { ++ /* internal serdes */ ++ serdes_wr_reg(ch->etc->unit, addr, reg, v); ++ } else { ++ /* external phy */ ++ phy5461_wr_reg(ch->etc->unit, addr, flags, bank, reg, &v); ++ } ++#endif ++#if defined(CONFIG_MACH_HR2) ++ uint32 addr, bank; ++ ++ addr = phyaddr&0xf; ++ bank = (phyaddr&0x1f00)>>8; ++ ++ phy5221_wr_reg(ch->etc->unit, addr, bank, reg, &v); ++ ++#endif /* defined(CONFIG_MACH_HR2) */ ++} ++ ++static void ++chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v) ++{ ++ uint16 tmp; ++ ++ tmp = chipphyrd(ch, phyaddr, reg); ++ tmp |= v; ++ chipphywr(ch, phyaddr, reg, tmp); ++} ++ ++static void ++chipphyreset(ch_t *ch, uint phyaddr) ++{ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ ET_TRACE(("et%d: chipphyreset: phyaddr %d\n", ch->etc->unit, phyaddr)); ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++ serdes_reset(ch->etc->unit, phyaddr); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++#endif /* defined(CONFIG_MACH_HR2) */ ++ ++ chipphyinit(ch, phyaddr); ++} ++ ++static void ++chipphyinit(ch_t *ch, uint phyaddr) ++{ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ ET_TRACE(("et%d: chipphyinit: phyaddr %d\n", ch->etc->unit, phyaddr)); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ phy5461_init(ch->etc->unit, phyaddr); ++ serdes_init(ch->etc->unit, phyaddr); ++ if (gmac_last_interface(ch->etc->unit)) { ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(ch->etc->unit, 3); ++ serdes_start_pll(ch->etc->unit, 1); ++ } ++#elif defined(CONFIG_MACH_HR2) ++ phy5221_init(ch->etc->unit, phyaddr); ++#endif ++ ++} ++ ++static void ++chipphyforce(ch_t *ch, uint phyaddr) ++{ ++ etc_info_t *etc; ++ uint16 ctl; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ etc = ch->etc; ++ ++ if (etc->forcespeed == ET_AUTO) ++ return; ++ ++ ET_TRACE(("et%d: chipphyforce: phyaddr %d speed %d\n", ++ ch->etc->unit, phyaddr, etc->forcespeed)); ++ ++ ctl = chipphyrd(ch, phyaddr, 0); ++ ctl &= ~(CTL_SPEED | CTL_SPEED_MSB | CTL_ANENAB | CTL_DUPLEX); ++ ++ switch (etc->forcespeed) { ++ case ET_10HALF: ++ break; ++ ++ case ET_10FULL: ++ ctl |= CTL_DUPLEX; ++ break; ++ ++ case ET_100HALF: ++ ctl |= CTL_SPEED_100; ++ break; ++ ++ case ET_100FULL: ++ ctl |= (CTL_SPEED_100 | CTL_DUPLEX); ++ break; ++ ++ case ET_1000FULL: ++ ctl |= (CTL_SPEED_1000 | CTL_DUPLEX); ++ break; ++ } ++ ++ chipphywr(ch, phyaddr, 0, ctl); ++} ++ ++/* set selected capability bits in autonegotiation advertisement */ ++static void ++chipphyadvertise(ch_t *ch, uint phyaddr) ++{ ++ etc_info_t *etc; ++ uint16 adv, adv2; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ etc = ch->etc; ++ ++ if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg) ++ return; ++ ++ ASSERT(etc->advertise); ++ ++ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d advertise %x\n", ++ ch->etc->unit, phyaddr, etc->advertise)); ++ ++ /* reset our advertised capabilitity bits */ ++ adv = chipphyrd(ch, phyaddr, 4); ++ adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ adv |= etc->advertise; ++ adv |= ADV_PAUSE; ++ chipphywr(ch, phyaddr, 4, adv); ++ ++ adv2 = chipphyrd(ch, phyaddr, 9); ++ adv2 &= ~(ADV_1000FULL | ADV_1000HALF); ++ adv2 |= etc->advertise2; ++ chipphywr(ch, phyaddr, 9, adv2); ++ ++ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d adv %x adv2 %x phyad0 %x\n", ++ ch->etc->unit, phyaddr, adv, adv2, chipphyrd(ch, phyaddr, 0))); ++ ++ /* restart autonegotiation */ ++ chipphyor(ch, phyaddr, 0, CTL_RESTART); ++ etc->needautoneg = FALSE; ++} ++ ++static void ++chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable) ++{ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ phy5461_enable_set(eth_num, phyaddr, enable); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ phy5221_enable_set(eth_num, phyaddr, enable); ++#endif /* defined(CONFIG_MACH_HR2) */ ++} ++ ++#ifdef GMAC_RATE_LIMITING ++void ++etc_check_rate_limiting(etc_info_t *etc, void *pch) ++{ ++ ch_t *ch = (ch_t*)pch; ++ uint32 timediff, bc_pkt_count, all_pkt_count; ++ ++ timediff = ((long)jiffies - (long)(etc->rl_prior_jiffies)); ++ if ((timediff>>5) != 0) { ++ /* 32 or more jiffies have gone by; see if we're seeing too ++ many packets */ ++ if ((timediff>>5) == 1) { ++ /* 32-63 jiffies elapsed */ ++ bc_pkt_count = R_REG(ch->osh, &ch->regs->mib.rx_broadcast_pkts); ++ all_pkt_count = R_REG(ch->osh, &ch->regs->mib.rx_good_pkts); ++ /* account for the dropped broadcast packets */ ++ all_pkt_count -= etc->rl_dropped_bc_packets; ++ ++ if (((bc_pkt_count>>10) != 0) && !(etc->rl_stopping_broadcasts)) { ++ /* 1K or more broadcast packets have arrived in 32-63 jiffies; try to throttle back the incoming packets */ ++ etc->rl_stopping_broadcasts = 1; ++ printf("et%d: %s: stopping broadcasts bc_pkt_count(0x%x)\n", ++ etc->unit, __FUNCTION__, bc_pkt_count); ++ if (!timer_pending(&etc->rl_timer)) { ++ etc->rl_timer.expires = jiffies + HZ; ++ add_timer(&etc->rl_timer); ++ etc->rl_set=TRUE; ++ } ++ } ++ } ++ etc->rl_prior_jiffies = jiffies; ++ } ++} ++#endif /* GMAC_RATE_LIMITING */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h +new file mode 100755 +index 0000000..395de4b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch new file mode 100644 index 00000000..394cd4be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch @@ -0,0 +1,74 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Gigabit Ethernet MAC defines. ++ * ++ * $Id: etcgmac.h 267700 2011-06-19 15:41:07Z $ ++ */ ++#ifndef _etcgmac_h_ ++#define _etcgmac_h_ ++ ++/* chip interrupt bit error summary */ ++#define I_ERRORS (I_PDEE | I_PDE | I_DE | I_RDU | I_RFO | I_XFU) ++#define DEF_INTMASK (I_XI0 | I_XI1 | I_XI2 | I_XI3 | I_RI | I_ERRORS) ++ ++#define GMAC_RESET_DELAY 2 ++ ++#define GMAC_MIN_FRAMESIZE 17 /* gmac can only send frames of ++ * size above 17 octetes. ++ */ ++ ++#define LOOPBACK_MODE_DMA 0 /* loopback the packet at the DMA engine */ ++#define LOOPBACK_MODE_MAC 1 /* loopback the packet at MAC */ ++#define LOOPBACK_MODE_NONE 2 /* no Loopback */ ++ ++#define DMAREG(ch, dir, qnum) ((dir == DMA_TX) ? \ ++ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmaxmt) : \ ++ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmarcv)) ++ ++/* ++ * Add multicast address to the list. Multicast address are maintained as ++ * hash table with chaining. ++ */ ++typedef struct mclist { ++ struct ether_addr mc_addr; /* multicast address to allow */ ++ struct mclist *next; /* next entry */ ++} mflist_t; ++ ++#define GMAC_HASHT_SIZE 16 /* hash table size */ ++#define GMAC_MCADDR_HASH(m) ((((uint8 *)(m))[3] + ((uint8 *)(m))[4] + \ ++ ((uint8 *)(m))[5]) & (GMAC_HASHT_SIZE - 1)) ++ ++#define ETHER_MCADDR_CMP(x, y) ((((uint16 *)(x))[0] ^ ((uint16 *)(y))[0]) | \ ++ (((uint16 *)(x))[1] ^ ((uint16 *)(y))[1]) | \ ++ (((uint16 *)(x))[2] ^ ((uint16 *)(y))[2])) ++ ++#define SUCCESS 0 ++#define FAILURE -1 ++ ++typedef struct mcfilter { ++ /* hash table for multicast filtering */ ++ mflist_t *bucket[GMAC_HASHT_SIZE]; ++} mcfilter_t; ++ ++extern uint32 find_priq(uint32 pri_map); ++ ++#endif /* _etcgmac_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/Makefile b/drivers/bcmdrivers/gmac/src/include/Makefile +new file mode 100755 +index 0000000..42b3b68 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch new file mode 100644 index 00000000..100147fb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_Makefile.patch @@ -0,0 +1,59 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/Makefile +@@ -0,0 +1,53 @@ ++#!/bin/bash ++# ++# This script serves following purpose: ++# ++# 1. It generates native version information by querying ++# automerger maintained database to see where src/include ++# came from ++# 2. For select components, as listed in compvers.sh ++# it generates component version files ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: Makefile 241686 2011-02-19 00:22:45Z $ ++# ++ ++SRCBASE := .. ++ ++TARGETS := epivers.h ++ ++ifdef VERBOSE ++export VERBOSE ++endif ++ ++all release: epivers compvers ++ ++# Generate epivers.h for native branch version ++epivers: ++ bash epivers.sh ++ ++# Generate epivers.h for native branch version ++compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "Generating component versions, if any"; \ ++ bash compvers.sh; \ ++ else \ ++ echo "Skipping component version generation"; \ ++ fi ++ ++# Generate epivers.h for native branch version ++clean_compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "bash compvers.sh clean"; \ ++ bash compvers.sh clean; \ ++ else \ ++ echo "Skipping component version clean"; \ ++ fi ++ ++clean: ++ rm -f $(TARGETS) *.prev ++ ++clean_all: clean clean_compvers ++ ++.PHONY: all release clean epivers compvers clean_compvers +diff --git a/drivers/bcmdrivers/gmac/src/include/aidmp.h b/drivers/bcmdrivers/gmac/src/include/aidmp.h +new file mode 100755 +index 0000000..a8fe0bc diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch new file mode 100644 index 00000000..d236fb0a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_aidmp.h.patch @@ -0,0 +1,389 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/aidmp.h +@@ -0,0 +1,383 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom AMBA Interconnect definitions. ++ * ++ * $Id: aidmp.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _AIDMP_H ++#define _AIDMP_H ++ ++/* Manufacturer Ids */ ++#define MFGID_ARM 0x43b ++#define MFGID_BRCM 0x4bf ++#define MFGID_MIPS 0x4a7 ++ ++/* Component Classes */ ++#define CC_SIM 0 ++#define CC_EROM 1 ++#define CC_CORESIGHT 9 ++#define CC_VERIF 0xb ++#define CC_OPTIMO 0xd ++#define CC_GEN 0xe ++#define CC_PRIMECELL 0xf ++ ++/* Enumeration ROM registers */ ++#define ER_EROMENTRY 0x000 ++#define ER_REMAPCONTROL 0xe00 ++#define ER_REMAPSELECT 0xe04 ++#define ER_MASTERSELECT 0xe10 ++#define ER_ITCR 0xf00 ++#define ER_ITIP 0xf04 ++ ++/* Erom entries */ ++#define ER_TAG 0xe ++#define ER_TAG1 0x6 ++#define ER_VALID 1 ++#define ER_CI 0 ++#define ER_MP 2 ++#define ER_ADD 4 ++#define ER_END 0xe ++#define ER_BAD 0xffffffff ++ ++/* EROM CompIdentA */ ++#define CIA_MFG_MASK 0xfff00000 ++#define CIA_MFG_SHIFT 20 ++#define CIA_CID_MASK 0x000fff00 ++#define CIA_CID_SHIFT 8 ++#define CIA_CCL_MASK 0x000000f0 ++#define CIA_CCL_SHIFT 4 ++ ++/* EROM CompIdentB */ ++#define CIB_REV_MASK 0xff000000 ++#define CIB_REV_SHIFT 24 ++#define CIB_NSW_MASK 0x00f80000 ++#define CIB_NSW_SHIFT 19 ++#define CIB_NMW_MASK 0x0007c000 ++#define CIB_NMW_SHIFT 14 ++#define CIB_NSP_MASK 0x00003e00 ++#define CIB_NSP_SHIFT 9 ++#define CIB_NMP_MASK 0x000001f0 ++#define CIB_NMP_SHIFT 4 ++ ++/* EROM MasterPortDesc */ ++#define MPD_MUI_MASK 0x0000ff00 ++#define MPD_MUI_SHIFT 8 ++#define MPD_MP_MASK 0x000000f0 ++#define MPD_MP_SHIFT 4 ++ ++/* EROM AddrDesc */ ++#define AD_ADDR_MASK 0xfffff000 ++#define AD_SP_MASK 0x00000f00 ++#define AD_SP_SHIFT 8 ++#define AD_ST_MASK 0x000000c0 ++#define AD_ST_SHIFT 6 ++#define AD_ST_SLAVE 0x00000000 ++#define AD_ST_BRIDGE 0x00000040 ++#define AD_ST_SWRAP 0x00000080 ++#define AD_ST_MWRAP 0x000000c0 ++#define AD_SZ_MASK 0x00000030 ++#define AD_SZ_SHIFT 4 ++#define AD_SZ_4K 0x00000000 ++#define AD_SZ_8K 0x00000010 ++#define AD_SZ_16K 0x00000020 ++#define AD_SZ_SZD 0x00000030 ++#define AD_AG32 0x00000008 ++#define AD_ADDR_ALIGN 0x00000fff ++#define AD_SZ_BASE 0x00001000 /* 4KB */ ++ ++/* EROM SizeDesc */ ++#define SD_SZ_MASK 0xfffff000 ++#define SD_SG32 0x00000008 ++#define SD_SZ_ALIGN 0x00000fff ++ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _aidmp { ++ uint32 oobselina30; /* 0x000 */ ++ uint32 oobselina74; /* 0x004 */ ++ uint32 PAD[6]; ++ uint32 oobselinb30; /* 0x020 */ ++ uint32 oobselinb74; /* 0x024 */ ++ uint32 PAD[6]; ++ uint32 oobselinc30; /* 0x040 */ ++ uint32 oobselinc74; /* 0x044 */ ++ uint32 PAD[6]; ++ uint32 oobselind30; /* 0x060 */ ++ uint32 oobselind74; /* 0x064 */ ++ uint32 PAD[38]; ++ uint32 oobselouta30; /* 0x100 */ ++ uint32 oobselouta74; /* 0x104 */ ++ uint32 PAD[6]; ++ uint32 oobseloutb30; /* 0x120 */ ++ uint32 oobseloutb74; /* 0x124 */ ++ uint32 PAD[6]; ++ uint32 oobseloutc30; /* 0x140 */ ++ uint32 oobseloutc74; /* 0x144 */ ++ uint32 PAD[6]; ++ uint32 oobseloutd30; /* 0x160 */ ++ uint32 oobseloutd74; /* 0x164 */ ++ uint32 PAD[38]; ++ uint32 oobsynca; /* 0x200 */ ++ uint32 oobseloutaen; /* 0x204 */ ++ uint32 PAD[6]; ++ uint32 oobsyncb; /* 0x220 */ ++ uint32 oobseloutben; /* 0x224 */ ++ uint32 PAD[6]; ++ uint32 oobsyncc; /* 0x240 */ ++ uint32 oobseloutcen; /* 0x244 */ ++ uint32 PAD[6]; ++ uint32 oobsyncd; /* 0x260 */ ++ uint32 oobseloutden; /* 0x264 */ ++ uint32 PAD[38]; ++ uint32 oobaextwidth; /* 0x300 */ ++ uint32 oobainwidth; /* 0x304 */ ++ uint32 oobaoutwidth; /* 0x308 */ ++ uint32 PAD[5]; ++ uint32 oobbextwidth; /* 0x320 */ ++ uint32 oobbinwidth; /* 0x324 */ ++ uint32 oobboutwidth; /* 0x328 */ ++ uint32 PAD[5]; ++ uint32 oobcextwidth; /* 0x340 */ ++ uint32 oobcinwidth; /* 0x344 */ ++ uint32 oobcoutwidth; /* 0x348 */ ++ uint32 PAD[5]; ++ uint32 oobdextwidth; /* 0x360 */ ++ uint32 oobdinwidth; /* 0x364 */ ++ uint32 oobdoutwidth; /* 0x368 */ ++ uint32 PAD[37]; ++ uint32 ioctrlset; /* 0x400 */ ++ uint32 ioctrlclear; /* 0x404 */ ++ uint32 ioctrl; /* 0x408 */ ++ uint32 PAD[61]; ++ uint32 iostatus; /* 0x500 */ ++ uint32 PAD[127]; ++ uint32 ioctrlwidth; /* 0x700 */ ++ uint32 iostatuswidth; /* 0x704 */ ++ uint32 PAD[62]; ++ uint32 resetctrl; /* 0x800 */ ++ uint32 resetstatus; /* 0x804 */ ++ uint32 resetreadid; /* 0x808 */ ++ uint32 resetwriteid; /* 0x80c */ ++ uint32 PAD[60]; ++ uint32 errlogctrl; /* 0x900 */ ++ uint32 errlogdone; /* 0x904 */ ++ uint32 errlogstatus; /* 0x908 */ ++ uint32 errlogaddrlo; /* 0x90c */ ++ uint32 errlogaddrhi; /* 0x910 */ ++ uint32 errlogid; /* 0x914 */ ++ uint32 errloguser; /* 0x918 */ ++ uint32 errlogflags; /* 0x91c */ ++ uint32 PAD[56]; ++ uint32 intstatus; /* 0xa00 */ ++ uint32 PAD[255]; ++ uint32 config; /* 0xe00 */ ++ uint32 PAD[63]; ++ uint32 itcr; /* 0xf00 */ ++ uint32 PAD[3]; ++ uint32 itipooba; /* 0xf10 */ ++ uint32 itipoobb; /* 0xf14 */ ++ uint32 itipoobc; /* 0xf18 */ ++ uint32 itipoobd; /* 0xf1c */ ++ uint32 PAD[4]; ++ uint32 itipoobaout; /* 0xf30 */ ++ uint32 itipoobbout; /* 0xf34 */ ++ uint32 itipoobcout; /* 0xf38 */ ++ uint32 itipoobdout; /* 0xf3c */ ++ uint32 PAD[4]; ++ uint32 itopooba; /* 0xf50 */ ++ uint32 itopoobb; /* 0xf54 */ ++ uint32 itopoobc; /* 0xf58 */ ++ uint32 itopoobd; /* 0xf5c */ ++ uint32 PAD[4]; ++ uint32 itopoobain; /* 0xf70 */ ++ uint32 itopoobbin; /* 0xf74 */ ++ uint32 itopoobcin; /* 0xf78 */ ++ uint32 itopoobdin; /* 0xf7c */ ++ uint32 PAD[4]; ++ uint32 itopreset; /* 0xf90 */ ++ uint32 PAD[15]; ++ uint32 peripherialid4; /* 0xfd0 */ ++ uint32 peripherialid5; /* 0xfd4 */ ++ uint32 peripherialid6; /* 0xfd8 */ ++ uint32 peripherialid7; /* 0xfdc */ ++ uint32 peripherialid0; /* 0xfe0 */ ++ uint32 peripherialid1; /* 0xfe4 */ ++ uint32 peripherialid2; /* 0xfe8 */ ++ uint32 peripherialid3; /* 0xfec */ ++ uint32 componentid0; /* 0xff0 */ ++ uint32 componentid1; /* 0xff4 */ ++ uint32 componentid2; /* 0xff8 */ ++ uint32 componentid3; /* 0xffc */ ++} aidmp_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Out-of-band Router registers */ ++#define OOB_BUSCONFIG 0x020 ++#define OOB_STATUSA 0x100 ++#define OOB_STATUSB 0x104 ++#define OOB_STATUSC 0x108 ++#define OOB_STATUSD 0x10c ++#define OOB_ENABLEA0 0x200 ++#define OOB_ENABLEA1 0x204 ++#define OOB_ENABLEA2 0x208 ++#define OOB_ENABLEA3 0x20c ++#define OOB_ENABLEB0 0x280 ++#define OOB_ENABLEB1 0x284 ++#define OOB_ENABLEB2 0x288 ++#define OOB_ENABLEB3 0x28c ++#define OOB_ENABLEC0 0x300 ++#define OOB_ENABLEC1 0x304 ++#define OOB_ENABLEC2 0x308 ++#define OOB_ENABLEC3 0x30c ++#define OOB_ENABLED0 0x380 ++#define OOB_ENABLED1 0x384 ++#define OOB_ENABLED2 0x388 ++#define OOB_ENABLED3 0x38c ++#define OOB_ITCR 0xf00 ++#define OOB_ITIPOOBA 0xf10 ++#define OOB_ITIPOOBB 0xf14 ++#define OOB_ITIPOOBC 0xf18 ++#define OOB_ITIPOOBD 0xf1c ++#define OOB_ITOPOOBA 0xf30 ++#define OOB_ITOPOOBB 0xf34 ++#define OOB_ITOPOOBC 0xf38 ++#define OOB_ITOPOOBD 0xf3c ++ ++/* DMP wrapper registers */ ++#define AI_OOBSELINA30 0x000 ++#define AI_OOBSELINA74 0x004 ++#define AI_OOBSELINB30 0x020 ++#define AI_OOBSELINB74 0x024 ++#define AI_OOBSELINC30 0x040 ++#define AI_OOBSELINC74 0x044 ++#define AI_OOBSELIND30 0x060 ++#define AI_OOBSELIND74 0x064 ++#define AI_OOBSELOUTA30 0x100 ++#define AI_OOBSELOUTA74 0x104 ++#define AI_OOBSELOUTB30 0x120 ++#define AI_OOBSELOUTB74 0x124 ++#define AI_OOBSELOUTC30 0x140 ++#define AI_OOBSELOUTC74 0x144 ++#define AI_OOBSELOUTD30 0x160 ++#define AI_OOBSELOUTD74 0x164 ++#define AI_OOBSYNCA 0x200 ++#define AI_OOBSELOUTAEN 0x204 ++#define AI_OOBSYNCB 0x220 ++#define AI_OOBSELOUTBEN 0x224 ++#define AI_OOBSYNCC 0x240 ++#define AI_OOBSELOUTCEN 0x244 ++#define AI_OOBSYNCD 0x260 ++#define AI_OOBSELOUTDEN 0x264 ++#define AI_OOBAEXTWIDTH 0x300 ++#define AI_OOBAINWIDTH 0x304 ++#define AI_OOBAOUTWIDTH 0x308 ++#define AI_OOBBEXTWIDTH 0x320 ++#define AI_OOBBINWIDTH 0x324 ++#define AI_OOBBOUTWIDTH 0x328 ++#define AI_OOBCEXTWIDTH 0x340 ++#define AI_OOBCINWIDTH 0x344 ++#define AI_OOBCOUTWIDTH 0x348 ++#define AI_OOBDEXTWIDTH 0x360 ++#define AI_OOBDINWIDTH 0x364 ++#define AI_OOBDOUTWIDTH 0x368 ++ ++#if defined(IL_BIGENDIAN) && defined(BCMHND74K) ++/* Selective swapped defines for those registers we need in ++ * big-endian code. ++ */ ++#define AI_IOCTRLSET 0x404 ++#define AI_IOCTRLCLEAR 0x400 ++#define AI_IOCTRL 0x40c ++#define AI_IOSTATUS 0x504 ++#define AI_RESETCTRL 0x804 ++#define AI_RESETSTATUS 0x800 ++ ++#else /* !IL_BIGENDIAN || !BCMHND74K */ ++ ++#define AI_IOCTRLSET 0x400 ++#define AI_IOCTRLCLEAR 0x404 ++#define AI_IOCTRL 0x408 ++#define AI_IOSTATUS 0x500 ++#define AI_RESETCTRL 0x800 ++#define AI_RESETSTATUS 0x804 ++ ++#endif /* IL_BIGENDIAN && BCMHND74K */ ++ ++#define AI_IOCTRLWIDTH 0x700 ++#define AI_IOSTATUSWIDTH 0x704 ++ ++#define AI_RESETREADID 0x808 ++#define AI_RESETWRITEID 0x80c ++#define AI_ERRLOGCTRL 0xa00 ++#define AI_ERRLOGDONE 0xa04 ++#define AI_ERRLOGSTATUS 0xa08 ++#define AI_ERRLOGADDRLO 0xa0c ++#define AI_ERRLOGADDRHI 0xa10 ++#define AI_ERRLOGID 0xa14 ++#define AI_ERRLOGUSER 0xa18 ++#define AI_ERRLOGFLAGS 0xa1c ++#define AI_INTSTATUS 0xa00 ++#define AI_CONFIG 0xe00 ++#define AI_ITCR 0xf00 ++#define AI_ITIPOOBA 0xf10 ++#define AI_ITIPOOBB 0xf14 ++#define AI_ITIPOOBC 0xf18 ++#define AI_ITIPOOBD 0xf1c ++#define AI_ITIPOOBAOUT 0xf30 ++#define AI_ITIPOOBBOUT 0xf34 ++#define AI_ITIPOOBCOUT 0xf38 ++#define AI_ITIPOOBDOUT 0xf3c ++#define AI_ITOPOOBA 0xf50 ++#define AI_ITOPOOBB 0xf54 ++#define AI_ITOPOOBC 0xf58 ++#define AI_ITOPOOBD 0xf5c ++#define AI_ITOPOOBAIN 0xf70 ++#define AI_ITOPOOBBIN 0xf74 ++#define AI_ITOPOOBCIN 0xf78 ++#define AI_ITOPOOBDIN 0xf7c ++#define AI_ITOPRESET 0xf90 ++#define AI_PERIPHERIALID4 0xfd0 ++#define AI_PERIPHERIALID5 0xfd4 ++#define AI_PERIPHERIALID6 0xfd8 ++#define AI_PERIPHERIALID7 0xfdc ++#define AI_PERIPHERIALID0 0xfe0 ++#define AI_PERIPHERIALID1 0xfe4 ++#define AI_PERIPHERIALID2 0xfe8 ++#define AI_PERIPHERIALID3 0xfec ++#define AI_COMPONENTID0 0xff0 ++#define AI_COMPONENTID1 0xff4 ++#define AI_COMPONENTID2 0xff8 ++#define AI_COMPONENTID3 0xffc ++ ++/* resetctrl */ ++#define AIRC_RESET 1 ++ ++/* config */ ++#define AICFG_OOB 0x00000020 ++#define AICFG_IOS 0x00000010 ++#define AICFG_IOC 0x00000008 ++#define AICFG_TO 0x00000004 ++#define AICFG_ERRL 0x00000002 ++#define AICFG_RST 0x00000001 ++ ++/* bit defines for AI_OOBSELOUTB74 reg */ ++#define OOB_SEL_OUTEN_B_5 15 ++#define OOB_SEL_OUTEN_B_6 23 ++ ++#endif /* _AIDMP_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/arminc.h b/drivers/bcmdrivers/gmac/src/include/arminc.h +new file mode 100755 +index 0000000..a0f2401 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch new file mode 100644 index 00000000..4f5012df --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_arminc.h.patch @@ -0,0 +1,323 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/arminc.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND Run Time Environment for standalone ARM programs. ++ * ++ * $Id: arminc.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _ARMINC_H ++#define _ARMINC_H ++ ++ ++/* ARM defines */ ++ ++#ifdef _LANGUAGE_ASSEMBLY ++ ++/* ++ * LEAF - declare leaf routine ++ */ ++#define LEAF(function) \ ++ .section .text.function, "ax"; \ ++ .global function; \ ++ .func function; \ ++function: ++ ++#define THUMBLEAF(function) \ ++ .section .text.function, "ax"; \ ++ .global function; \ ++ .func function; \ ++ .thumb; \ ++ .thumb_func; \ ++function: ++ ++/* ++ * END - mark end of function ++ */ ++#define END(function) \ ++ .ltorg; \ ++ .endfunc; \ ++ .size function, . - function ++ ++#define DW(var, val) \ ++ .global var; \ ++ .type var, %object; \ ++ .size var, 4; \ ++ .align 2; \ ++var: .word val ++ ++ ++#define _ULCAST_ ++ ++#else ++ ++/* ++ * The following macros are especially useful for __asm__ ++ * inline assembler. ++ */ ++#ifndef __STR ++#define __STR(x) #x ++#endif ++#ifndef STR ++#define STR(x) __STR(x) ++#endif ++ ++#define _ULCAST_ (unsigned long) ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++ ++#if defined(__ARM_ARCH_7M__) /* Cortex-M3 */ ++ ++/* Data Watchpoint and Trigger */ ++#define CM3_DWT_CTRL 0xe0001000 ++#define CM3_DWT_CYCCNT 0xe0001004 ++#define CM3_DWT_CPICNT 0xe0001008 ++#define CM3_DWT_EXCCNT 0xe000100c ++#define CM3_DWT_SLEEPCNT 0xe0001010 ++#define CM3_DWT_LSUCNT 0xe0001014 ++#define CM3_DWT_FOLDCNT 0xe0001018 ++#define CM3_DWT_COMP0 0xe0001020 ++#define CM3_DWT_MASK0 0xe0001024 ++#define CM3_DWT_FUNCTION0 0xe0001028 ++#define CM3_DWT_COMP1 0xe0001030 ++#define CM3_DWT_MASK1 0xe0001034 ++#define CM3_DWT_FUNCTION1 0xe0001038 ++#define CM3_DWT_COMP2 0xe0001040 ++#define CM3_DWT_MASK2 0xe0001044 ++#define CM3_DWT_FUNCTION2 0xe0001048 ++#define CM3_DWT_COMP3 0xe0001050 ++#define CM3_DWT_MASK3 0xe0001054 ++#define CM3_DWT_FUNCTION3 0xe0001058 ++ ++#define CM3_DWT_FUNCTION_DISAB 0 ++#define CM3_DWT_FUNCTION_WP_PCMATCH 4 ++#define CM3_DWT_FUNCTION_WP_READ 5 ++#define CM3_DWT_FUNCTION_WP_WRITE 6 ++#define CM3_DWT_FUNCTION_WP_RDWR 7 ++ ++#define CM3_NVIC_IC_TYPE 0xe000e004 /* Interrupt Control Type Reg */ ++#define CM3_NVIC_TICK_CSR 0xe000e010 /* SysTick Control and Status Reg */ ++#define CM3_NVIC_TICK_CSR_COUNTFLAG 0x10000 ++#define CM3_NVIC_TICK_CSR_CLKSOURCE 0x4 /* Set for core clock, 0 for ext ref */ ++#define CM3_NVIC_TICK_CSR_TICKINT 0x2 /* Set for intr on count going 1 => 0 */ ++#define CM3_NVIC_TICK_CSR_ENABLE 0x1 ++#define CM3_NVIC_TICK_RLDVAL 0xe000e014 /* SysTick Reload Value Reg */ ++#define CM3_NVIC_TICK_CURVAL 0xe000e018 /* SysTick Current Value Reg */ ++#define CM3_NVIC_TICK_CALVAL 0xe000e01c /* SysTick Calibration Value Reg */ ++ ++/* Interrupt enable/disable register */ ++#define CM3_NVIC_IRQ_SET_EN0 0xe000e100 /* Irq 0 to 31 Set Enable Reg */ ++#define CM3_NVIC_IRQ_SET_EN(n) (0xe000e100 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_CLR_EN0 0xe000e180 /* Irq 0 to 31 Clear Enable Reg [...] */ ++#define CM3_NVIC_IRQ_CLR_EN(n) (0xe000e180 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_SET_PND0 0xe000e200 /* Irq 0 to 31 Set Pending Reg [...] */ ++#define CM3_NVIC_IRQ_SET_PND(n) (0xe000e200 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_CLR_PND0 0xe000e280 /* Irq 0 to 31 Clear Pending Reg [...] */ ++#define CM3_NVIC_IRQ_CLR_PND(n) (0xe000e280 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_ACT_BIT0 0xe000e300 /* Irq 0 to 31 Active Bit Reg [...] */ ++#define CM3_NVIC_IRQ_ACT_BIT(n) (0xe000e300 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_PRIO0 0xe000e400 /* Irq 0 to 31 Priority Reg [...] */ ++#define CM3_NVIC_IRQ_PRIO(n) (0xe000e400 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++/* CPU control */ ++#define CM3_CPUID 0xe000ed00 ++#define CM3_INTCTLSTATE 0xe000ed04 ++#define CM3_VTOFF 0xe000ed08 /* Vector Table Offset */ ++#define CM3_SYSCTRL 0xe000ed10 ++#define CM3_CFGCTRL 0xe000ed14 ++#define CM3_CFGCTRL_UNALIGN_TRP 0x8 ++#define CM3_CFGCTRL_DIV_0_TRP 0x10 ++#define CM3_CFGCTRL_STKALIGN 0x200 ++ ++#define CM3_PFR0 0xe000ed40 ++#define CM3_PFR1 0xe000ed44 ++#define CM3_DFR0 0xe000ed48 ++#define CM3_AFR0 0xe000ed4c ++#define CM3_MMFR0 0xe000ed50 ++#define CM3_MMFR1 0xe000ed54 ++#define CM3_MMFR2 0xe000ed58 ++#define CM3_MMFR3 0xe000ed5c ++#define CM3_ISAR0 0xe000ed60 ++#define CM3_ISAR1 0xe000ed64 ++#define CM3_ISAR2 0xe000ed68 ++#define CM3_ISAR3 0xe000ed6c ++#define CM3_ISAR4 0xe000ed70 ++#define CM3_ISAR5 0xe000ed74 ++ ++#define CM3_MPUTYPE 0xe000ed90 ++#define CM3_MPUCTRL 0xe000ed94 ++#define CM3_REGNUM 0xe000ed98 ++#define CM3_REGBAR 0xe000ed9c ++#define CM3_REGASZ 0xe000eda0 ++#define CM3_AL1BAR 0xe000eda4 ++#define CM3_AL1ASZ 0xe000eda8 ++#define CM3_AL2BAR 0xe000edac ++#define CM3_AL2ASZ 0xe000edb0 ++#define CM3_AL3BAR 0xe000edb4 ++#define CM3_AL3ASZ 0xe000edb8 ++ ++#define CM3_DBG_HCSR 0xe000edf0 /* Debug Halting Control and Status Reg */ ++#define CM3_DBG_CRSR 0xe000edf4 /* Debug Core Register Selector Reg */ ++#define CM3_DBG_CRDR 0xe000edf8 /* Debug Core Register Data Reg */ ++#define CM3_DBG_EMCR 0xe000edfc /* Debug Exception and Monitor Control Reg */ ++#define CM3_DBG_EMCR_TRCENA (1U << 24) ++#define CM3_DBG_EMCR_MON_EN (1U << 16) ++ ++/* Trap types */ ++#define TR_RST 1 /* Reset */ ++#define TR_NMI 2 /* NMI */ ++#define TR_FAULT 3 /* Hard Fault */ ++#define TR_MM 4 /* Memory Management */ ++#define TR_BUS 5 /* Bus Fault */ ++#define TR_USAGE 6 /* Usage Fault */ ++#define TR_SVC 11 /* SVCall */ ++#define TR_DMON 12 /* Debug Monitor */ ++#define TR_PENDSV 14 /* PendSV */ ++#define TR_SYSTICK 15 /* SysTick */ ++#define TR_ISR 16 /* External Interrupts start here */ ++ ++#define TR_BAD 256 /* Bad trap: Not used by CM3 */ ++ ++/* Offsets of automatically saved registers from sp upon trap */ ++#define CM3_TROFF_R0 0 ++#define CM3_TROFF_R1 4 ++#define CM3_TROFF_R2 8 ++#define CM3_TROFF_R3 12 ++#define CM3_TROFF_R12 16 ++#define CM3_TROFF_LR 20 ++#define CM3_TROFF_PC 24 ++#define CM3_TROFF_xPSR 28 ++ ++#elif defined(__ARM_ARCH_7A__) /* Cortex-A9 */ ++/* Fields in cpsr */ ++#define PS_USR 0x00000010 /* Mode: User */ ++#define PS_FIQ 0x00000011 /* Mode: FIQ */ ++#define PS_IRQ 0x00000012 /* Mode: IRQ */ ++#define PS_SVC 0x00000013 /* Mode: Supervisor */ ++#define PS_ABT 0x00000017 /* Mode: Abort */ ++#define PS_UND 0x0000001b /* Mode: Undefined */ ++#define PS_SYS 0x0000001f /* Mode: System */ ++#define PS_MM 0x0000001f /* Mode bits mask */ ++#define PS_T 0x00000020 /* Thumb mode */ ++#define PS_F 0x00000040 /* FIQ disable */ ++#define PS_I 0x00000080 /* IRQ disable */ ++#define PS_A 0x00000100 /* Imprecise abort */ ++#define PS_E 0x00000200 /* Endianess */ ++#define PS_IT72 0x0000fc00 /* IT[7:2] */ ++#define PS_GE 0x000f0000 /* IT[7:2] */ ++#define PS_J 0x01000000 /* Java state */ ++#define PS_IT10 0x06000000 /* IT[1:0] */ ++#define PS_Q 0x08000000 /* Sticky overflow */ ++#define PS_V 0x10000000 /* Overflow cc */ ++#define PS_C 0x20000000 /* Carry cc */ ++#define PS_Z 0x40000000 /* Zero cc */ ++#define PS_N 0x80000000 /* Negative cc */ ++ ++/* Trap types */ ++#define TR_RST 0 /* Reset trap */ ++#define TR_UND 1 /* Indefined instruction trap */ ++#define TR_SWI 2 /* Software intrrupt */ ++#define TR_IAB 3 /* Instruction fetch abort */ ++#define TR_DAB 4 /* Data access abort */ ++#define TR_BAD 5 /* Bad trap: Not used by ARM */ ++#define TR_IRQ 6 /* Interrupt */ ++#define TR_FIQ 7 /* Fast interrupt */ ++ ++/* ++ * Memory segments (32bit kernel mode addresses) ++ */ ++#define PHYSADDR_MASK 0xffffffff ++ ++/* ++ * Map an address to a certain kernel segment ++ */ ++#undef PHYSADDR ++#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK) ++#else /* !__ARM_ARCH_7M__ */ ++ ++/* Fields in cpsr */ ++#define PS_USR 0x00000010 /* Mode: User */ ++#define PS_FIQ 0x00000011 /* Mode: FIQ */ ++#define PS_IRQ 0x00000012 /* Mode: IRQ */ ++#define PS_SVC 0x00000013 /* Mode: Supervisor */ ++#define PS_ABT 0x00000017 /* Mode: Abort */ ++#define PS_UND 0x0000001b /* Mode: Undefined */ ++#define PS_SYS 0x0000001f /* Mode: System */ ++#define PS_MM 0x0000001f /* Mode bits mask */ ++#define PS_T 0x00000020 /* Thumb mode */ ++#define PS_F 0x00000040 /* FIQ disable */ ++#define PS_I 0x00000080 /* IRQ disable */ ++#define PS_A 0x00000100 /* Imprecise abort */ ++#define PS_E 0x00000200 /* Endianess */ ++#define PS_IT72 0x0000fc00 /* IT[7:2] */ ++#define PS_GE 0x000f0000 /* IT[7:2] */ ++#define PS_J 0x01000000 /* Java state */ ++#define PS_IT10 0x06000000 /* IT[1:0] */ ++#define PS_Q 0x08000000 /* Sticky overflow */ ++#define PS_V 0x10000000 /* Overflow cc */ ++#define PS_C 0x20000000 /* Carry cc */ ++#define PS_Z 0x40000000 /* Zero cc */ ++#define PS_N 0x80000000 /* Negative cc */ ++ ++/* Trap types */ ++#define TR_RST 0 /* Reset trap */ ++#define TR_UND 1 /* Indefined instruction trap */ ++#define TR_SWI 2 /* Software intrrupt */ ++#define TR_IAB 3 /* Instruction fetch abort */ ++#define TR_DAB 4 /* Data access abort */ ++#define TR_BAD 5 /* Bad trap: Not used by ARM */ ++#define TR_IRQ 6 /* Interrupt */ ++#define TR_FIQ 7 /* Fast interrupt */ ++ ++#ifdef BCMDBG_ARMRST ++#define TR_ARMRST 0xF /* Debug facility to trap Arm reset */ ++#endif ++ ++/* used to fill an overlay region with nop's */ ++#define NOP_UINT32 0x46c046c0 ++ ++ ++#define mrc(cp, a, b, n) \ ++({ \ ++ int __res; \ ++ __asm__ __volatile__("\tmrc\tp"STR(cp)", 0, %0, c"STR(a)", c"STR(b)", "STR(n) \ ++ :"=r" (__res)); \ ++ __res; \ ++}) ++ ++ ++#endif /* !__ARM_ARCH_7M__ */ ++ ++/* Pieces of a CPU Id */ ++#define CID_IMPL 0xff000000 /* Implementor: 0x41 for ARM Ltd. */ ++#define CID_VARIANT 0x00f00000 ++#define CID_ARCH 0x000f0000 ++#define CID_PART 0x0000fff0 ++#define CID_REV 0x0000000f ++#define CID_MASK (CID_IMPL | CID_ARCH | CID_PART) ++ ++#endif /* _ARMINC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h b/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h +new file mode 100755 +index 0000000..8219b8b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch new file mode 100644 index 00000000..15007d3f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch @@ -0,0 +1,34 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM common config options ++ * ++ * $Id: bcm_cfg.h 294399 2011-11-07 03:31:22Z $ ++ */ ++ ++#ifndef _bcm_cfg_h_ ++#define _bcm_cfg_h_ ++#if defined(__NetBSD__) || defined(__FreeBSD__) ++#if defined(_KERNEL) ++#include ++#endif /* defined(_KERNEL) */ ++#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ ++#endif /* _bcm_cfg_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h b/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h +new file mode 100755 +index 0000000..7a1f01d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch new file mode 100644 index 00000000..1bebaba8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch @@ -0,0 +1,361 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h +@@ -0,0 +1,355 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Memory pools library, Public interface ++ * ++ * API Overview ++ * ++ * This package provides a memory allocation subsystem based on pools of ++ * homogenous objects. ++ * ++ * Instrumentation is available for reporting memory utilization both ++ * on a per-data-structure basis and system wide. ++ * ++ * There are two main types defined in this API. ++ * ++ * pool manager: A singleton object that acts as a factory for ++ * pool allocators. It also is used for global ++ * instrumentation, such as reporting all blocks ++ * in use across all data structures. The pool manager ++ * creates and provides individual memory pools ++ * upon request to application code. ++ * ++ * memory pool: An object for allocating homogenous memory blocks. ++ * ++ * Global identifiers in this module use the following prefixes: ++ * bcm_mpm_* Memory pool manager ++ * bcm_mp_* Memory pool ++ * ++ * There are two main types of memory pools: ++ * ++ * prealloc: The contiguous memory block of objects can either be supplied ++ * by the client or malloc'ed by the memory manager. The objects are ++ * allocated out of a block of memory and freed back to the block. ++ * ++ * heap: The memory pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing statistics ++ * and instrumentation on top of the heap, without modifying the heap ++ * allocation implementation. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _BCM_MPOOL_PUB_H ++#define _BCM_MPOOL_PUB_H 1 ++ ++#include /* needed for uint16 */ ++ ++ ++/* ++************************************************************************** ++* ++* Type definitions, handles ++* ++************************************************************************** ++*/ ++ ++/* Forward declaration of OSL handle. */ ++struct osl_info; ++ ++/* Forward declaration of string buffer. */ ++struct bcmstrbuf; ++ ++/* ++ * Opaque type definition for the pool manager handle. This object is used for global ++ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and ++ * instrumentation/debugging. ++ */ ++struct bcm_mpm_mgr; ++typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; ++ ++/* ++ * Opaque type definition for an instance of a pool. This handle is used for allocating ++ * and freeing memory through the pool, as well as management/instrumentation on this ++ * specific pool. ++ */ ++struct bcm_mp_pool; ++typedef struct bcm_mp_pool *bcm_mp_pool_h; ++ ++ ++/* ++ * To make instrumentation more readable, every memory ++ * pool must have a readable name. Pool names are up to ++ * 8 bytes including '\0' termination. (7 printable characters.) ++ */ ++#define BCM_MP_NAMELEN 8 ++ ++ ++/* ++ * Type definition for pool statistics. ++ */ ++typedef struct bcm_mp_stats { ++ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ ++ unsigned int objsz; /* Object size allocated in this pool */ ++ uint16 nobj; /* Total number of objects in this pool */ ++ uint16 num_alloc; /* Number of objects currently allocated */ ++ uint16 high_water; /* Max number of allocated objects. */ ++ uint16 failed_alloc; /* Failed allocations. */ ++} bcm_mp_stats_t; ++ ++ ++/* ++************************************************************************** ++* ++* API Routines on the pool manager. ++* ++************************************************************************** ++*/ ++ ++/* ++ * bcm_mpm_init() - initialize the whole memory pool system. ++ * ++ * Parameters: ++ * osh: INPUT Operating system handle. Needed for heap memory allocation. ++ * max_pools: INPUT Maximum number of mempools supported. ++ * mgr: OUTPUT The handle is written with the new pools manager object/handle. ++ * ++ * Returns: ++ * BCME_OK Object initialized successfully. May be used. ++ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. ++ */ ++int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); ++ ++ ++/* ++ * bcm_mpm_deinit() - de-initialize the whole memory pool system. ++ * ++ * Parameters: ++ * mgr: INPUT Pointer to pool manager handle. ++ * ++ * Returns: ++ * BCME_OK Memory pool manager successfully de-initialized. ++ * other Indicated error occured during de-initialization. ++ */ ++int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); ++ ++/* ++ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The ++ * pool uses a contiguous block of pre-alloced ++ * memory. The memory block may either be provided ++ * by the client or dynamically allocated by the ++ * pool manager. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * Must be >= sizeof(void *). ++ * nobj: INPUT Maximum number of concurrently existing objects to support ++ * memstart INPUT Pointer to the memory to use, or NULL to malloc() ++ * memsize INPUT Number of bytes referenced from memstart (for error checking). ++ * Must be 0 if 'memstart' is NULL. ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, ++ unsigned int obj_sz, ++ int nobj, ++ void *memstart, ++ unsigned int memsize, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++/* ++ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory ++ * pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing ++ * statistics and instrumentation on top of the heap, ++ * without modifying the heap allocation implementation. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++ ++/* ++ * bcm_mpm_stats() - Return stats for all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * stats: OUTPUT Array of pool statistics. ++ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number ++ * of array elements copied to 'stats' on OUTPUT. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting stats. ++ * ++ */ ++int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); ++ ++ ++/* ++ * bcm_mpm_dump() - Display statistics on all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * b: OUTPUT Output buffer. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); ++ ++ ++/* ++ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to ++ * compensate for alignment requirements of the objects. ++ * This function provides the padded object size. If clients ++ * pre-allocate a memory slab for a memory pool, the ++ * padded object size should be used by the client to allocate ++ * the memory slab (in order to provide sufficent space for ++ * the maximum number of objects). ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager. ++ * obj_sz: INPUT Input object size. ++ * padded_obj_sz: OUTPUT Padded object size. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * BCME_BADARG Bad arguments. ++ * ++ */ ++int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); ++ ++ ++/* ++*************************************************************************** ++* ++* API Routines on a specific pool. ++* ++*************************************************************************** ++*/ ++ ++ ++/* ++ * bcm_mp_alloc() - Allocate a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * ++ * Returns: ++ * A pointer to the new object. NULL on error. ++ * ++ */ ++void* bcm_mp_alloc(bcm_mp_pool_h pool); ++ ++/* ++ * bcm_mp_free() - Free a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * objp: INPUT A pointer to the object to free. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during free. ++ * ++ */ ++int bcm_mp_free(bcm_mp_pool_h pool, void *objp); ++ ++/* ++ * bcm_mp_stats() - Return stats for this pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * stats: OUTPUT Pool statistics ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting statistics. ++ * ++ */ ++int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); ++ ++ ++/* ++ * bcm_mp_dump() - Dump a pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * b OUTPUT Output buffer ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); ++ ++ ++#endif /* _BCM_MPOOL_PUB_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmcdc.h b/drivers/bcmdrivers/gmac/src/include/bcmcdc.h +new file mode 100755 +index 0000000..2b99cf1 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch new file mode 100644 index 00000000..ba71ec98 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch @@ -0,0 +1,128 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmcdc.h +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * CDC network driver ioctl/indication encoding ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * $Id: bcmcdc.h 291086 2011-10-21 01:17:24Z $ ++ */ ++#ifndef _bcmcdc_h_ ++#define _bcmcdc_h_ ++#include ++ ++typedef struct cdc_ioctl { ++ uint32 cmd; /* ioctl command value */ ++ uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ ++ uint32 flags; /* flag defns given below */ ++ uint32 status; /* status code returned from the device */ ++} cdc_ioctl_t; ++ ++/* Max valid buffer size that can be sent to the dongle */ ++#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN ++ ++/* len field is divided into input and output buffer lengths */ ++#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */ ++ /* excluding IOCTL header */ ++#define CDCL_IOC_OUTLEN_SHIFT 0 ++#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */ ++#define CDCL_IOC_INLEN_SHIFT 16 ++ ++/* CDC flag definitions */ ++#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */ ++#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ ++#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */ ++#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */ ++#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */ ++#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */ ++#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */ ++#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ ++#define CDCF_IOC_IF_SHIFT 12 ++#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */ ++#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */ ++ ++#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT) ++#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) ++ ++#define CDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)) ++#define CDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT))) ++ ++/* ++ * BDC header ++ * ++ * The BDC header is used on data packets to convey priority across USB. ++ */ ++ ++#define BDC_HEADER_LEN 4 ++ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++#define BDC_PROTO_VER 2 /* Protocol version */ ++ ++#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ ++#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ ++ ++#define BDC_FLAG__UNUSED 0x03 /* Unassigned */ ++#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ ++#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ ++ ++#define BDC_PRIORITY_MASK 0x7 ++ ++#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */ ++ /* FLOW CONTROL info only */ ++#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */ ++ ++#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the packet was received */ ++#define BDC_FLAG2_IF_SHIFT 0 ++#define BDC_FLAG2_PAD_MASK 0xf0 ++#define BDC_FLAG_PAD_MASK 0x03 ++#define BDC_FLAG2_PAD_SHIFT 2 ++#define BDC_FLAG_PAD_SHIFT 0 ++#define BDC_FLAG2_PAD_IDX 0x3c ++#define BDC_FLAG_PAD_IDX 0x03 ++#define BDC_GET_PAD_LEN(hdr) \ ++ ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \ ++ ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT))) ++#define BDC_SET_PAD_LEN(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \ ++ (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \ ++ ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \ ++ (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) ++ ++#define BDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) ++#define BDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) ++ ++struct bdc_header { ++ uint8 flags; /* Flags */ ++ uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */ ++ uint8 flags2; ++ uint8 dataOffset; /* Offset from end of BDC header to packet data, in ++ * 4-byte words. Leaves room for optional headers. ++ */ ++}; ++ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++ ++#endif /* _bcmcdc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmdefs.h b/drivers/bcmdrivers/gmac/src/include/bcmdefs.h +new file mode 100755 +index 0000000..e2b9b0e diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch new file mode 100644 index 00000000..b7bb9878 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch @@ -0,0 +1,342 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmdefs.h +@@ -0,0 +1,336 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc system wide definitions ++ * ++ * $Id: bcmdefs.h 316696 2012-02-23 03:29:35Z $ ++ */ ++ ++#ifndef _bcmdefs_h_ ++#define _bcmdefs_h_ ++ ++/* ++ * One doesn't need to include this file explicitly, gets included automatically if ++ * typedefs.h is included. ++ */ ++ ++/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function ++ * arguments or local variables. ++ */ ++#define BCM_REFERENCE(data) ((void)(data)) ++ ++/* Compile-time assert can be used in place of ASSERT if the expression evaluates ++ * to a constant at compile time. ++ */ ++#define STATIC_ASSERT(expr) { \ ++ /* Make sure the expression is constant. */ \ ++ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \ ++ /* Make sure the expression is true. */ \ ++ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \ ++} ++ ++/* Reclaiming text and data : ++ * The following macros specify special linker sections that can be reclaimed ++ * after a system is considered 'up'. ++ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN, ++ * as in most cases, the attach function calls the detach function to clean up on error). ++ */ ++#ifdef DONGLEBUILD ++ ++extern bool bcmreclaimed; ++extern bool attach_part_reclaimed; ++ ++#define BCMATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data ++#define BCMATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn ++ ++#ifndef PREATTACH_NORECLAIM ++#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini3." #_data))) _data ++#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini3." #_fn), noinline)) _fn ++#else ++#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data ++#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn ++#endif ++ ++#if defined(BCMRECLAIM) ++#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini1." #_data))) _data ++#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini1." #_fn), noinline)) _fn ++#define CONST ++#else ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define CONST const ++#endif ++ ++/* Non-manufacture or internal attach function/dat */ ++#if !defined(WLTEST) ++#define BCMNMIATTACHFN(_fn) BCMATTACHFN(_fn) ++#define BCMNMIATTACHDATA(_data) BCMATTACHDATA(_data) ++#else ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#endif ++ ++#define BCMUNINITFN(_fn) _fn ++ ++#define BCMFASTPATH ++#else /* DONGLEBUILD */ ++ ++#define bcmreclaimed 0 ++#define BCMATTACHDATA(_data) _data ++#define BCMATTACHFN(_fn) _fn ++#define BCMPREATTACHDATA(_data) _data ++#define BCMPREATTACHFN(_fn) _fn ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define BCMUNINITFN(_fn) _fn ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#define CONST const ++#if defined(__ARM_ARCH_7A__) ++#define BCM47XX_CA9 ++#else ++#undef BCM47XX_CA9 ++#endif ++#ifndef BCMFASTPATH ++#if defined(mips) || defined(BCM47XX_CA9) ++#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) ++#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) ++#else ++#define BCMFASTPATH ++#define BCMFASTPATH_HOST ++#endif ++#endif /* BCMFASTPATH */ ++ ++#endif /* DONGLEBUILD */ ++ ++#if defined(BCMROMBUILD) ++typedef struct { ++ uint16 esiz; ++ uint16 cnt; ++ void *addr; ++} bcmromdat_patch_t; ++#endif ++ ++/* Put some library data/code into ROM to reduce RAM requirements */ ++#if defined(BCMROMBUILD) && !defined(BCMROMSYMGEN_BUILD) && !defined(BCMJMPTBL_TCAM) ++#include ++#define STATIC static ++#else /* !BCMROMBUILD */ ++#define BCMROMDATA(_data) _data ++#define BCMROMDAT_NAME(_data) _data ++#define BCMROMFN(_fn) _fn ++#define BCMROMFN_NAME(_fn) _fn ++#define STATIC static ++#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) ++#define BCMROMDAT_SIZEOF(data) sizeof(data) ++#define BCMROMDAT_APATCH(data) ++#define BCMROMDAT_SPATCH(data) ++#endif /* !BCMROMBUILD */ ++ ++/* Bus types */ ++#define SI_BUS 0 /* SOC Interconnect */ ++#define PCI_BUS 1 /* PCI target */ ++#define PCMCIA_BUS 2 /* PCMCIA target */ ++#define SDIO_BUS 3 /* SDIO target */ ++#define JTAG_BUS 4 /* JTAG */ ++#define USB_BUS 5 /* USB (does not support R/W REG) */ ++#define SPI_BUS 6 /* gSPI target */ ++#define RPC_BUS 7 /* RPC target */ ++ ++/* Allows size optimization for single-bus image */ ++#ifdef BCMBUSTYPE ++#define BUSTYPE(bus) (BCMBUSTYPE) ++#else ++#define BUSTYPE(bus) (bus) ++#endif ++ ++/* Allows size optimization for single-backplane image */ ++#ifdef BCMCHIPTYPE ++#define CHIPTYPE(bus) (BCMCHIPTYPE) ++#else ++#define CHIPTYPE(bus) (bus) ++#endif ++ ++ ++/* Allows size optimization for SPROM support */ ++#if defined(BCMSPROMBUS) ++#define SPROMBUS (BCMSPROMBUS) ++#elif defined(SI_PCMCIA_SROM) ++#define SPROMBUS (PCMCIA_BUS) ++#else ++#define SPROMBUS (PCI_BUS) ++#endif ++ ++/* Allows size optimization for single-chip image */ ++#ifdef BCMCHIPID ++#define CHIPID(chip) (BCMCHIPID) ++#else ++#define CHIPID(chip) (chip) ++#endif ++ ++#ifdef BCMCHIPREV ++#define CHIPREV(rev) (BCMCHIPREV) ++#else ++#define CHIPREV(rev) (rev) ++#endif ++ ++/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ ++#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ ++#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ ++#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ ++ ++#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ ++#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ ++#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ ++#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ ++ ++#ifdef BCMDMA64OSL ++typedef struct { ++ uint32 loaddr; ++ uint32 hiaddr; ++} dma64addr_t; ++ ++typedef dma64addr_t dmaaddr_t; ++#define PHYSADDRHI(_pa) ((_pa).hiaddr) ++#define PHYSADDRHISET(_pa, _val) \ ++ do { \ ++ (_pa).hiaddr = (_val); \ ++ } while (0) ++#define PHYSADDRLO(_pa) ((_pa).loaddr) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa).loaddr = (_val); \ ++ } while (0) ++ ++#else ++typedef unsigned long dmaaddr_t; ++#define PHYSADDRHI(_pa) (0) ++#define PHYSADDRHISET(_pa, _val) ++#define PHYSADDRLO(_pa) ((_pa)) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa) = (_val); \ ++ } while (0) ++#endif /* BCMDMA64OSL */ ++ ++/* One physical DMA segment */ ++typedef struct { ++ dmaaddr_t addr; ++ uint32 length; ++} hnddma_seg_t; ++ ++#if defined(MACOSX) ++/* In MacOS, the OS API may return large number of segments. Setting this number lower ++ * will result in failure of dma map ++ */ ++#define MAX_DMA_SEGS 8 ++#elif defined(__NetBSD__) ++/* In NetBSD we also want more segments because the lower level mbuf mapping api might ++ * allocate a large number of segments ++ */ ++#define MAX_DMA_SEGS 16 ++#else ++#define MAX_DMA_SEGS 4 ++#endif ++ ++ ++typedef struct { ++ void *oshdmah; /* Opaque handle for OSL to store its information */ ++ uint origsize; /* Size of the virtual packet */ ++ uint nsegs; ++ hnddma_seg_t segs[MAX_DMA_SEGS]; ++} hnddma_seg_map_t; ++ ++ ++/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). ++ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this value is at least as big ++ * as TXOFF. This value is used in dma_rxfill (hnddma.c). ++ */ ++ ++#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) ++/* add 40 bytes to allow for extra RPC header and info */ ++#define BCMEXTRAHDROOM 260 ++#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++#ifdef CTFMAP ++#define BCMEXTRAHDROOM 208 ++#else /* CTFMAP */ ++#define BCMEXTRAHDROOM 204 ++#endif /* CTFMAP */ ++#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#ifndef SDALIGN ++#define SDALIGN 32 ++#endif ++ ++/* Headroom required for dongle-to-host communication. Packets allocated ++ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should ++ * leave this much room in front for low-level message headers which may ++ * be needed to get across the dongle bus to the host. (These messages ++ * don't go over the network, so room for the full WL header above would ++ * be a waste.). ++*/ ++#define BCMDONGLEHDRSZ 12 ++#define BCMDONGLEPADSZ 16 ++ ++#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) ++ ++#ifdef BCMDBG ++ ++#ifndef BCMDBG_ERR ++#define BCMDBG_ERR ++#endif /* BCMDBG_ERR */ ++ ++#define BCMDBG_ASSERT ++ ++#endif /* BCMDBG */ ++ ++ ++/* Macros for doing definition and get/set of bitfields ++ * Usage example, e.g. a three-bit field (bits 4-6): ++ * #define _M BITFIELD_MASK(3) ++ * #define _S 4 ++ * ... ++ * regval = R_REG(osh, ®s->regfoo); ++ * field = GFIELD(regval, ); ++ * regval = SFIELD(regval, , 1); ++ * W_REG(osh, ®s->regfoo, regval); ++ */ ++#define BITFIELD_MASK(width) \ ++ (((unsigned)1 << (width)) - 1) ++#define GFIELD(val, field) \ ++ (((val) >> field ## _S) & field ## _M) ++#define SFIELD(val, field, bits) \ ++ (((val) & (~(field ## _M << field ## _S))) | \ ++ ((unsigned)(bits) << field ## _S)) ++ ++/* define BCMSMALL to remove misc features for memory-constrained environments */ ++#ifdef BCMSMALL ++#undef BCMSPACE ++#define bcmspace FALSE /* if (bcmspace) code is discarded */ ++#else ++#define BCMSPACE ++#define bcmspace TRUE /* if (bcmspace) code is retained */ ++#endif ++ ++/* Max. nvram variable table size */ ++#define MAXSZ_NVRAM_VARS 4096 ++ ++#ifdef EFI ++#define __attribute__(x) /* CSTYLED */ ++#endif ++ ++#endif /* _bcmdefs_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmdevs.h b/drivers/bcmdrivers/gmac/src/include/bcmdevs.h +new file mode 100755 +index 0000000..39918b9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch new file mode 100644 index 00000000..c8295ce1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch @@ -0,0 +1,868 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmdevs.h +@@ -0,0 +1,862 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom device-specific manifest constants. ++ * ++ * $Id: bcmdevs.h 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#ifndef _BCMDEVS_H ++#define _BCMDEVS_H ++ ++/* PCI vendor IDs */ ++#define VENDOR_EPIGRAM 0xfeda ++#define VENDOR_BROADCOM 0x14e4 ++#define VENDOR_3COM 0x10b7 ++#define VENDOR_NETGEAR 0x1385 ++#define VENDOR_DIAMOND 0x1092 ++#define VENDOR_INTEL 0x8086 ++#define VENDOR_DELL 0x1028 ++#define VENDOR_HP 0x103c ++#define VENDOR_HP_COMPAQ 0x0e11 ++#define VENDOR_APPLE 0x106b ++#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ ++#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ ++#define VENDOR_TI 0x104c /* Texas Instruments */ ++#define VENDOR_RICOH 0x1180 /* Ricoh */ ++#define VENDOR_JMICRON 0x197b ++ ++ ++/* PCMCIA vendor IDs */ ++#define VENDOR_BROADCOM_PCMCIA 0x02d0 ++ ++/* SDIO vendor IDs */ ++#define VENDOR_BROADCOM_SDIO 0x00BF ++ ++/* DONGLE VID/PIDs */ ++#define BCM_DNGL_VID 0x0a5c ++#define BCM_DNGL_BL_PID_4328 0xbd12 ++#define BCM_DNGL_BL_PID_4322 0xbd13 ++#define BCM_DNGL_BL_PID_4319 0xbd16 ++#define BCM_DNGL_BL_PID_43236 0xbd17 ++#define BCM_DNGL_BL_PID_4332 0xbd18 ++#define BCM_DNGL_BL_PID_4330 0xbd19 ++#define BCM_DNGL_BL_PID_4334 0xbd1a ++#define BCM_DNGL_BL_PID_43239 0xbd1b ++#define BCM_DNGL_BL_PID_4324 0xbd1c ++#define BCM_DNGL_BL_PID_4360 0xbd1d ++#define BCM_DNGL_BL_PID_4335 0xbd20 ++ ++#define BCM_DNGL_BDC_PID 0x0bdc ++#define BCM_DNGL_JTAG_PID 0x4a44 ++ ++/* HW USB BLOCK [CPULESS USB] PIDs */ ++#define BCM_HWUSB_PID_43239 43239 ++ ++/* PCI Device IDs */ ++#define BCM4210_DEVICE_ID 0x1072 /* never used */ ++#define BCM4230_DEVICE_ID 0x1086 /* never used */ ++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ ++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ ++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ ++#define BCM4211_DEVICE_ID 0x4211 ++#define BCM4231_DEVICE_ID 0x4231 ++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ ++#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ ++#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ ++#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ ++#define BCM4328_D11DUAL_ID 0x4314 /* 4328/4312 802.11a/g id */ ++#define BCM4328_D11G_ID 0x4315 /* 4328/4312 802.11g id */ ++#define BCM4328_D11A_ID 0x4316 /* 4328/4312 802.11a id */ ++#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ ++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ ++#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ ++#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */ ++#define BCM4325_D11G_ID 0x431c /* 4325 802.11g id */ ++#define BCM4325_D11A_ID 0x431d /* 4325 802.11a id */ ++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ ++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ ++#define BCM4306_UART_ID 0x4322 /* 4306 uart */ ++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ ++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ ++#define BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G_ID; INF w/loose binding war */ ++#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ ++#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */ ++#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ ++#define BCM4322_D11N_ID 0x432b /* 4322 802.11n dualband device */ ++#define BCM4322_D11N2G_ID 0x432c /* 4322 802.11n 2.4GHz device */ ++#define BCM4322_D11N5G_ID 0x432d /* 4322 802.11n 5GHz device */ ++#define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */ ++#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ ++#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ ++#define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */ ++#define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */ ++#define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */ ++#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ ++#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ ++#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ ++#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ ++#define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */ ++#define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */ ++#define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */ ++#define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */ ++#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ ++#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ ++#define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */ ++#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ ++#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ ++#define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */ ++#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ ++#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ ++#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ ++#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ ++#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ ++#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ ++#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ ++#define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ ++#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ ++#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ ++#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ ++#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ ++#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ ++#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ ++#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ ++#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ ++#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ ++#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ ++#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ ++#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ ++#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ ++#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ ++#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ ++#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ ++#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ ++#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ ++#define BCM4360_D11AC_ID 0x43a0 ++#define BCM4360_D11AC2G_ID 0x43a1 ++#define BCM4360_D11AC5G_ID 0x43a2 ++#define BCM4335_D11AC_ID 0x43ae ++#define BCM4335_D11AC2G_ID 0x43af ++#define BCM4335_D11AC5G_ID 0x43b0 ++#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ ++#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ ++#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ ++ ++/* PCI Subsystem ID */ ++#define BCM943228HMB_SSID_VEN1 0x0607 ++#define BCM94313HMGBL_SSID_VEN1 0x0608 ++#define BCM94313HMG_SSID_VEN1 0x0609 ++ ++ ++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ ++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ ++#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ ++#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */ ++#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ ++#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */ ++#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ ++#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */ ++#define BCM_SPIH_ID 0x43f6 /* Synopsis SPI Host Controller */ ++#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ ++#define BCM_JTAGM2_ID 0x43f9 /* BCM alternate jtagm device id */ ++#define SDHCI_FPGA_ID 0x43fa /* Standard SDIO Host Controller FPGA */ ++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ ++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ ++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ ++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ ++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ ++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ ++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ ++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ ++#define BCM47XX_AUDIO_ID 0x4711 /* 47xx audio codec */ ++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ ++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ ++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ ++#define BCM47XX_GMAC_ID 0x4715 /* 47xx Unimac based GbE */ ++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ ++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ ++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ ++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ ++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ ++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ ++#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ ++#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ ++#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ ++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ ++#define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */ ++#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ ++#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ ++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ ++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ ++#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */ ++#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */ ++#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */ ++#define R5C822_SDIOH_ID 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */ ++#define JMICRON_SDIOH_ID 0x2381 /* JMicron Standard SDIO Host Controller */ ++ ++/* Chip IDs */ ++#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ ++#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ ++#define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */ ++#define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ ++#define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ ++#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ ++#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ ++#define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ ++#define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ ++#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ ++#define BCM4320_CHIP_ID 0x4320 /* 4320 chipcommon chipid */ ++#define BCM4321_CHIP_ID 0x4321 /* 4321 chipcommon chipid */ ++#define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */ ++#define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */ ++#define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */ ++#define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */ ++#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ ++#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ ++#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ ++#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ ++#define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */ ++#define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */ ++#define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */ ++#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ ++#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ ++#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ ++#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ ++#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ ++#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ ++#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ ++#define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ ++#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ ++#define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ ++#define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */ ++#define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */ ++#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ ++#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ ++#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ ++#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ ++#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ ++#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ ++#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ ++#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ ++#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ ++#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ ++#define BCM4335_CHIP_ID 0x4335 ++#define BCM4360_CHIP_ID 0x4360 ++#define BCM43526_CHIP_ID 0xAA06 ++#define BCM4352_CHIP_ID 0x4352 ++ ++#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ ++#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ ++#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ ++#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ ++#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ ++#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ ++#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ ++#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ ++#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ ++#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ ++#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ ++#define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */ ++#define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */ ++#define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */ ++#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ ++#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */ ++#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */ ++#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */ ++#define BCM53010_CHIP_ID 53010 /* NS chipcommon chipid */ ++#define BCM56150_CHIP_ID 56150 /* HR2 chipcommon chipid */ ++#define BCM56340_CHIP_ID 56340 /* HX4 chipcommon chipid */ ++#define BCM53020_CHIP_ID 53020 /* NSP chipcommon chipid */ ++#define BCM56450_CHIP_ID 56450 /* KT2 chipcommon chipid */ ++ ++#if defined(CONFIG_MACH_NS) ++#define BCMIPROC_CHIP_ID BCM53010_CHIP_ID ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define BCMIPROC_CHIP_ID BCM56340_CHIP_ID ++#elif defined(CONFIG_MACH_HR2) ++#define BCMIPROC_CHIP_ID BCM56150_CHIP_ID ++#elif defined(CONFIG_MACH_NSP) ++#define BCMIPROC_CHIP_ID BCM53020_CHIP_ID ++#elif defined(CONFIG_MACH_KT2) ++#define BCMIPROC_CHIP_ID BCM56450_CHIP_ID ++#endif ++ ++#define IS_BCM5301X_CHIP_ID(id) (1) ++#define IS_IPROC_CHIP_ID(id) (((id) >= 53010 && (id) <= 53019) || \ ++ ((id) >= 56150 && (id) <= 56159) || \ ++ ((id) >= 56340 && (id) <= 56349) || \ ++ ((id) >= 53020 && (id) <= 53029) || \ ++ ((id) >= 56450 && (id) <= 56459)) ++ ++/* Package IDs */ ++#define BCM4303_PKG_ID 2 /* 4303 package id */ ++#define BCM4309_PKG_ID 1 /* 4309 package id */ ++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ ++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ ++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ ++#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */ ++#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */ ++#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */ ++#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */ ++#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */ ++#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */ ++#define BCM5354E_PKG_ID 1 /* 5354E package id */ ++#define BCM4716_PKG_ID 8 /* 4716 package id */ ++#define BCM4717_PKG_ID 9 /* 4717 package id */ ++#define BCM4718_PKG_ID 10 /* 4718 package id */ ++#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */ ++#define BCM5358U_PKG_ID 8 /* 5358U package id */ ++#define BCM5358_PKG_ID 9 /* 5358 package id */ ++#define BCM47186_PKG_ID 10 /* 47186 package id */ ++#define BCM5357_PKG_ID 11 /* 5357 package id */ ++#define BCM5356U_PKG_ID 12 /* 5356U package id */ ++#define BCM53572_PKG_ID 8 /* 53572 package id */ ++#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ ++#define BCM47188_PKG_ID 9 /* 47188 package id */ ++#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ ++#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ ++#define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ ++#define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ ++#define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ ++#define BCM4706L_PKG_ID 1 /* 4706L package id */ ++ ++#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ ++#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ ++#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ ++#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ ++#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ ++#define BCM4336_WLBGA_PKG_ID 0x8 ++#define BCM4330_WLBGA_PKG_ID 0x0 ++#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ ++#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */ ++#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ ++#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ ++#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ ++#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ ++ ++#define BCM4707_PKG_ID 1 /* 4707 package id */ ++#define BCM4708_PKG_ID 2 /* 4708 package id */ ++#define BCM4709_PKG_ID 0 /* 4709 package id */ ++ ++#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ ++ ++#define BCM4335_WLCSP_PKG_ID (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */ ++#define BCM4335_FCBGA_PKG_ID (0x1) /* FCBGA PC/Embeded/Media PCIE/SDIO */ ++#define BCM4335_WLBGA_PKG_ID (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */ ++#define BCM4335_FCBGAD_PKG_ID (0x3) /* FCBGA Debug Debug/Dev All if's. */ ++#define BCM4335_PKG_MASK (0x3) ++ ++/* boardflags */ ++#define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ ++#define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ ++#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ ++#define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ ++#define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ ++#define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ ++#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ ++#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ ++#define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ ++#define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ ++#define BFL_UNUSED 0x00000200 ++#define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ ++#define BFL_FEM 0x00000800 /* Board supports the Front End Module */ ++#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ ++#define BFL_HGPA 0x00002000 /* Board has a high gain PA */ ++#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */ ++#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ ++#define BFL_NOPA 0x00010000 /* Board has no PA */ ++#define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ ++#define BFL_PAREF 0x00040000 /* Board uses the PARef LDO */ ++#define BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */ ++#define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ ++#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ ++#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ ++#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ ++#define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ ++#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ ++#define BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */ ++#define BFL_FASTPWR 0x08000000 ++#define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ ++#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ ++#define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ ++#define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ ++#define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field ++ * when this flag is set ++ */ ++#define BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */ ++ ++/* boardflags2 */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ ++#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ ++#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ ++#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ ++#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ ++#define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ ++#define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ ++#define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace ++ * BFL2_BTC3WIRE ++ */ ++#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ ++#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ ++#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ ++#define BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */ ++#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ ++#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ ++#define BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */ ++#define BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */ ++#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ ++#define BFL2_IPALVLSHIFT_3P3 0x00020000 ++#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ ++#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */ ++ /* Most drivers will turn it off without this flag */ ++ /* to save power. */ ++ ++#define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ ++#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */ ++#define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value ++ * than programmed. The exact delta is decided by ++ * driver per chip/boardtype. This can be used ++ * when tempsense qualification happens after shipment ++ */ ++#define BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */ ++#define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ ++#define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */ ++ /* ucode control of eLNA during Tx */ ++#define BFL2_4313_RADIOREG 0x10000000 ++ /* board rework */ ++#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ ++ ++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ ++#define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ ++#define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ ++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ ++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ ++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ ++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ ++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ ++#define BOARD_GPIO_12 0x1000 /* gpio 12 */ ++#define BOARD_GPIO_13 0x2000 /* gpio 13 */ ++#define BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */ ++#define BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ ++#define BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ ++#define BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ ++#define BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ ++#define BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ ++#define BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ ++ ++#define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ ++#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ ++#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ ++ ++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ ++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */ ++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */ ++ ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define MIN_SLOW_CLK 32 /* us Slow clock period */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Reference Board Types */ ++#define BU4710_BOARD 0x0400 ++#define VSIM4710_BOARD 0x0401 ++#define QT4710_BOARD 0x0402 ++ ++#define BU4309_BOARD 0x040a ++#define BCM94309CB_BOARD 0x040b ++#define BCM94309MP_BOARD 0x040c ++#define BCM4309AP_BOARD 0x040d ++ ++#define BCM94302MP_BOARD 0x040e ++ ++#define BU4306_BOARD 0x0416 ++#define BCM94306CB_BOARD 0x0417 ++#define BCM94306MP_BOARD 0x0418 ++ ++#define BCM94710D_BOARD 0x041a ++#define BCM94710R1_BOARD 0x041b ++#define BCM94710R4_BOARD 0x041c ++#define BCM94710AP_BOARD 0x041d ++ ++#define BU2050_BOARD 0x041f ++ ++#define BCM94306P50_BOARD 0x0420 ++ ++#define BCM94309G_BOARD 0x0421 ++ ++#define BU4704_BOARD 0x0423 ++#define BU4702_BOARD 0x0424 ++ ++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ ++ ++#define MPSG4306_BOARD 0x0427 ++ ++#define BCM94702MN_BOARD 0x0428 ++ ++/* BCM4702 1U CompactPCI Board */ ++#define BCM94702CPCI_BOARD 0x0429 ++ ++/* BCM4702 with BCM95380 VLAN Router */ ++#define BCM95380RR_BOARD 0x042a ++ ++/* cb4306 with SiGe PA */ ++#define BCM94306CBSG_BOARD 0x042b ++ ++/* cb4306 with SiGe PA */ ++#define PCSG94306_BOARD 0x042d ++ ++/* bu4704 with sdram */ ++#define BU4704SD_BOARD 0x042e ++ ++/* Dual 11a/11g Router */ ++#define BCM94704AGR_BOARD 0x042f ++ ++/* 11a-only minipci */ ++#define BCM94308MP_BOARD 0x0430 ++ ++/* 4306/gprs combo */ ++#define BCM94306GPRS_BOARD 0x0432 ++ ++/* BCM5365/BCM4704 FPGA Bringup Board */ ++#define BU5365_FPGA_BOARD 0x0433 ++ ++#define BU4712_BOARD 0x0444 ++#define BU4712SD_BOARD 0x045d ++#define BU4712L_BOARD 0x045f ++ ++/* BCM4712 boards */ ++#define BCM94712AP_BOARD 0x0445 ++#define BCM94712P_BOARD 0x0446 ++ ++/* BCM4318 boards */ ++#define BU4318_BOARD 0x0447 ++#define CB4318_BOARD 0x0448 ++#define MPG4318_BOARD 0x0449 ++#define MP4318_BOARD 0x044a ++#define SD4318_BOARD 0x044b ++ ++/* BCM4313 boards */ ++#define BCM94313BU_BOARD 0x050f ++#define BCM94313HM_BOARD 0x0510 ++#define BCM94313EPA_BOARD 0x0511 ++#define BCM94313HMG_BOARD 0x051C ++ ++/* BCM63XX boards */ ++#define BCM96338_BOARD 0x6338 ++#define BCM96348_BOARD 0x6348 ++#define BCM96358_BOARD 0x6358 ++#define BCM96368_BOARD 0x6368 ++ ++/* Another mp4306 with SiGe */ ++#define BCM94306P_BOARD 0x044c ++ ++/* mp4303 */ ++#define BCM94303MP_BOARD 0x044e ++ ++/* mpsgh4306 */ ++#define BCM94306MPSGH_BOARD 0x044f ++ ++/* BRCM 4306 w/ Front End Modules */ ++#define BCM94306MPM 0x0450 ++#define BCM94306MPL 0x0453 ++ ++/* 4712agr */ ++#define BCM94712AGR_BOARD 0x0451 ++ ++/* pcmcia 4303 */ ++#define PC4303_BOARD 0x0454 ++ ++/* 5350K */ ++#define BCM95350K_BOARD 0x0455 ++ ++/* 5350R */ ++#define BCM95350R_BOARD 0x0456 ++ ++/* 4306mplna */ ++#define BCM94306MPLNA_BOARD 0x0457 ++ ++/* 4320 boards */ ++#define BU4320_BOARD 0x0458 ++#define BU4320S_BOARD 0x0459 ++#define BCM94320PH_BOARD 0x045a ++ ++/* 4306mph */ ++#define BCM94306MPH_BOARD 0x045b ++ ++/* 4306pciv */ ++#define BCM94306PCIV_BOARD 0x045c ++ ++#define BU4712SD_BOARD 0x045d ++ ++#define BCM94320PFLSH_BOARD 0x045e ++ ++#define BU4712L_BOARD 0x045f ++#define BCM94712LGR_BOARD 0x0460 ++#define BCM94320R_BOARD 0x0461 ++ ++#define BU5352_BOARD 0x0462 ++ ++#define BCM94318MPGH_BOARD 0x0463 ++ ++#define BU4311_BOARD 0x0464 ++#define BCM94311MC_BOARD 0x0465 ++#define BCM94311MCAG_BOARD 0x0466 ++ ++#define BCM95352GR_BOARD 0x0467 ++ ++/* bcm95351agr */ ++#define BCM95351AGR_BOARD 0x0470 ++ ++/* bcm94704mpcb */ ++#define BCM94704MPCB_BOARD 0x0472 ++ ++/* 4785 boards */ ++#define BU4785_BOARD 0x0478 ++ ++/* 4321 boards */ ++#define BU4321_BOARD 0x046b ++#define BU4321E_BOARD 0x047c ++#define MP4321_BOARD 0x046c ++#define CB2_4321_BOARD 0x046d ++#define CB2_4321_AG_BOARD 0x0066 ++#define MC4321_BOARD 0x046e ++ ++/* 4328 boards */ ++#define BU4328_BOARD 0x0481 ++#define BCM4328SDG_BOARD 0x0482 ++#define BCM4328SDAG_BOARD 0x0483 ++#define BCM4328UG_BOARD 0x0484 ++#define BCM4328UAG_BOARD 0x0485 ++#define BCM4328PC_BOARD 0x0486 ++#define BCM4328CF_BOARD 0x0487 ++ ++/* 4325 boards */ ++#define BCM94325DEVBU_BOARD 0x0490 ++#define BCM94325BGABU_BOARD 0x0491 ++ ++#define BCM94325SDGWB_BOARD 0x0492 ++ ++#define BCM94325SDGMDL_BOARD 0x04aa ++#define BCM94325SDGMDL2_BOARD 0x04c6 ++#define BCM94325SDGMDL3_BOARD 0x04c9 ++ ++#define BCM94325SDABGWBA_BOARD 0x04e1 ++ ++/* 4322 boards */ ++#define BCM94322MC_SSID 0x04a4 ++#define BCM94322USB_SSID 0x04a8 /* dualband */ ++#define BCM94322HM_SSID 0x04b0 ++#define BCM94322USB2D_SSID 0x04bf /* single band discrete front end */ ++ ++/* 4312 boards */ ++#define BCM4312MCGSG_BOARD 0x04b5 ++ ++/* 4315 boards */ ++#define BCM94315DEVBU_SSID 0x04c2 ++#define BCM94315USBGP_SSID 0x04c7 ++#define BCM94315BGABU_SSID 0x04ca ++#define BCM94315USBGP41_SSID 0x04cb ++ ++/* 4319 boards */ ++#define BCM94319DEVBU_SSID 0X04e5 ++#define BCM94319USB_SSID 0X04e6 ++#define BCM94319SD_SSID 0X04e7 ++ ++/* 4716 boards */ ++#define BCM94716NR2_SSID 0x04cd ++ ++/* 4319 boards */ ++#define BCM94319DEVBU_SSID 0X04e5 ++#define BCM94319USBNP4L_SSID 0X04e6 ++#define BCM94319WLUSBN4L_SSID 0X04e7 ++#define BCM94319SDG_SSID 0X04ea ++#define BCM94319LCUSBSDN4L_SSID 0X04eb ++#define BCM94319USBB_SSID 0x04ee ++#define BCM94319LCSDN4L_SSID 0X0507 ++#define BCM94319LSUSBN4L_SSID 0X0508 ++#define BCM94319SDNA4L_SSID 0X0517 ++#define BCM94319SDELNA4L_SSID 0X0518 ++#define BCM94319SDELNA6L_SSID 0X0539 ++#define BCM94319ARCADYAN_SSID 0X0546 ++#define BCM94319WINDSOR_SSID 0x0561 ++#define BCM94319MLAP_SSID 0x0562 ++#define BCM94319SDNA_SSID 0x058b ++#define BCM94319BHEMU3_SSID 0x0563 ++#define BCM94319SDHMB_SSID 0x058c ++#define BCM94319SDBREF_SSID 0x05a1 ++#define BCM94319USBSDB_SSID 0x05a2 ++ ++ ++/* 4329 boards */ ++#define BCM94329AGB_SSID 0X04b9 ++#define BCM94329TDKMDL1_SSID 0X04ba ++#define BCM94329TDKMDL11_SSID 0X04fc ++#define BCM94329OLYMPICN18_SSID 0X04fd ++#define BCM94329OLYMPICN90_SSID 0X04fe ++#define BCM94329OLYMPICN90U_SSID 0X050c ++#define BCM94329OLYMPICN90M_SSID 0X050b ++#define BCM94329AGBF_SSID 0X04ff ++#define BCM94329OLYMPICX17_SSID 0X0504 ++#define BCM94329OLYMPICX17M_SSID 0X050a ++#define BCM94329OLYMPICX17U_SSID 0X0509 ++#define BCM94329OLYMPICUNO_SSID 0X0564 ++#define BCM94329MOTOROLA_SSID 0X0565 ++#define BCM94329OLYMPICLOCO_SSID 0X0568 ++/* 4336 SDIO board types */ ++#define BCM94336SD_WLBGABU_SSID 0x0511 ++#define BCM94336SD_WLBGAREF_SSID 0x0519 ++#define BCM94336SDGP_SSID 0x0538 ++#define BCM94336SDG_SSID 0x0519 ++#define BCM94336SDGN_SSID 0x0538 ++#define BCM94336SDGFC_SSID 0x056B ++ ++/* 4330 SDIO board types */ ++#define BCM94330SDG_SSID 0x0528 ++#define BCM94330SD_FCBGABU_SSID 0x052e ++#define BCM94330SD_WLBGABU_SSID 0x052f ++#define BCM94330SD_FCBGA_SSID 0x0530 ++#define BCM94330FCSDAGB_SSID 0x0532 ++#define BCM94330OLYMPICAMG_SSID 0x0549 ++#define BCM94330OLYMPICAMGEPA_SSID 0x054F ++#define BCM94330OLYMPICUNO3_SSID 0x0551 ++#define BCM94330WLSDAGB_SSID 0x0547 ++#define BCM94330CSPSDAGBB_SSID 0x054A ++ ++/* 43224 boards */ ++#define BCM943224X21 0x056e ++#define BCM943224X21_FCC 0x00d1 ++#define BCM943224X21B 0x00e9 ++#define BCM943224M93 0x008b ++#define BCM943224M93A 0x0090 ++#define BCM943224X16 0x0093 ++#define BCM94322X9 0x008d ++#define BCM94322M35e 0x008e ++ ++/* 43228 Boards */ ++#define BCM943228BU8_SSID 0x0540 ++#define BCM943228BU9_SSID 0x0541 ++#define BCM943228BU_SSID 0x0542 ++#define BCM943227HM4L_SSID 0x0543 ++#define BCM943227HMB_SSID 0x0544 ++#define BCM943228HM4L_SSID 0x0545 ++#define BCM943228SD_SSID 0x0573 ++ ++/* 43239 Boards */ ++#define BCM943239MOD_SSID 0x05ac ++#define BCM943239REF_SSID 0x05aa ++ ++/* 4331 boards */ ++#define BCM94331X19 0x00D6 /* X19B */ ++#define BCM94331X28 0x00E4 /* X28 */ ++#define BCM94331X28B 0x010E /* X28B */ ++#define BCM94331PCIEBT3Ax_SSID BCM94331X28 ++#define BCM94331X12_2G_SSID 0x00EC /* X12 2G */ ++#define BCM94331X12_5G_SSID 0x00ED /* X12 5G */ ++#define BCM94331X29B 0x00EF /* X29B */ ++#define BCM94331CSAX_SSID BCM94331X29B ++#define BCM94331X19C 0x00F5 /* X19C */ ++#define BCM94331X33 0x00F4 /* X33 */ ++#define BCM94331BU_SSID 0x0523 ++#define BCM94331S9BU_SSID 0x0524 ++#define BCM94331MC_SSID 0x0525 ++#define BCM94331MCI_SSID 0x0526 ++#define BCM94331PCIEBT4_SSID 0x0527 ++#define BCM94331HM_SSID 0x0574 ++#define BCM94331PCIEDUAL_SSID 0x059B ++#define BCM94331MCH5_SSID 0x05A9 ++#define BCM94331CS_SSID 0x05C6 ++#define BCM94331CD_SSID 0x05DA ++ ++/* 4314 Boards */ ++#define BCM94314BU_SSID 0x05b1 ++ ++/* 53572 Boards */ ++#define BCM953572BU_SSID 0x058D ++#define BCM953572NR2_SSID 0x058E ++#define BCM947188NR2_SSID 0x058F ++#define BCM953572SDRNR2_SSID 0x0590 ++ ++/* 43236 boards */ ++#define BCM943236OLYMPICSULLEY_SSID 0x594 ++#define BCM943236PREPROTOBLU2O3_SSID 0x5b9 ++#define BCM943236USBELNA_SSID 0x5f8 ++ ++/* 4314 Boards */ ++#define BCM94314BUSDIO_SSID 0x05c8 ++#define BCM94314BGABU_SSID 0x05c9 ++#define BCM94314HMEPA_SSID 0x05ca ++#define BCM94314HMEPABK_SSID 0x05cb ++#define BCM94314SUHMEPA_SSID 0x05cc ++#define BCM94314SUHM_SSID 0x05cd ++#define BCM94314HM_SSID 0x05d1 ++ ++/* 4334 Boards */ ++#define BCM94334FCAGBI_SSID 0x05df ++#define BCM94334WLAGBI_SSID 0x05dd ++ ++/* 43217 Boards */ ++#define BCM943217BU_SSID 0x05d5 ++#define BCM943217HM2L_SSID 0x05d6 ++#define BCM943217HMITR2L_SSID 0x05d7 ++ ++/* 43142 Boards */ ++#define BCM943142HM_SSID 0x05e0 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* # of GPIO pins */ ++#define GPIO_NUMPINS 32 ++ ++/* These values are used by dhd host driver. */ ++#define RDL_RAM_BASE_4319 0x60000000 ++#define RDL_RAM_BASE_4329 0x60000000 ++#define RDL_RAM_SIZE_4319 0x48000 ++#define RDL_RAM_SIZE_4329 0x48000 ++#define RDL_RAM_SIZE_43236 0x70000 ++#define RDL_RAM_BASE_43236 0x60000000 ++#define RDL_RAM_SIZE_4328 0x60000 ++#define RDL_RAM_BASE_4328 0x80000000 ++#define RDL_RAM_SIZE_4322 0x60000 ++#define RDL_RAM_BASE_4322 0x60000000 ++#define RDL_RAM_SIZE_4360 0xE0000 ++#define RDL_RAM_BASE_4360 0x60000000 ++ ++/* generic defs for nvram "muxenab" bits ++* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options. ++*/ ++#define MUXENAB_UART 0x00000001 ++#define MUXENAB_GPIO 0x00000002 ++#define MUXENAB_ERCX 0x00000004 ++#define MUXENAB_JTAG 0x00000008 ++#define MUXENAB_HOST_WAKE 0x00000010 ++ ++/* Boot flags */ ++#define FLASH_KERNEL_NFLASH 0x00000001 ++#define FLASH_BOOT_NFLASH 0x00000002 ++ ++#endif /* _BCMDEVS_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmendian.h b/drivers/bcmdrivers/gmac/src/include/bcmendian.h +new file mode 100755 +index 0000000..6e810d3 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch new file mode 100644 index 00000000..daeb4572 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch @@ -0,0 +1,330 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmendian.h +@@ -0,0 +1,324 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Byte order utilities ++ * ++ * $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $ ++ * ++ * This file by default provides proper behavior on little-endian architectures. ++ * On big-endian architectures, IL_BIGENDIAN should be defined. ++ */ ++ ++#ifndef _BCMENDIAN_H_ ++#define _BCMENDIAN_H_ ++ ++#include ++ ++/* Reverse the bytes in a 16-bit value */ ++#define BCMSWAP16(val) \ ++ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \ ++ (((uint16)(val) & (uint16)0xff00U) >> 8))) ++ ++/* Reverse the bytes in a 32-bit value */ ++#define BCMSWAP32(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \ ++ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \ ++ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \ ++ (((uint32)(val) & (uint32)0xff000000U) >> 24))) ++ ++/* Reverse the two 16-bit halves of a 32-bit value */ ++#define BCMSWAP32BY16(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \ ++ (((uint32)(val) & (uint32)0xffff0000U) >> 16))) ++ ++/* Byte swapping macros ++ * Host <=> Network (Big Endian) for 16- and 32-bit values ++ * Host <=> Little-Endian for 16- and 32-bit values ++ */ ++#ifndef hton16 ++#ifndef IL_BIGENDIAN ++#define HTON16(i) BCMSWAP16(i) ++#define hton16(i) bcmswap16(i) ++#define HTON32(i) BCMSWAP32(i) ++#define hton32(i) bcmswap32(i) ++#define NTOH16(i) BCMSWAP16(i) ++#define ntoh16(i) bcmswap16(i) ++#define NTOH32(i) BCMSWAP32(i) ++#define ntoh32(i) bcmswap32(i) ++#define LTOH16(i) (i) ++#define ltoh16(i) (i) ++#define LTOH32(i) (i) ++#define ltoh32(i) (i) ++#define HTOL16(i) (i) ++#define htol16(i) (i) ++#define HTOL32(i) (i) ++#define htol32(i) (i) ++#else /* IL_BIGENDIAN */ ++#define HTON16(i) (i) ++#define hton16(i) (i) ++#define HTON32(i) (i) ++#define hton32(i) (i) ++#define NTOH16(i) (i) ++#define ntoh16(i) (i) ++#define NTOH32(i) (i) ++#define ntoh32(i) (i) ++#define LTOH16(i) BCMSWAP16(i) ++#define ltoh16(i) bcmswap16(i) ++#define LTOH32(i) BCMSWAP32(i) ++#define ltoh32(i) bcmswap32(i) ++#define HTOL16(i) BCMSWAP16(i) ++#define htol16(i) bcmswap16(i) ++#define HTOL32(i) BCMSWAP32(i) ++#define htol32(i) bcmswap32(i) ++#endif /* IL_BIGENDIAN */ ++#endif /* hton16 */ ++ ++#ifndef IL_BIGENDIAN ++#define ltoh16_buf(buf, i) ++#define htol16_buf(buf, i) ++#else ++#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) ++#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) ++#endif /* IL_BIGENDIAN */ ++ ++/* Unaligned loads and stores in host byte order */ ++#ifndef IL_BIGENDIAN ++#define load32_ua(a) ltoh32_ua(a) ++#define store32_ua(a, v) htol32_ua_store(v, a) ++#define load16_ua(a) ltoh16_ua(a) ++#define store16_ua(a, v) htol16_ua_store(v, a) ++#else ++#define load32_ua(a) ntoh32_ua(a) ++#define store32_ua(a, v) hton32_ua_store(v, a) ++#define load16_ua(a) ntoh16_ua(a) ++#define store16_ua(a, v) hton16_ua_store(v, a) ++#endif /* IL_BIGENDIAN */ ++ ++#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) ++#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) ++#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) ++#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) ++ ++#define ltoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#define ntoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#ifdef __GNUC__ ++ ++/* GNU macro versions avoid referencing the argument multiple times, while also ++ * avoiding the -fno-inline used in ROM builds. ++ */ ++ ++#define bcmswap16(val) ({ \ ++ uint16 _val = (val); \ ++ BCMSWAP16(_val); \ ++}) ++ ++#define bcmswap32(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32(_val); \ ++}) ++ ++#define bcmswap32by16(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32BY16(_val); \ ++}) ++ ++#define bcmswap16_buf(buf, len) ({ \ ++ uint16 *_buf = (uint16 *)(buf); \ ++ uint _wds = (len) / 2; \ ++ while (_wds--) { \ ++ *_buf = bcmswap16(*_buf); \ ++ _buf++; \ ++ } \ ++}) ++ ++#define htol16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = _val >> 8; \ ++}) ++ ++#define htol32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = (_val >> 8) & 0xff; \ ++ _bytes[2] = (_val >> 16) & 0xff; \ ++ _bytes[3] = _val >> 24; \ ++}) ++ ++#define hton16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 8; \ ++ _bytes[1] = _val & 0xff; \ ++}) ++ ++#define hton32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 24; \ ++ _bytes[1] = (_val >> 16) & 0xff; \ ++ _bytes[2] = (_val >> 8) & 0xff; \ ++ _bytes[3] = _val & 0xff; \ ++}) ++ ++#define ltoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH16_UA(_bytes); \ ++}) ++ ++#define ltoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH32_UA(_bytes); \ ++}) ++ ++#define ntoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH16_UA(_bytes); \ ++}) ++ ++#define ntoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH32_UA(_bytes); \ ++}) ++ ++#else /* !__GNUC__ */ ++ ++/* Inline versions avoid referencing the argument multiple times */ ++static INLINE uint16 ++bcmswap16(uint16 val) ++{ ++ return BCMSWAP16(val); ++} ++ ++static INLINE uint32 ++bcmswap32(uint32 val) ++{ ++ return BCMSWAP32(val); ++} ++ ++static INLINE uint32 ++bcmswap32by16(uint32 val) ++{ ++ return BCMSWAP32BY16(val); ++} ++ ++/* Reverse pairs of bytes in a buffer (not for high-performance use) */ ++/* buf - start of buffer of shorts to swap */ ++/* len - byte length of buffer */ ++static INLINE void ++bcmswap16_buf(uint16 *buf, uint len) ++{ ++ len = len / 2; ++ ++ while (len--) { ++ *buf = bcmswap16(*buf); ++ buf++; ++ } ++} ++ ++/* ++ * Store 16-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = val >> 8; ++} ++ ++/* ++ * Store 32-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = (val >> 8) & 0xff; ++ bytes[2] = (val >> 16) & 0xff; ++ bytes[3] = val >> 24; ++} ++ ++/* ++ * Store 16-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 8; ++ bytes[1] = val & 0xff; ++} ++ ++/* ++ * Store 32-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 24; ++ bytes[1] = (val >> 16) & 0xff; ++ bytes[2] = (val >> 8) & 0xff; ++ bytes[3] = val & 0xff; ++} ++ ++/* ++ * Load 16-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint16 ++ltoh16_ua(const void *bytes) ++{ ++ return _LTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint32 ++ltoh32_ua(const void *bytes) ++{ ++ return _LTOH32_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 16-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint16 ++ntoh16_ua(const void *bytes) ++{ ++ return _NTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint32 ++ntoh32_ua(const void *bytes) ++{ ++ return _NTOH32_UA((const uint8 *)bytes); ++} ++ ++#endif /* !__GNUC__ */ ++#endif /* !_BCMENDIAN_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h b/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h +new file mode 100755 +index 0000000..6f733fc diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch new file mode 100644 index 00000000..adaa42e3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch @@ -0,0 +1,94 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific MIB definition for ++ * Broadcom Home Networking Division ++ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. ++ * ++ * $Id: bcmenetmib.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetmib_h_ ++#define _bcmenetmib_h_ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* ++ * EMAC MIB Registers ++ */ ++typedef volatile struct { ++ uint32 tx_good_octets; ++ uint32 tx_good_pkts; ++ uint32 tx_octets; ++ uint32 tx_pkts; ++ uint32 tx_broadcast_pkts; ++ uint32 tx_multicast_pkts; ++ uint32 tx_len_64; ++ uint32 tx_len_65_to_127; ++ uint32 tx_len_128_to_255; ++ uint32 tx_len_256_to_511; ++ uint32 tx_len_512_to_1023; ++ uint32 tx_len_1024_to_max; ++ uint32 tx_jabber_pkts; ++ uint32 tx_oversize_pkts; ++ uint32 tx_fragment_pkts; ++ uint32 tx_underruns; ++ uint32 tx_total_cols; ++ uint32 tx_single_cols; ++ uint32 tx_multiple_cols; ++ uint32 tx_excessive_cols; ++ uint32 tx_late_cols; ++ uint32 tx_defered; ++ uint32 tx_carrier_lost; ++ uint32 tx_pause_pkts; ++ uint32 PAD[8]; ++ ++ uint32 rx_good_octets; ++ uint32 rx_good_pkts; ++ uint32 rx_octets; ++ uint32 rx_pkts; ++ uint32 rx_broadcast_pkts; ++ uint32 rx_multicast_pkts; ++ uint32 rx_len_64; ++ uint32 rx_len_65_to_127; ++ uint32 rx_len_128_to_255; ++ uint32 rx_len_256_to_511; ++ uint32 rx_len_512_to_1023; ++ uint32 rx_len_1024_to_max; ++ uint32 rx_jabber_pkts; ++ uint32 rx_oversize_pkts; ++ uint32 rx_fragment_pkts; ++ uint32 rx_missed_pkts; ++ uint32 rx_crc_align_errs; ++ uint32 rx_undersize; ++ uint32 rx_crc_errs; ++ uint32 rx_align_errs; ++ uint32 rx_symbol_errs; ++ uint32 rx_pause_pkts; ++ uint32 rx_nonpause_pkts; ++} bcmenetmib_t; ++ ++#endif /* _bcmenetmib_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h b/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h +new file mode 100755 +index 0000000..19c9c86 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch new file mode 100644 index 00000000..33bbb94e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch @@ -0,0 +1,93 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc Broadcom BCM47XX MDC/MDIO enet phy definitions. ++ * ++ * $Id: bcmenetphy.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetphy_h_ ++#define _bcmenetphy_h_ ++ ++/* phy address */ ++#define MAXEPHY 32 /* mdio phy addresses are 5bit quantities */ ++#define EPHY_MASK 0x1f /* phy mask */ ++#define EPHY_NONE 31 /* nvram: no phy present at all */ ++#define EPHY_NOREG 30 /* nvram: no local phy regs */ ++ ++#define MAXPHYREG 32 /* max 32 registers per phy */ ++ ++/* just a few phy registers */ ++#define CTL_RESET (1 << 15) /* reset */ ++#define CTL_LOOP (1 << 14) /* loopback */ ++#define CTL_SPEED (1 << 13) /* speed selection lsb 0=10, 1=100 */ ++#define CTL_ANENAB (1 << 12) /* autonegotiation enable */ ++#define CTL_RESTART (1 << 9) /* restart autonegotiation */ ++#define CTL_DUPLEX (1 << 8) /* duplex mode 0=half, 1=full */ ++#define CTL_SPEED_MSB (1 << 6) /* speed selection msb */ ++ ++#define CTL_SPEED_10 ((0 << 6) | (0 << 13)) /* speed selection CTL.6=0, CTL.13=0 */ ++#define CTL_SPEED_100 ((0 << 6) | (1 << 13)) /* speed selection CTL.6=0, CTL.13=1 */ ++#define CTL_SPEED_1000 ((1 << 6) | (0 << 13)) /* speed selection CTL.6=1, CTL.13=0 */ ++ ++#define ADV_10FULL (1 << 6) /* autonegotiate advertise 10full */ ++#define ADV_10HALF (1 << 5) /* autonegotiate advertise 10half */ ++#define ADV_100FULL (1 << 8) /* autonegotiate advertise 100full */ ++#define ADV_100HALF (1 << 7) /* autonegotiate advertise 100half */ ++#define ADV_PAUSE (1 << 10) /* autonegotiate advertise pause */ ++ ++/* link partner ability register */ ++#define LPA_SLCT 0x001f /* same as advertise selector */ ++#define LPA_10HALF 0x0020 /* can do 10mbps half-duplex */ ++#define LPA_10FULL 0x0040 /* can do 10mbps full-duplex */ ++#define LPA_100HALF 0x0080 /* can do 100mbps half-duplex */ ++#define LPA_100FULL 0x0100 /* can do 100mbps full-duplex */ ++#define LPA_100BASE4 0x0200 /* can do 100mbps 4k packets */ ++#define LPA_RESV 0x1c00 /* unused */ ++#define LPA_RFAULT 0x2000 /* link partner faulted */ ++#define LPA_LPACK 0x4000 /* link partner acked us */ ++#define LPA_NPAGE 0x8000 /* next page bit */ ++ ++#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) ++#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) ++ ++/* 1000BASE-T control register */ ++#define ADV_1000HALF 0x0100 /* advertise 1000BASE-T half duplex */ ++#define ADV_1000FULL 0x0200 /* advertise 1000BASE-T full duplex */ ++ ++/* 1000BASE-T status register */ ++#define LPA_1000HALF 0x0400 /* link partner 1000BASE-T half duplex */ ++#define LPA_1000FULL 0x0800 /* link partner 1000BASE-T full duplex */ ++ ++/* 1000BASE-T extended status register */ ++#define EST_1000THALF 0x1000 /* 1000BASE-T half duplex capable */ ++#define EST_1000TFULL 0x2000 /* 1000BASE-T full duplex capable */ ++#define EST_1000XHALF 0x4000 /* 1000BASE-X half duplex capable */ ++#define EST_1000XFULL 0x8000 /* 1000BASE-X full duplex capable */ ++ ++#define STAT_REMFAULT (1 << 4) /* remote fault */ ++#define STAT_LINK (1 << 2) /* link status */ ++#define STAT_JAB (1 << 1) /* jabber detected */ ++#define AUX_FORCED (1 << 2) /* forced 10/100 */ ++#define AUX_SPEED (1 << 1) /* speed 0=10mbps 1=100mbps */ ++#define AUX_DUPLEX (1 << 0) /* duplex 0=half 1=full */ ++ ++#endif /* _bcmenetphy_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h b/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h +new file mode 100755 +index 0000000..b82e0fe diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch new file mode 100644 index 00000000..9a2fd4d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch @@ -0,0 +1,56 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific Receive Data Header for the ++ * Broadcom Home Networking Division ++ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. ++ * ++ * $Id: bcmenetrxh.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetrxh_h_ ++#define _bcmenetrxh_h_ ++ ++/* ++ * The Ethernet MAC core returns an 8-byte Receive Frame Data Header ++ * with every frame consisting of ++ * 16bits of frame length, followed by ++ * 16bits of EMAC rx descriptor info, followed by 32bits of undefined. ++ */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++ uint16 pad[12]; ++} bcmenetrxh_t; ++ ++#define RXHDR_LEN 28 /* Header length */ ++ ++#define RXF_L ((uint16)1 << 11) /* last buffer in a frame */ ++#define RXF_MISS ((uint16)1 << 7) /* received due to promisc mode */ ++#define RXF_BRDCAST ((uint16)1 << 6) /* dest is broadcast address */ ++#define RXF_MULT ((uint16)1 << 5) /* dest is multicast address */ ++#define RXF_LG ((uint16)1 << 4) /* frame length > rxmaxlength */ ++#define RXF_NO ((uint16)1 << 3) /* odd number of nibbles */ ++#define RXF_RXER ((uint16)1 << 2) /* receive symbol error */ ++#define RXF_CRC ((uint16)1 << 1) /* crc error */ ++#define RXF_OV ((uint16)1 << 0) /* fifo overflow */ ++ ++#endif /* _bcmenetrxh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h b/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h +new file mode 100755 +index 0000000..6f0cf09 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch new file mode 100644 index 00000000..ff31dd8b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch @@ -0,0 +1,123 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h +@@ -0,0 +1,117 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific MIB definition for ++ * Broadcom Home Networking Division ++ * GbE Unimac core ++ * ++ * $Id: bcmgmacmib.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmgmacmib_h_ ++#define _bcmgmacmib_h_ ++ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* GMAC MIB structure */ ++ ++typedef struct _gmacmib { ++ uint32 tx_good_octets; /* 0x300 */ ++ uint32 tx_good_octets_high; /* 0x304 */ ++ uint32 tx_good_pkts; /* 0x308 */ ++ uint32 tx_octets; /* 0x30c */ ++ uint32 tx_octets_high; /* 0x310 */ ++ uint32 tx_pkts; /* 0x314 */ ++ uint32 tx_broadcast_pkts; /* 0x318 */ ++ uint32 tx_multicast_pkts; /* 0x31c */ ++ uint32 tx_len_64; /* 0x320 */ ++ uint32 tx_len_65_to_127; /* 0x324 */ ++ uint32 tx_len_128_to_255; /* 0x328 */ ++ uint32 tx_len_256_to_511; /* 0x32c */ ++ uint32 tx_len_512_to_1023; /* 0x330 */ ++ uint32 tx_len_1024_to_1522; /* 0x334 */ ++ uint32 tx_len_1523_to_2047; /* 0x338 */ ++ uint32 tx_len_2048_to_4095; /* 0x33c */ ++ uint32 tx_len_4095_to_8191; /* 0x340 */ ++ uint32 tx_len_8192_to_max; /* 0x344 */ ++ uint32 tx_jabber_pkts; /* 0x348 */ ++ uint32 tx_oversize_pkts; /* 0x34c */ ++ uint32 tx_fragment_pkts; /* 0x350 */ ++ uint32 tx_underruns; /* 0x354 */ ++ uint32 tx_total_cols; /* 0x358 */ ++ uint32 tx_single_cols; /* 0x35c */ ++ uint32 tx_multiple_cols; /* 0x360 */ ++ uint32 tx_excessive_cols; /* 0x364 */ ++ uint32 tx_late_cols; /* 0x368 */ ++ uint32 tx_defered; /* 0x36c */ ++ uint32 tx_carrier_lost; /* 0x370 */ ++ uint32 tx_pause_pkts; /* 0x374 */ ++ uint32 tx_uni_pkts; /* 0x378 */ ++ uint32 tx_q0_pkts; /* 0x37c */ ++ uint32 tx_q0_octets; /* 0x380 */ ++ uint32 tx_q0_octets_high; /* 0x384 */ ++ uint32 tx_q1_pkts; /* 0x388 */ ++ uint32 tx_q1_octets; /* 0x38c */ ++ uint32 tx_q1_octets_high; /* 0x390 */ ++ uint32 tx_q2_pkts; /* 0x394 */ ++ uint32 tx_q2_octets; /* 0x398 */ ++ uint32 tx_q2_octets_high; /* 0x39c */ ++ uint32 tx_q3_pkts; /* 0x3a0 */ ++ uint32 tx_q3_octets; /* 0x3a4 */ ++ uint32 tx_q3_octets_high; /* 0x3a8 */ ++ uint32 PAD; ++ uint32 rx_good_octets; /* 0x3b0 */ ++ uint32 rx_good_octets_high; /* 0x3b4 */ ++ uint32 rx_good_pkts; /* 0x3b8 */ ++ uint32 rx_octets; /* 0x3bc */ ++ uint32 rx_octets_high; /* 0x3c0 */ ++ uint32 rx_pkts; /* 0x3c4 */ ++ uint32 rx_broadcast_pkts; /* 0x3c8 */ ++ uint32 rx_multicast_pkts; /* 0x3cc */ ++ uint32 rx_len_64; /* 0x3d0 */ ++ uint32 rx_len_65_to_127; /* 0x3d4 */ ++ uint32 rx_len_128_to_255; /* 0x3d8 */ ++ uint32 rx_len_256_to_511; /* 0x3dc */ ++ uint32 rx_len_512_to_1023; /* 0x3e0 */ ++ uint32 rx_len_1024_to_1522; /* 0x3e4 */ ++ uint32 rx_len_1523_to_2047; /* 0x3e8 */ ++ uint32 rx_len_2048_to_4095; /* 0x3ec */ ++ uint32 rx_len_4095_to_8191; /* 0x3f0 */ ++ uint32 rx_len_8192_to_max; /* 0x3f4 */ ++ uint32 rx_jabber_pkts; /* 0x3f8 */ ++ uint32 rx_oversize_pkts; /* 0x3fc */ ++ uint32 rx_fragment_pkts; /* 0x400 */ ++ uint32 rx_missed_pkts; /* 0x404 */ ++ uint32 rx_crc_align_errs; /* 0x408 */ ++ uint32 rx_undersize; /* 0x40c */ ++ uint32 rx_crc_errs; /* 0x410 */ ++ uint32 rx_align_errs; /* 0x414 */ ++ uint32 rx_symbol_errs; /* 0x418 */ ++ uint32 rx_pause_pkts; /* 0x41c */ ++ uint32 rx_nonpause_pkts; /* 0x420 */ ++ uint32 rx_sachanges; /* 0x424 */ ++ uint32 rx_uni_pkts; /* 0x428 */ ++} gmacmib_t; ++ ++#define GM_MIB_BASE 0x300 ++#define GM_MIB_LIMIT 0x800 ++ ++#endif /* _bcmgmacmib_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h b/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h +new file mode 100755 +index 0000000..c3d58e9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch new file mode 100644 index 00000000..09401730 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch @@ -0,0 +1,59 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific Receive Data Header for the ++ * Broadcom Home Networking Division ++ * BCM47XX GbE cores. ++ * ++ * $Id: bcmgmacrxh.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmgmacrxh_h_ ++#define _bcmgmacrxh_h_ ++ ++/* ++ * The Ethernet GMAC core returns an 8-byte Receive Frame Data Header ++ * with every frame consisting of ++ * 16 bits of frame length, followed by ++ * 16 bits of GMAC rx descriptor info, followed by 32bits of undefined. ++ */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++ uint16 pad[12]; ++} bcmgmacrxh_t; ++ ++#define RXHDR_LEN 28 /* Header length */ ++ ++#define GRXF_DT_MASK ((uint16)0xf) /* data type */ ++#define GRXF_DT_SHIFT 12 ++#define GRXF_DC_MASK ((uint16)0xf) /* (num descr to xfer the frame) - 1 */ ++#define GRXF_DC_SHIFT 8 ++#define GRXF_OVF ((uint16)1 << 7) /* overflow error occured */ ++#define GRXF_CTFERR ((uint16)1 << 6) /* overflow error occured */ ++#define GRXF_OVERSIZE ((uint16)1 << 4) /* frame size > rxmaxlength */ ++#define GRXF_CRC ((uint16)1 << 3) /* crc error */ ++#define GRXF_VLAN ((uint16)1 << 2) /* vlan tag detected */ ++#define GRXF_PT_MASK ((uint16)3) /* packet type 0 - Unicast, ++ * 1 - Multicast, 2 - Broadcast ++ */ ++ ++#endif /* _bcmgmacrxh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h +new file mode 100755 +index 0000000..3698729 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch new file mode 100644 index 00000000..9ab89f01 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch @@ -0,0 +1,273 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h +@@ -0,0 +1,267 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy_h_ ++#define _bcm_iproc_phy_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++/* ++ * Defines: SOC_E_XXX ++ * Purpose: SOC API error codes ++ * Notes: ++ * An error code may be converted to a string by passing ++ * the code to soc_errmsg(). ++ */ ++ ++typedef enum { ++ SOC_E_NONE = 0, ++ SOC_E_INTERNAL = -1, ++ SOC_E_MEMORY = -2, ++ SOC_E_UNIT = -3, ++ SOC_E_PARAM = -4, ++ SOC_E_EMPTY = -5, ++ SOC_E_FULL = -6, ++ SOC_E_NOT_FOUND = -7, ++ SOC_E_EXISTS = -8, ++ SOC_E_TIMEOUT = -9, ++ SOC_E_BUSY = -10, ++ SOC_E_FAIL = -11, ++ SOC_E_DISABLED = -12, ++ SOC_E_BADID = -13, ++ SOC_E_RESOURCE = -14, ++ SOC_E_CONFIG = -15, ++ SOC_E_UNAVAIL = -16, ++ SOC_E_INIT = -17, ++ SOC_E_PORT = -18, ++ ++ SOC_E_LIMIT = -19 /* Must come last */ ++} soc_error_t; ++ ++#define SOC_SUCCESS(rv) ((rv) >= 0) ++#define SOC_FAILURE(rv) ((rv) < 0) ++ ++typedef enum _soc_port_if_e { ++ SOC_PORT_IF_NOCXN, /* No physical connection */ ++ SOC_PORT_IF_NULL, /* Pass-through connection without PHY */ ++ SOC_PORT_IF_MII, ++ SOC_PORT_IF_GMII, ++ SOC_PORT_IF_SGMII, ++ SOC_PORT_IF_TBI, ++ SOC_PORT_IF_XGMII, ++ SOC_PORT_IF_RGMII, ++ SOC_PORT_IF_RvMII, ++ SOC_PORT_IF_SFI, ++ SOC_PORT_IF_XFI, ++ SOC_PORT_IF_KR, ++ SOC_PORT_IF_KR4, ++ SOC_PORT_IF_CR, ++ SOC_PORT_IF_CR4, ++ SOC_PORT_IF_XLAUI, ++ SOC_PORT_IF_SR, ++ SOC_PORT_IF_RXAUI, ++ SOC_PORT_IF_XAUI, ++ SOC_PORT_IF_SPAUI, ++ SOC_PORT_IF_QSGMII, ++ SOC_PORT_IF_ILKN, ++ SOC_PORT_IF_RCY, ++ SOC_PORT_IF_FAT_PIPE, ++ SOC_PORT_IF_CGMII, ++ SOC_PORT_IF_CAUI, ++ SOC_PORT_IF_LR, ++ SOC_PORT_IF_LR4, ++ SOC_PORT_IF_SR4, ++ SOC_PORT_IF_KX, ++ SOC_PORT_IF_CPU, ++ SOC_PORT_IF_OLP, ++ SOC_PORT_IF_OAMP, ++ SOC_PORT_IF_ERP, ++ SOC_PORT_IF_COUNT /* last, please */ ++} _soc_port_if_t; ++typedef _soc_port_if_t soc_port_if_t; ++ ++ ++/* 1000BASE-T/100BASE-TX/10BASE-T MII Control Register (Addr 00h) */ ++#define PHY_MII_CTRLr_FLAGS 0x00 ++#define PHY_MII_CTRLr_BANK 0x0000 ++#define PHY_MII_CTRLr_ADDR 0x00 ++/* 1000BASE-T/100BASE-TX/10BASE-T MII Status Register (ADDR 01h) */ ++#define PHY_MII_STATr_FLAGS 0x00 ++#define PHY_MII_STATr_BANK 0x0000 ++#define PHY_MII_STATr_ADDR 0x01 ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 02h) */ ++#define PHY_MII_PHY_ID0r_FLAGS _SOC_PHY_REG_DIRECT ++#define PHY_MII_PHY_ID0r_BANK 0x0000 ++#define PHY_MII_PHY_ID0r_ADDR 0x02 ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 03h) */ ++#define PHY_MII_PHY_ID1r_FLAGS _SOC_PHY_REG_DIRECT ++#define PHY_MII_PHY_ID1r_BANK 0x0000 ++#define PHY_MII_PHY_ID1r_ADDR 0x03 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Advertisment Register (ADDR 04h) */ ++#define PHY_MII_ANAr_FLAGS 0x00 ++#define PHY_MII_ANAr_BANK 0x0000 ++#define PHY_MII_ANAr_ADDR 0x04 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Link Partner Ability (ADDR 05h) */ ++#define PHY_MII_ANPr_FLAGS 0x00 ++#define PHY_MII_ANPr_BANK 0x0000 ++#define PHY_MII_ANPr_ADDR 0x05 ++/* 1000BASE-T Control Register (ADDR 09h) */ ++#define PHY_MII_GB_CTRLr_FLAGS 0x00 ++#define PHY_MII_GB_CTRLr_BANK 0x0000 ++#define PHY_MII_GB_CTRLr_ADDR 0x09 ++/* 1000BASE-T Status Register (ADDR 0ah) */ ++#define PHY_MII_GB_STATr_FLAGS 0x00 ++#define PHY_MII_GB_STATr_BANK 0x0000 ++#define PHY_MII_GB_STATr_ADDR 0x0a ++/* 1000BASE-T/100BASE-TX/10BASE-T IEEE Extended Status Register (ADDR 0fh) */ ++#define PHY_MII_ESRr_FLAGS 0x00 ++#define PHY_MII_ESRr_BANK 0x0000 ++#define PHY_MII_ESRr_ADDR 0x0f ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Extended Control Register (ADDR 10h) */ ++#define PHY_MII_ECRr_FLAGS 0x00 ++#define PHY_MII_ECRr_BANK 0x0000 ++#define PHY_MII_ECRr_ADDR 0x10 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auxiliary Control Reg (ADDR 18h Shadow 000)*/ ++#define PHY_MII_AUX_CTRLr_FLAGS 0x00 ++#define PHY_MII_AUX_CTRLr_BANK 0x0000 ++#define PHY_MII_AUX_CTRLr_ADDR 0x18 ++/* 1000BASE-T/100BASE-TX/10BASE-T Power/MII Control Reg (ADDR 18h Shadow 010)*/ ++#define PHY_MII_POWER_CTRLr_FLAGS 0x00 ++#define PHY_MII_POWER_CTRLr_BANK 0x0002 ++#define PHY_MII_POWER_CTRLr_ADDR 0x18 ++/* Auxiliary 1000BASE-X Control Reg (ADDR 1ch shadow 11011) */ ++#define PHY_AUX_1000X_CTRLr_FLAGS 0x00 ++#define PHY_AUX_1000X_CTRLr_BANK 0x001B ++#define PHY_AUX_1000X_CTRLr_ADDRS 0x1c ++/* Mode Control Reg (ADDR 1ch shadow 11111) */ ++#define PHY_MODE_CTRLr_FLAGS 0x00 ++#define PHY_MODE_CTRLr_BANK 0x001F ++#define PHY_MODE_CTRLr_ADDR 0x1c ++ ++/* ++ * Primary SerDes Registers ++ */ ++/* 1000BASE-X MII Control Register (Addr 00h) */ ++#define PHY_1000X_MII_CTRLr_FLAGS SOC_PHY_REG_1000X ++#define PHY_1000X_MII_CTRLr_BANK 0x0000 ++#define PHY_1000X_MII_CTRLr_ADDR 0x00 ++ ++ ++/* MII Control Register: bit definitions */ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++/* ++ * MII Status Register: See 802.3, 1998 pg 544 ++ */ ++#define MII_STAT_EXT (1 << 0) /* Extended Registers */ ++#define MII_STAT_JBBR (1 << 1) /* Jabber Detected */ ++#define MII_STAT_LA (1 << 2) /* Link Active */ ++#define MII_STAT_AN_CAP (1 << 3) /* Autoneg capable */ ++#define MII_STAT_RF (1 << 4) /* Remote Fault */ ++#define MII_STAT_AN_DONE (1 << 5) /* Autoneg complete */ ++#define MII_STAT_MF_PS (1 << 6) /* Preamble suppression */ ++#define MII_STAT_ES (1 << 8) /* Extended status (R15) */ ++#define MII_STAT_HD_100_T2 (1 << 9) /* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_100_T2 (1 << 10)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_HD_10 (1 << 11)/* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_10 (1 << 12)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_HD_100 (1 << 13)/* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_100 (1 << 14)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_100_T4 (1 << 15)/* Full duplex 100Mb/s supported */ ++ ++/* ++ * MII Link Advertisment ++ */ ++#define MII_ANA_ASF (1 << 0)/* Advertise Selector Field */ ++#define MII_ANA_HD_10 (1 << 5)/* Half duplex 10Mb/s supported */ ++#define MII_ANA_FD_10 (1 << 6)/* Full duplex 10Mb/s supported */ ++#define MII_ANA_HD_100 (1 << 7)/* Half duplex 100Mb/s supported */ ++#define MII_ANA_FD_100 (1 << 8)/* Full duplex 100Mb/s supported */ ++#define MII_ANA_T4 (1 << 9)/* T4 */ ++#define MII_ANA_PAUSE (1 << 10)/* Pause supported */ ++#define MII_ANA_ASYM_PAUSE (1 << 11)/* Asymmetric pause supported */ ++#define MII_ANA_RF (1 << 13)/* Remote fault */ ++#define MII_ANA_NP (1 << 15)/* Next Page */ ++ ++#define MII_ANA_ASF_802_3 (1) /* 802.3 PHY */ ++ ++/* ++ * 1000Base-T Control Register ++ */ ++#define MII_GB_CTRL_MS_MAN (1 << 12) /* Manual Master/Slave mode */ ++#define MII_GB_CTRL_MS (1 << 11) /* Master/Slave negotiation mode */ ++#define MII_GB_CTRL_PT (1 << 10) /* Port type */ ++#define MII_GB_CTRL_ADV_1000FD (1 << 9) /* Advertise 1000Base-T FD */ ++#define MII_GB_CTRL_ADV_1000HD (1 << 8) /* Advertise 1000Base-T HD */ ++ ++/* ++ * 1000Base-T Status Register ++ */ ++#define MII_GB_STAT_MS_FAULT (1 << 15) /* Master/Slave Fault */ ++#define MII_GB_STAT_MS (1 << 14) /* Master/Slave, 1 == Master */ ++#define MII_GB_STAT_LRS (1 << 13) /* Local receiver status */ ++#define MII_GB_STAT_RRS (1 << 12) /* Remote receiver status */ ++#define MII_GB_STAT_LP_1000FD (1 << 11) /* Link partner 1000FD capable */ ++#define MII_GB_STAT_LP_1000HD (1 << 10) /* Link partner 1000HD capable */ ++#define MII_GB_STAT_IDE (0xff << 0) /* Idle error count */ ++ ++/* ++ * IEEE Extended Status Register ++ */ ++#define MII_ESR_1000_X_FD (1 << 15) /* 1000Base-T FD capable */ ++#define MII_ESR_1000_X_HD (1 << 14) /* 1000Base-T HD capable */ ++#define MII_ESR_1000_T_FD (1 << 13) /* 1000Base-T FD capable */ ++#define MII_ESR_1000_T_HD (1 << 12) /* 1000Base-T FD capable */ ++ ++/* MII Extended Control Register (BROADCOM) */ ++#define MII_ECR_FE (1 << 0) /* FIFO Elasticity */ ++#define MII_ECR_TLLM (1 << 1) /* Three link LED mode */ ++#define MII_ECR_ET_IPG (1 << 2) /* Extended XMIT IPG mode */ ++#define MII_ECR_FLED_OFF (1 << 3) /* Force LED off */ ++#define MII_ECR_FLED_ON (1 << 4) /* Force LED on */ ++#define MII_ECR_ELT (1 << 5) /* Enable LED traffic */ ++#define MII_ECR_RS (1 << 6) /* Reset Scrambler */ ++#define MII_ECR_BRSA (1 << 7) /* Bypass Receive Sym. align */ ++#define MII_ECR_BMLT3 (1 << 8) /* Bypass MLT3 Encoder/Decoder */ ++#define MII_ECR_BSD (1 << 9) /* Bypass Scramble/Descramble */ ++#define MII_ECR_B4B5B (1 << 10) /* Bypass 4B/5B Encode/Decode */ ++#define MII_ECR_FI (1 << 11) /* Force Interrupt */ ++#define MII_ECR_ID (1 << 12) /* Interrupt Disable */ ++#define MII_ECR_TD (1 << 13) /* XMIT Disable */ ++#define MII_ECR_DAMC (1 << 14) /* DIsable Auto-MDI Crossover */ ++#define MII_ECR_10B (1 << 15) /* 1 == 10B, 0 == GMII */ ++ ++#endif /* _bcm_iproc_phy_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h +new file mode 100755 +index 0000000..523c8e1 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch new file mode 100644 index 00000000..e93ef478 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch @@ -0,0 +1,51 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy5221_h_ ++#define _bcm_iproc_phy5221_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++#define PHY_AUX_MULTIPLE_PHYr_BANK 0x0000 ++#define PHY_AUX_MULTIPLE_PHYr_ADDR 0x1e ++ ++#define PHY522X_SUPER_ISOLATE_MODE (1<<3) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern int phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask); ++extern int phy5221_init(uint eth_num, uint phyaddr); ++extern int phy5221_link_get(uint eth_num, uint phyaddr, int *link); ++extern int phy5221_enable_set(uint eth_num, uint phyaddr, int enable); ++extern int phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); ++ ++#endif /* _bcm_iproc_phy5221_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h +new file mode 100755 +index 0000000..a366dd8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch new file mode 100644 index 00000000..41b215f9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch @@ -0,0 +1,52 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy5461s_h_ ++#define _bcm_iproc_phy5461s_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++/* Indirect PHY register address flags */ ++#define SOC_PHY_REG_RESERVE_ACCESS 0x20000000 ++#define SOC_PHY_REG_1000X 0x40000000 ++#define SOC_PHY_REG_INDIRECT 0x80000000 ++#define _SOC_PHY_REG_DIRECT ((SOC_PHY_REG_1000X << 1) | (SOC_PHY_REG_1000X >> 1)) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern int phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask); ++extern int phy5461_init(uint eth_num, uint phyaddr); ++extern int phy5461_link_get(uint eth_num, uint phyaddr, int *link); ++extern int phy5461_enable_set(uint eth_num, uint phyaddr, int enable); ++extern int phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); ++ ++#endif /* _bcm_iproc_phy5461s_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h +new file mode 100755 +index 0000000..d8e0a39 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch new file mode 100644 index 00000000..794c4995 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++#ifndef _bcm_iproc_robo_serdes_h_ ++#define _bcm_iproc_robo_serdes_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include "bcmrobo.h" ++ ++#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ ++ ++/* ++ * MII Link Advertisment (Clause 37) ++ */ ++#define MII_ANA_C37_NP (1 << 15) /* Next Page */ ++#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ ++#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ ++#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ ++#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ ++#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ ++#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ ++#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ ++#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ ++ ++/* MII Control Register: bit definitions */ ++ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++#define GPIO_SFP0_TXDIS 26 ++#define GPIO_SFP1_TXDIS 27 ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern uint16 robo_serdes_get_id(robo_info_t *robo, uint page, uint off); ++extern void robo_serdes_reset(robo_info_t *robo, uint page); ++extern int robo_serdes_reset_core(robo_info_t *robo, uint page); ++extern int robo_serdes_start_pll(robo_info_t *robo, uint page); ++extern int robo_serdes_init(robo_info_t *robo, uint page); ++extern int robo_serdes_enable_set(robo_info_t *robo, uint page, int enable); ++extern int robo_serdes_speed_set(robo_info_t *robo, uint page, int speed); ++extern int robo_serdes_speed_get(robo_info_t *robo, uint page, int *speed); ++ ++#endif /* _bcm_iproc_serdes_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h +new file mode 100755 +index 0000000..f9abc47 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch new file mode 100644 index 00000000..64223745 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++#ifndef _bcm_iproc_serdes_h_ ++#define _bcm_iproc_serdes_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ ++ ++/* ++ * MII Link Advertisment (Clause 37) ++ */ ++#define MII_ANA_C37_NP (1 << 15) /* Next Page */ ++#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ ++#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ ++#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ ++#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ ++#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ ++#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ ++#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ ++#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ ++ ++/* MII Control Register: bit definitions */ ++ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern void serdes_set_blk(uint eth_num, uint phyaddr, uint blk); ++extern void serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data); ++extern uint16 serdes_rd_reg(uint eth_num, uint phyaddr, uint reg); ++extern uint16 serdes_get_id(uint eth_num, uint phyaddr, uint off); ++extern void serdes_reset(uint eth_num, uint phyaddr); ++extern int serdes_reset_core(uint eth_num, uint phyaddr); ++extern int serdes_start_pll(uint eth_num, uint phyaddr); ++extern int serdes_init(uint eth_num, uint phyaddr); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++extern int serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx); ++extern int serdes_set_asym_mode(uint eth_num, uint phyaddr); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++#endif /* _bcm_iproc_serdes_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h +new file mode 100755 +index 0000000..5bd5abd diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch new file mode 100644 index 00000000..f6f227d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch @@ -0,0 +1,312 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h +@@ -0,0 +1,306 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These are serdes defines ++ * ++ */ ++ ++#ifndef _PHY_XGXS16G_H_ ++#define _PHY_XGXS16G_H_ ++ ++/* macros */ ++ ++/* Macros ONLY used after initialization */ ++#define XGXS16G_2p5G_ID(id2) ((id2 & 0xff) == 0xf) ++ ++ ++/****************************************************************************/ ++/***** Starting below is auto-generated register macros from RDB files *****/ ++/****************************************************************************/ ++ ++/**************************************************************************** ++ * Core Enums. ++ ***************************************************************************/ ++ ++#define XGXS16G_IEEE0BLK_IEEECONTROL0r 0x00000000 ++#define XGXS16G_XGXSBLK0_XGXSCONTROLr 0x00008000 ++#define XGXS16G_XGXSBLK0_XGXSSTATUSr 0x00008001 ++#define XGXS16G_XGXSBLK0_MMDSELECTr 0x0000800d ++#define XGXS16G_XGXSBLK0_MISCCONTROL1r 0x0000800e ++#define XGXS16G_XGXSBLK1_LANECTRL0r 0x00008015 ++#define XGXS16G_XGXSBLK1_LANECTRL1r 0x00008016 ++#define XGXS16G_XGXSBLK1_LANECTRL3r 0x00008018 ++#define XGXS16G_TX0_TX_ACONTROL0r 0x00008061 ++#define XGXS16G_RX0_RX_CONTROLr 0x000080b1 ++#define XGXS16G_AN73_PDET_PARDET10GCONTROLr 0x00008131 ++#define XGXS16G_XGXSBLK7_EEECONTROLr 0x00008150 ++#define XGXS16G_TX_LN_SWAP1r 0x00008169 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X1r 0x00008300 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X2r 0x00008301 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X3r 0x00008302 ++#define XGXS16G_SERDESDIGITAL_STATUS1000X1r 0x00008304 ++#define XGXS16G_SERDESDIGITAL_MISC1r 0x00008308 ++#define XGXS16G_SERDESID_SERDESID0r 0x00008310 ++#define XGXS16G_SERDESID_SERDESID1r 0x00008311 ++#define XGXS16G_SERDESID_SERDESID2r 0x00008312 ++#define XGXS16G_SERDESID_SERDESID3r 0x00008313 ++#define XGXS16G_REMOTEPHY_MISC3r 0x0000833c ++#define XGXS16G_REMOTEPHY_MISC5r 0x0000833e ++#define XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr 0x00008350 ++#define XGXS16G_BAM_NEXTPAGE_UD_FIELDr 0x00008357 ++#define XGXS16G_COMBO_IEEE0_MIICNTLr 0x0000ffe0 ++#define XGXS16G_COMBO_IEEE0_AUTONEGADVr 0x0000ffe4 ++ ++ ++/**************************************************************************** ++ * XGXS16G_IEEE_ieee0Blk ++ ***************************************************************************/ ++/**************************************************************************** ++ * ieee0Blk :: ieeeControl0 ++ ***************************************************************************/ ++/* ieee0Blk :: ieeeControl0 :: rst_hw [15:15] */ ++#define IEEE0BLK_IEEECONTROL0_RST_HW_MASK 0x8000 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_SHIFT 15 ++ ++/* ieee0Blk :: ieeeControl0 :: gloopback [14:14] */ ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK 0x4000 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_SHIFT 14 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsControl ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsControl :: start_sequencer [13:13] */ ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK 0x2000 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_SHIFT 13 ++ ++/* XgxsBlk0 :: xgxsControl :: mode_10g [11:08] */ ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_MASK 0x0f00 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_BITS 4 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noCC 1 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane 6 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss_noCC 9 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass 10 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass_noDsk 11 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ComboCoreMode 12 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ClocksOff 15 ++ ++/* XgxsBlk0 :: xgxsControl :: hstl [05:05] */ ++#define XGXSBLK0_XGXSCONTROL_HSTL_MASK 0x0020 ++#define XGXSBLK0_XGXSCONTROL_HSTL_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_HSTL_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_HSTL_SHIFT 5 ++ ++/* XgxsBlk0 :: xgxsControl :: cdet_en [03:03] */ ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_MASK 0x0008 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_SHIFT 3 ++ ++/* XgxsBlk0 :: xgxsControl :: eden [02:02] */ ++#define XGXSBLK0_XGXSCONTROL_EDEN_MASK 0x0004 ++#define XGXSBLK0_XGXSCONTROL_EDEN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_EDEN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_EDEN_SHIFT 2 ++ ++/* XgxsBlk0 :: xgxsControl :: afrst_en [01:01] */ ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK 0x0002 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_SHIFT 1 ++ ++/* XgxsBlk0 :: xgxsControl :: txcko_div [00:00] */ ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK 0x0001 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsStatus ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsStatus :: txpll_lock [11:11] */ ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK 0x0800 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_ALIGN 0 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_BITS 1 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_SHIFT 11 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: miscControl1 ++ ***************************************************************************/ ++/* XgxsBlk0 :: miscControl1 :: PCS_dev_en_override [10:10] */ ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK 0x0400 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_SHIFT 10 ++ ++/* XgxsBlk0 :: miscControl1 :: PMD_dev_en_override [09:09] */ ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK 0x0200 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_SHIFT 9 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_autodet [01:01] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK 0x0002 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_SHIFT 1 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_val [00:00] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK 0x0001 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk1 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk1 :: laneCtrl0 ++ ***************************************************************************/ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_rx [07:04] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK 0x00f0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_SHIFT 4 ++ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_tx [03:00] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK 0x000f ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_TX0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * TX0 :: Tx_AControl0 ++ ***************************************************************************/ ++/* TX0 :: Tx_AControl0 :: txpol_flip [05:05] */ ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_MASK 0x0020 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_ALIGN 0 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_BITS 1 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_SHIFT 5 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_dsc_2_0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * dsc_2_0 :: dsc_ctrl0 ++ ***************************************************************************/ ++/* dsc_2_0 :: dsc_ctrl0 :: rxSeqStart [15:15] */ ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK 0x8000 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_ALIGN 0 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_BITS 1 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_SerdesDigital ++ ***************************************************************************/ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X1 :: crc_checker_disable [07:07] */ ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK 0x0080 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_SHIFT 7 ++ ++/* SerdesDigital :: Control1000X1 :: disable_pll_pwrdwn [06:06] */ ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK 0x0040 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_SHIFT 6 ++ ++/* SerdesDigital :: Control1000X1 :: fiber_mode_1000X [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X3 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X3 :: fifo_elasicity_tx_rx [02:01] */ ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK 0x0006 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_BITS 2 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_SHIFT 1 ++ ++/* SerdesDigital :: Control1000X3 :: tx_fifo_rst [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Status1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Status1000X1 :: speed_status [04:03] */ ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK 0x0018 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_ALIGN 0 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_BITS 2 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT 3 ++ ++/**************************************************************************** ++ * SerdesDigital :: Misc1 ++ ***************************************************************************/ ++/* SerdesDigital :: Misc1 :: force_speed_sel [04:04] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK 0x0010 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_BITS 1 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_SHIFT 4 ++ ++/* SerdesDigital :: Misc1 :: force_speed [03:00] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_MASK 0x000f ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_BITS 4 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * CL73_UserB0 :: CL73_BAMCtrl1 ++ ***************************************************************************/ ++/* CL73_UserB0 :: CL73_BAMCtrl1 :: CL73_bamEn [15:15] */ ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK 0x8000 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_ALIGN 0 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_BITS 1 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * Datatype Definitions. ++ ***************************************************************************/ ++#endif /* _PHY_XGXS16G_H_ */ ++ ++/* End of File */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmnvram.h b/drivers/bcmdrivers/gmac/src/include/bcmnvram.h +new file mode 100755 +index 0000000..a9c63d8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch new file mode 100644 index 00000000..cf3bb855 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch @@ -0,0 +1,301 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmnvram.h +@@ -0,0 +1,295 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * NVRAM variable manipulation ++ * ++ * $Id: bcmnvram.h 325984 2012-04-05 08:51:37Z $ ++ */ ++ ++#ifndef _bcmnvram_h_ ++#define _bcmnvram_h_ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++#include ++#include ++#include ++ ++struct nvram_header { ++ uint32 magic; ++ uint32 len; ++ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ ++ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ ++ uint32 config_ncdl; /* ncdl values for memc */ ++}; ++ ++struct nvram_otphdr { ++ struct nvram_header nvh; ++ uint16 flags_swmacm_gpio_phya; /* otp flags, switch/gmac mode, gpio, phyaddr */ ++ struct ether_addr mac; ++ uint32 clkfreq; ++}; ++ ++struct nvram_tuple { ++ char *name; ++ char *value; ++ struct nvram_tuple *next; ++}; ++ ++/* ++ * Get default value for an NVRAM variable ++ */ ++extern char *nvram_default_get(const char *name); ++ ++/* ++ * Initialize NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern int nvram_init(void *sih); ++ ++/* ++ * Append a chunk of nvram variables to the global list ++ */ ++extern int nvram_append(void *si, char *vars, uint varsz); ++ ++extern void nvram_get_global_vars(char **varlst, uint *varsz); ++ ++ ++/* ++ * Check for reset button press for restoring factory defaults. ++ */ ++extern int nvram_reset(void *sih); ++ ++/* ++ * Disable NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern void nvram_exit(void *sih); ++ ++/* ++ * Get the value of an NVRAM variable. The pointer returned may be ++ * invalid after a set. ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined ++ */ ++extern char * nvram_get(const char *name); ++ ++/* ++ * Read the reset GPIO value from the nvram and set the GPIO ++ * as input ++ */ ++extern int BCMINITFN(nvram_resetgpio_init)(void *sih); ++ ++/* ++ * Get the value of an NVRAM variable. ++ * @param name name of variable to get ++ * @return value of variable or NUL if undefined ++ */ ++static INLINE char * ++nvram_safe_get(const char *name) ++{ ++ char *p = nvram_get(name); ++ return p ? p : ""; ++} ++ ++/* ++ * Match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is string equal ++ * to match or FALSE otherwise ++ */ ++static INLINE int ++nvram_match(char *name, char *match) ++{ ++ const char *value = nvram_get(name); ++ return (value && !strcmp(value, match)); ++} ++ ++/* ++ * Inversely match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is not string ++ * equal to invmatch or FALSE otherwise ++ */ ++static INLINE int ++nvram_invmatch(char *name, char *invmatch) ++{ ++ const char *value = nvram_get(name); ++ return (value && strcmp(value, invmatch)); ++} ++ ++/* ++ * Set the value of an NVRAM variable. The name and value strings are ++ * copied into private storage. Pointers to previously set values ++ * may become invalid. The new value may be immediately ++ * retrieved but will not be permanently stored until a commit. ++ * @param name name of variable to set ++ * @param value value of variable ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_set(const char *name, const char *value); ++ ++/* ++ * Unset an NVRAM variable. Pointers to previously set values ++ * remain valid until a set. ++ * @param name name of variable to unset ++ * @return 0 on success and errno on failure ++ * NOTE: use nvram_commit to commit this change to flash. ++ */ ++extern int nvram_unset(const char *name); ++ ++/* ++ * NVRAM is based of FLASH or OTP. ++ * @return From FLASH: TRUE ++ * From OTP: FALSE ++ */ ++extern bool nvram_inotp(void); ++ ++/* ++ * Commit NVRAM header to OTP. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_otpcommit(void *sih); ++ ++/* ++ * Commit NVRAM variables to permanent storage. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_commit(void); ++ ++/* ++ * Get all NVRAM variables (format name=value\0 ... \0\0). ++ * @param buf buffer to store variables ++ * @param count size of buffer in bytes ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_getall(char *nvram_buf, int count); ++ ++/* ++ * returns the crc value of the nvram ++ * @param nvh nvram header pointer ++ */ ++uint8 nvram_calc_crc(struct nvram_header * nvh); ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* The NVRAM version number stored as an NVRAM variable */ ++#define NVRAM_SOFTWARE_VERSION "1" ++ ++#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ ++#define NVRAM_CLEAR_MAGIC 0x0 ++#define NVRAM_INVALID_MAGIC 0xFFFFFFFF ++#define NVRAM_VERSION 1 ++#define NVRAM_HEADER_SIZE 20 ++#define NVRAM_SPACE 0x8000 ++#define ENVRAM_SPACE 0x1000 ++ ++#define NVRAM_MAX_VALUE_LEN 255 ++#define NVRAM_MAX_PARAM_LEN 64 ++ ++#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */ ++#define NVRAM_CRC_VER_MASK 0xffffff00 /* for crc_ver_init */ ++ ++/* Incase of nvram header(in OTP), we save 16bit after nvram header ++ * o 0:0 Switch Present ++ * o 1:4 Switch and gmac mode ++ * o 5:10 robo reset GPIO pin number ++ * o 11:15 phyaddr ++ */ ++#define OTPNVRAM_SWITCH_PRESENT 0x1 ++ ++#define OTPNVRAM_FLAGS_MASK 0x1 ++#define OTPNVRAM_SMACMODE_MASK 0x1e ++#define OTPNVRAM_GPIO_MASK 0x7e0 ++#define OTPNVRAM_PHYADDR_MASK 0xf800 ++ ++#define OTPNVRAM_SMACMODE_SHIFT 1 ++#define OTPNVRAM_GPIO_SHIFT 5 ++#define OTPNVRAM_PHYADDR_SHIFT 11 ++ ++/* clkfreq is saved in following format in OTP nvram data ++ * 9:0 pci clock ++ * 20:10 si clock ++ * 31:21 mips clock ++ */ ++ ++#define NVRAM_PCI_CLKMASK 0x3ff ++#define NVRAM_SI_CLKMASK 0x1ffc00 ++#define NVRAM_SI_CLKSHIFT 10 ++#define NVRAM_CPUCLK_SHIFT 21 ++ ++/* Offsets to embedded nvram area */ ++#define NVRAM_START_COMPRESSED 0x400 ++#define NVRAM_START 0x1000 ++ ++#define BCM_JUMBO_NVRAM_DELIMIT '\n' ++#define BCM_JUMBO_START "Broadcom Jumbo Nvram file" ++ ++#if !defined(BCMHIGHSDIO) && defined(BCMTRXV2) ++extern char *_vars; ++extern uint _varsz; ++#endif ++ ++#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \ ++ defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__)) ++#define IMAGE_SIZE "image_size" ++#define BOOTPARTITION "bootpartition" ++#define IMAGE_BOOT BOOTPARTITION ++#define PARTIALBOOTS "partialboots" ++#define MAXPARTIALBOOTS "maxpartialboots" ++#define IMAGE_1ST_FLASH_TRX "flash0.trx" ++#define IMAGE_1ST_FLASH_OS "flash0.os" ++#define IMAGE_2ND_FLASH_TRX "flash0.trx2" ++#define IMAGE_2ND_FLASH_OS "flash0.os2" ++#define IMAGE_FIRST_OFFSET "image_first_offset" ++#define IMAGE_SECOND_OFFSET "image_second_offset" ++#define LINUX_FIRST "linux" ++#define LINUX_SECOND "linux2" ++#endif ++ ++#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \ ++ defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__)) ++/* Shared by all: CFE, Linux Kernel, and Ap */ ++#define IMAGE_BOOT "image_boot" ++#define BOOTPARTITION IMAGE_BOOT ++/* CFE variables */ ++#define IMAGE_1ST_FLASH_TRX "flash0.trx" ++#define IMAGE_1ST_FLASH_OS "flash0.os" ++#define IMAGE_2ND_FLASH_TRX "flash0.trx2" ++#define IMAGE_2ND_FLASH_OS "flash0.os2" ++#define IMAGE_SIZE "image_size" ++ ++/* CFE and Linux Kernel shared variables */ ++#define IMAGE_FIRST_OFFSET "image_first_offset" ++#define IMAGE_SECOND_OFFSET "image_second_offset" ++ ++/* Linux application variables */ ++#define LINUX_FIRST "linux" ++#define LINUX_SECOND "linux2" ++#define POLICY_TOGGLE "toggle" ++#define LINUX_PART_TO_FLASH "linux_to_flash" ++#define LINUX_FLASH_POLICY "linux_flash_policy" ++ ++#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */ ++ ++int nvram_env_gmac_name(int gmac, char *name); ++ ++#endif /* _bcmnvram_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmotp.h b/drivers/bcmdrivers/gmac/src/include/bcmotp.h +new file mode 100755 +index 0000000..d1ec475 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch new file mode 100644 index 00000000..f1095b67 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch @@ -0,0 +1,87 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmotp.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OTP support. ++ * ++ * $Id: bcmotp.h 321779 2012-03-16 19:39:00Z $ ++ */ ++ ++#ifndef _bcmotp_h_ ++#define _bcmotp_h_ ++ ++/* OTP regions */ ++#define OTP_HW_RGN 1 ++#define OTP_SW_RGN 2 ++#define OTP_CI_RGN 4 ++#define OTP_FUSE_RGN 8 ++#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */ ++ ++/* OTP Size */ ++#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ ++ ++/* Fixed size subregions sizes in words */ ++#define OTPGU_CI_SZ 2 ++ ++/* OTP usage */ ++#define OTP4325_FM_DISABLED_OFFSET 188 ++ ++#ifdef BCMNVRAMW ++/* Global RDE index for chips not having an OTP PMU resource. */ ++#define OTP_GLOBAL_RDE_IDX 0xFF ++#endif ++ ++/* Exported functions */ ++extern int otp_status(void *oh); ++extern int otp_size(void *oh); ++extern uint16 otp_read_bit(void *oh, uint offset); ++extern void* otp_init(si_t *sih); ++extern int otp_read_region(si_t *sih, int region, uint16 *data, uint *wlen); ++extern int otp_read_word(si_t *sih, uint wn, uint16 *data); ++extern int otp_nvread(void *oh, char *data, uint *len); ++#ifdef BCMNVRAMW ++extern int otp_write_region(si_t *sih, int region, uint16 *data, uint wlen); ++extern int otp_write_word(si_t *sih, uint wn, uint16 data); ++extern int otp_cis_append_region(si_t *sih, int region, char *vars, int count); ++extern int otp_lock(si_t *sih); ++extern int otp_nvwrite(void *oh, uint16 *data, uint wlen); ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) ++extern int otp_dump(void *oh, int arg, char *buf, uint size); ++extern int otp_dumpstats(void *oh, int arg, char *buf, uint size); ++#endif ++ ++#if defined(BCMNVRAMW) ++#define otp_write_rde(oh, rde, bit, val) ipxotp_write_rde(oh, rde, bit, val) ++extern int ipxotp_write_rde(void *oh, int rde, uint bit, uint val); ++extern int otp_write_bits(void *oh, uint offset, int bits, uint8* data); ++ ++#ifdef OTP_DEBUG ++extern int otp_verify1x(void *oh, uint off, uint fuse); ++extern int otp_read1x(void *oh, uint off, uint fuse); ++extern int otp_repair_bit(void *oh, uint off, uint val); ++extern int otp_write_ones(void *oh, uint off, uint bits); ++extern int otp_write_ones_old(void *oh, uint off, uint bits); ++#endif ++ ++#endif ++ ++#endif /* _bcmotp_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmparams.h b/drivers/bcmdrivers/gmac/src/include/bcmparams.h +new file mode 100755 +index 0000000..da6eb4c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch new file mode 100644 index 00000000..bb7540b5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch @@ -0,0 +1,38 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmparams.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc system wide parameters. ++ * ++ * $Id: bcmparams.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmparams_h_ ++#define _bcmparams_h_ ++ ++#define VLAN_MAXVID 15 /* Max. VLAN ID supported/allowed */ ++ ++#define VLAN_NUMPRIS 8 /* # of prio, start from 0 */ ++ ++#define DEV_NUMIFS 16 /* Max. # of devices/interfaces supported */ ++ ++#define WL_MAXBSSCFG 16 /* maximum number of BSS Configs we can configure */ ++ ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmperf.h b/drivers/bcmdrivers/gmac/src/include/bcmperf.h +new file mode 100755 +index 0000000..2ec4079 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch new file mode 100644 index 00000000..09d863ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch @@ -0,0 +1,46 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmperf.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Performance counters software interface. ++ * ++ * $Id: bcmperf.h 241182 2011-02-17 21:50:03Z $ ++ */ ++/* essai */ ++#ifndef _BCMPERF_H_ ++#define _BCMPERF_H_ ++/* get cache hits and misses */ ++#if defined(BCMMIPS) && defined(BCMPERFSTATS) ++#include ++#define BCMPERF_ENABLE_INSTRCOUNT() hndmips_perf_instrcount_enable() ++#define BCMPERF_ENABLE_ICACHE_MISS() hndmips_perf_icache_miss_enable() ++#define BCMPERF_ENABLE_ICACHE_HIT() hndmips_perf_icache_hit_enable() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = hndmips_perf_read_cache_miss()) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = hndmips_perf_read_cache_hit()) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = hndmips_perf_read_instrcount()) ++#else ++#define BCMPERF_ENABLE_INSTRCOUNT() ++#define BCMPERF_ENABLE_ICACHE_MISS() ++#define BCMPERF_ENABLE_ICACHE_HIT() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) ++#endif /* defined(mips) */ ++#endif /* _BCMPERF_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmrobo.h b/drivers/bcmdrivers/gmac/src/include/bcmrobo.h +new file mode 100755 +index 0000000..38f5a9f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch new file mode 100644 index 00000000..39b3425b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch @@ -0,0 +1,209 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmrobo.h +@@ -0,0 +1,203 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * RoboSwitch setup functions ++ * ++ * $Id: bcmrobo.h 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#ifndef _bcm_robo_h_ ++#define _bcm_robo_h_ ++ ++/* ++ * MODELID: ++ * 0x53010: BCM53010, Select Low SKU device if SKU ID[1:0] = 01. ++ * 0x53011: BCM53011, Select Middle SKU device if SKU ID[1:0] = 10. ++ * 0x53012: BCM53012, Select High SKU device if SKU ID[1:0] = 00. ++ * Note: The SKU ID[1:0] is loaded from OTP configuration data. ++ */ ++#define DEVID53010 0x53010 /* 53010 */ ++#define DEVID53011 0x53011 /* 53011 */ ++#define DEVID53012 0x53012 /* 53012 */ ++#define DEVID53013 0x53013 /* 53013 */ ++#define DEVID53014 0x53014 /* 53014 */ ++#define DEVID53015 0x53015 /* 53015 */ ++#define DEVID53016 0x53016 /* 53016 */ ++#define DEVID53017 0x53017 /* 53017 */ ++#define DEVID53018 0x53018 /* 53018 */ ++#define DEVID53019 0x53019 /* 53019 */ ++#define DEVID53022 0x53022 /* 53022 */ ++#define DEVID53025 0x53025 /* 53025 */ ++ ++#define ROBO_IS_BCM5301X(id) (1) ++#define ROBO_IS_VEGA(id) ((id) >= DEVID53014 && (id) <= DEVID53017) ++ ++#define OTP_SKU_ID_53014 0x2 ++#define OTP_SKU_ID_53015 0x3 ++#define OTP_SKU_ID_53016 0x4 ++ ++/* Power save duty cycle times */ ++#define MAX_NO_PHYS 5 ++#define PWRSAVE_SLEEP_TIME 12 ++#define PWRSAVE_WAKE_TIME 3 ++ ++/* Power save modes for the switch */ ++#define ROBO_PWRSAVE_NORMAL 0 ++#define ROBO_PWRSAVE_AUTO 1 ++#define ROBO_PWRSAVE_MANUAL 2 ++#define ROBO_PWRSAVE_AUTO_MANUAL 3 ++ ++#define ROBO_IS_PWRSAVE_MANUAL(r) ((r)->pwrsave_mode_manual) ++#define ROBO_IS_PWRSAVE_AUTO(r) ((r)->pwrsave_mode_auto) ++ ++/* NorthStar SRAB interface */ ++/* Access switch registers through SRAB (Switch Register Access Bridge) */ ++#define REG_VERSION_ID 0x40 ++#define REG_CTRL_PORT0_GMIIPO 0x58 /* 53012: GMII Port0 Override register */ ++#define REG_CTRL_PORT1_GMIIPO 0x59 /* 53012: GMII Port1 Override register */ ++#define REG_CTRL_PORT2_GMIIPO 0x5a /* 53012: GMII Port2 Override register */ ++#define REG_CTRL_PORT3_GMIIPO 0x5b /* 53012: GMII Port3 Override register */ ++#define REG_CTRL_PORT4_GMIIPO 0x5c /* 53012: GMII Port4 Override register */ ++#define REG_CTRL_PORT5_GMIIPO 0x5d /* 53012: GMII Port5 Override register */ ++#define REG_CTRL_PORT7_GMIIPO 0x5f /* 53012: GMII Port7 Override register */ ++ ++/* Command and status register of the SRAB */ ++#define CFG_F_sra_rst_MASK (1 << 2) ++#define CFG_F_sra_write_MASK (1 << 1) ++#define CFG_F_sra_gordyn_MASK (1 << 0) ++#define CFG_F_sra_page_R 24 ++#define CFG_F_sra_offset_R 16 ++ ++/* Switch interface controls */ ++#define CFG_F_sw_init_done_MASK (1 << 6) ++#define CFG_F_rcareq_MASK (1 << 3) ++#define CFG_F_rcagnt_MASK (1 << 4) ++ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++#define PAGE_P5_SGMII 0x16 ++#define PAGE_P4_SGMII 0x17 ++ ++/* SGMII REGISTERS */ ++#define REG_SGMII_BLK_ADDR 0x3e ++#define REG_IEEECTRL0 0x0000 ++#define REG_TX_ACTL0 0x8061 ++#define REG_TX_DRIVER 0x8065 ++#define REG_RX_CONTROL 0x80f1 ++#define REG_RX_ANLOGBIAS0L 0x80fc ++#define REG_SERDES_CTL1000X1 0x8300 ++#define REG_SERDES_CTL1000X2 0x8301 ++#define REG_SERDES_CTL1000X3 0x8302 ++#define REG_SERDES_STAT1000X1 0x8304 ++#define REG_COMBO_IEEE0_MIICTL 0xffe0 ++#define REG_COMBO_IEEE0_ANADV 0xffe4 ++#define REG_COMBO_IEEE0_ANLP 0xffe5 ++ ++#define PORTCFG_5 5 ++#define PORTCFG_4 4 ++#define PORTCFG "port%dcfg" ++#define PORTCFG_RGMII "rgmii" ++#define PORTCFG_SGMII "sgmii" ++#define PORTCFG_GPHY "gphy" ++ ++typedef volatile struct { ++ uint32 PAD[11]; ++ uint32 cmdstat; /* 0x2c, command and status register of the SRAB */ ++ uint32 wd_h; /* 0x30, high order word of write data to switch registe */ ++ uint32 wd_l; /* 0x34, low order word of write data to switch registe */ ++ uint32 rd_h; /* 0x38, high order word of read data from switch register */ ++ uint32 rd_l; /* 0x3c, low order word of read data from switch register */ ++ uint32 ctrls; /* 0x40, switch interface controls */ ++ uint32 intr; /* 0x44, the register captures interrupt pulses from the switch */ ++} srabregs_t; ++ ++/* Forward declaration */ ++typedef struct robo_info_s robo_info_t; ++ ++/* Device access/config oprands */ ++typedef struct { ++ /* low level routines */ ++ void (*enable_mgmtif)(robo_info_t *robo); /* enable mgmt i/f, optional */ ++ void (*disable_mgmtif)(robo_info_t *robo); /* disable mgmt i/f, optional */ ++ int (*write_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); ++ int (*read_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); ++ /* description */ ++ char *desc; ++} dev_ops_t; ++ ++ ++typedef uint16 (*miird_f)(void *h, int add, int off); ++typedef void (*miiwr_f)(void *h, int add, int off, uint16 val); ++ ++/* Private state per RoboSwitch */ ++struct robo_info_s { ++ si_t *sih; /* SiliconBackplane handle */ ++ char *vars; /* nvram variables handle */ ++ void *h; /* dev handle */ ++ uint16 devid; /* Device id for the switch */ ++ uint32 devid32; /* Device id for the switch (32bits) */ ++ uint32 corerev; /* Core rev of internal switch */ ++ ++ dev_ops_t *ops; /* device ops */ ++ uint8 page; /* current page */ ++ ++ /* SPI */ ++ uint32 ss, sck, mosi, miso; /* GPIO mapping */ ++ ++ /* MII */ ++ miird_f miird; ++ miiwr_f miiwr; ++ ++ /* SRAB */ ++ srabregs_t *srabregs; ++ ++ uint16 prev_status; /* link status of switch ports */ ++ uint32 pwrsave_mode_manual; /* bitmap of ports in manual power save */ ++ uint32 pwrsave_mode_auto; /* bitmap of ports in auto power save mode */ ++ uint8 pwrsave_phys; /* Phys that can be put into power save mode */ ++ uint8 pwrsave_mode_phys[MAX_NO_PHYS]; /* Power save mode on the switch */ ++}; ++ ++extern int srab_sgmii_rreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val); ++extern int srab_sgmii_wreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val); ++ ++/* Power Save mode related functions */ ++extern int32 robo_power_save_mode_get(robo_info_t *robo, int32 phy); ++extern int32 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy); ++extern void robo_power_save_mode_update(robo_info_t *robo); ++extern int robo_power_save_mode(robo_info_t *robo, int mode, int phy); ++extern int robo_power_save_toggle(robo_info_t *robo, int normal); ++ ++extern robo_info_t *bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr); ++extern void bcm_robo_detach(robo_info_t *robo); ++extern int bcm_robo_enable_device(robo_info_t *robo); ++extern int bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr); ++extern int bcm_robo_enable_switch(robo_info_t *robo); ++extern int robo_is_port5_cpu(void); ++extern int robo_is_port_cfg(int port, char *cfg); ++ ++extern void robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b); ++ ++extern void robo_watchdog(robo_info_t *robo); ++ ++void robo_reset_mib(robo_info_t *robo); ++void robo_dump_mib(robo_info_t *robo); ++void robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b); ++ ++#endif /* _bcm_robo_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsdh.h b/drivers/bcmdrivers/gmac/src/include/bcmsdh.h +new file mode 100755 +index 0000000..2767f73 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch new file mode 100644 index 00000000..21ea547c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch @@ -0,0 +1,232 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsdh.h +@@ -0,0 +1,226 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SDIO host client driver interface of Broadcom HNBU ++ * export functions to client drivers ++ * abstract OS and BUS specific details of SDIO ++ * ++ * $Id: bcmsdh.h 299859 2011-12-01 03:53:27Z $ ++ */ ++ ++/** ++ * @file bcmsdh.h ++ */ ++ ++#ifndef _bcmsdh_h_ ++#define _bcmsdh_h_ ++ ++#define BCMSDH_ERROR_VAL 0x0001 /* Error */ ++#define BCMSDH_INFO_VAL 0x0002 /* Info */ ++extern const uint bcmsdh_msglevel; ++ ++#ifdef BCMDBG ++#define BCMSDH_ERROR(x) do { if (bcmsdh_msglevel & BCMSDH_ERROR_VAL) printf x; } while (0) ++#define BCMSDH_INFO(x) do { if (bcmsdh_msglevel & BCMSDH_INFO_VAL) printf x; } while (0) ++#else /* BCMDBG */ ++#define BCMSDH_ERROR(x) ++#define BCMSDH_INFO(x) ++#endif /* BCMDBG */ ++ ++ ++/* forward declarations */ ++typedef struct bcmsdh_info bcmsdh_info_t; ++typedef void (*bcmsdh_cb_fn_t)(void *); ++ ++/* Attach and build an interface to the underlying SD host driver. ++ * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. ++ * - Returns the bcmsdh handle and virtual address base for register access. ++ * The returned handle should be used in all subsequent calls, but the bcmsh ++ * implementation may maintain a single "default" handle (e.g. the first or ++ * most recent one) to enable single-instance implementations to pass NULL. ++ */ ++extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq); ++ ++/* Detach - freeup resources allocated in attach */ ++extern int bcmsdh_detach(osl_t *osh, void *sdh); ++ ++/* Query if SD device interrupts are enabled */ ++extern bool bcmsdh_intr_query(void *sdh); ++ ++/* Enable/disable SD interrupt */ ++extern int bcmsdh_intr_enable(void *sdh); ++extern int bcmsdh_intr_disable(void *sdh); ++ ++/* Register/deregister device interrupt handler. */ ++extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++extern int bcmsdh_intr_dereg(void *sdh); ++ ++#if defined(DHD_DEBUG) || defined(BCMDBG) ++/* Query pending interrupt status from the host controller */ ++extern bool bcmsdh_intr_pending(void *sdh); ++#endif ++ ++/* Register a callback to be called if and when bcmsdh detects ++ * device removal. No-op in the case of non-removable/hardwired devices. ++ */ ++extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++ ++/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). ++ * fn: function number ++ * addr: unmodified SDIO-space address ++ * data: data byte to write ++ * err: pointer to error code (or NULL) ++ */ ++extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err); ++extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err); ++ ++/* Read/Write 4bytes from/to cfg space */ ++extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err); ++extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err); ++ ++/* Read CIS content for specified function. ++ * fn: function whose CIS is being requested (0 is common CIS) ++ * cis: pointer to memory location to place results ++ * length: number of bytes to read ++ * Internally, this routine uses the values from the cis base regs (0x9-0xB) ++ * to form an SDIO-space address to read the data from. ++ */ ++extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length); ++ ++/* Synchronous access to device (client) core registers via CMD53 to F1. ++ * addr: backplane address (i.e. >= regsva from attach) ++ * size: register width in bytes (2 or 4) ++ * data: data for register write ++ */ ++extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size); ++extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data); ++ ++/* set sb address window */ ++extern int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set); ++ ++/* Indicate if last reg read/write failed */ ++extern bool bcmsdh_regfail(void *sdh); ++ ++/* Buffer transfer to/from device (client) core via cmd53. ++ * fn: function number ++ * addr: backplane address (i.e. >= regsva from attach) ++ * flags: backplane width, address increment, sync/async ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * pkt: pointer to packet associated with buf (if any) ++ * complete: callback function for command completion (async only) ++ * handle: handle for completion callback (first arg in callback) ++ * Returns 0 or error code. ++ * NOTE: Async operation is not currently supported. ++ */ ++typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting); ++extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++ ++/* Flags bits */ ++#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */ ++#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */ ++#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */ ++#define SDIO_BYTE_MODE 0x8 /* Byte mode request(non-block mode) */ ++ ++/* Pending (non-error) return code */ ++#define BCME_PENDING 1 ++ ++/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). ++ * rw: read or write (0/1) ++ * addr: direct SDIO address ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * Returns 0 or error code. ++ */ ++extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes); ++ ++/* Issue an abort to the specified function */ ++extern int bcmsdh_abort(void *sdh, uint fn); ++ ++/* Start SDIO Host Controller communication */ ++extern int bcmsdh_start(void *sdh, int stage); ++ ++/* Stop SDIO Host Controller communication */ ++extern int bcmsdh_stop(void *sdh); ++ ++/* Wait system lock free */ ++extern int bcmsdh_waitlockfree(void *sdh); ++ ++/* Returns the "Device ID" of target device on the SDIO bus. */ ++extern int bcmsdh_query_device(void *sdh); ++ ++/* Returns the number of IO functions reported by the device */ ++extern uint bcmsdh_query_iofnum(void *sdh); ++ ++/* Miscellaneous knob tweaker. */ ++extern int bcmsdh_iovar_op(void *sdh, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Reset and reinitialize the device */ ++extern int bcmsdh_reset(bcmsdh_info_t *sdh); ++ ++/* helper functions */ ++ ++extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); ++ ++/* callback functions */ ++typedef struct { ++ /* attach to device */ ++ void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot, ++ uint16 func, uint bustype, void * regsva, osl_t * osh, ++ void * param); ++ /* detach from device */ ++ void (*detach)(void *ch); ++} bcmsdh_driver_t; ++ ++/* platform specific/high level functions */ ++extern int bcmsdh_register(bcmsdh_driver_t *driver); ++extern void bcmsdh_unregister(void); ++extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device); ++extern void bcmsdh_device_remove(void * sdh); ++ ++#if defined(OOB_INTR_ONLY) ++extern int bcmsdh_register_oob_intr(void * dhdp); ++extern void bcmsdh_unregister_oob_intr(void); ++extern void bcmsdh_oob_intr_set(bool enable); ++#endif /* defined(OOB_INTR_ONLY) */ ++ ++/* Function to pass device-status bits to DHD. */ ++extern uint32 bcmsdh_get_dstatus(void *sdh); ++ ++/* Function to return current window addr */ ++extern uint32 bcmsdh_cur_sbwad(void *sdh); ++ ++/* Function to pass chipid and rev to lower layers for controlling pr's */ ++extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev); ++ ++#ifdef BCMSPI ++extern void bcmsdh_dwordmode(void *sdh, bool set); ++#endif /* BCMSPI */ ++ ++extern int bcmsdh_sleep(void *sdh, bool enab); ++ ++/* GPIO support */ ++extern int bcmsdh_gpio_init(void *sd); ++extern bool bcmsdh_gpioin(void *sd, uint32 gpio); ++extern int bcmsdh_gpioouten(void *sd, uint32 gpio); ++extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab); ++ ++#endif /* _bcmsdh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h b/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h +new file mode 100755 +index 0000000..c1a320c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch new file mode 100644 index 00000000..05d7cfe0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch @@ -0,0 +1,274 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h +@@ -0,0 +1,268 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SDIO/PCMCIA ++ * Software-specific definitions shared between device and host side ++ * ++ * $Id: bcmsdpcm.h 314495 2012-02-12 07:56:39Z $ ++ */ ++ ++#ifndef _bcmsdpcm_h_ ++#define _bcmsdpcm_h_ ++ ++/* ++ * Software allocation of To SB Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */ ++#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */ ++#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */ ++#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOSBMAIL (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT) ++ ++/* tosbmailbox bits corresponding to intstatus bits */ ++#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */ ++#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */ ++#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */ ++#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */ ++#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */ ++ ++/* tosbmailboxdata */ ++#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ ++#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ ++ ++/* ++ * Software allocation of To Host Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */ ++#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */ ++#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */ ++#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOHOSTMAIL (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT) ++ ++/* tohostmailbox bits corresponding to intstatus bits */ ++#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */ ++#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */ ++#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */ ++#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */ ++#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */ ++ ++/* tohostmailboxdata */ ++#define HMB_DATA_NAKHANDLED 0x01 /* we're ready to retransmit NAK'd frame to host */ ++#define HMB_DATA_DEVREADY 0x02 /* we're ready to to talk to host after enable */ ++#define HMB_DATA_FC 0x04 /* per prio flowcontrol update flag to host */ ++#define HMB_DATA_FWREADY 0x08 /* firmware is ready for protocol activity */ ++#define HMB_DATA_FWHALT 0x10 /* firmware has halted operation */ ++ ++#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ ++#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ ++ ++#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */ ++#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */ ++ ++/* ++ * Software-defined protocol header ++ */ ++ ++/* Current protocol version */ ++#define SDPCM_PROT_VERSION 4 ++ ++/* SW frame header */ ++#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */ ++#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */ ++ ++#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */ ++#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */ ++#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */ ++ ++#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */ ++#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */ ++#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */ ++ ++/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */ ++#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */ ++#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */ ++#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */ ++#define SDPCM_NEXTLEN_OFFSET 2 ++ ++/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ ++#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ ++#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) ++#define SDPCM_DOFFSET_MASK 0xff000000 ++#define SDPCM_DOFFSET_SHIFT 24 ++ ++#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ ++#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff) ++#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ ++#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) ++#define SDPCM_VERSION_OFFSET 6 /* Version # */ ++#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff) ++#define SDPCM_UNUSED_OFFSET 7 /* Spare */ ++#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff) ++ ++#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ ++ ++/* logical channel numbers */ ++#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */ ++#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ ++#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ ++#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */ ++#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ ++#define SDPCM_MAX_CHANNEL 15 ++ ++#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */ ++ ++#define SDPCM_FLAG_RESVD0 0x01 ++#define SDPCM_FLAG_RESVD1 0x02 ++#define SDPCM_FLAG_GSPI_TXENAB 0x04 ++#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */ ++ ++/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */ ++#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT) ++ ++#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) ++ ++/* For TEST_CHANNEL packets, define another 4-byte header */ ++#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); ++ * Semantics of Ext byte depend on command. ++ * Len is current or requested frame length, not ++ * including test header; sent little-endian. ++ */ ++#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ ++#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count */ ++#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off */ ++ ++/* Handy macro for filling in datagen packets with a pattern */ ++#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) ++ ++/* ++ * Software counters (first part matches hardware counters) ++ */ ++ ++typedef volatile struct { ++ uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */ ++ uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */ ++ uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */ ++ uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */ ++ uint32 abort; /* AbortCount, SDIO: aborts */ ++ uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */ ++ uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */ ++ uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */ ++ uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */ ++ uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */ ++ uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */ ++ uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */ ++ uint32 rxdescuflo; /* receive descriptor underflows */ ++ uint32 rxfifooflo; /* receive fifo overflows */ ++ uint32 txfifouflo; /* transmit fifo underflows */ ++ uint32 runt; /* runt (too short) frames recv'd from bus */ ++ uint32 badlen; /* frame's rxh len does not match its hw tag len */ ++ uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */ ++ uint32 seqbreak; /* break in sequence # space from one rx frame to the next */ ++ uint32 rxfcrc; /* frame rx header indicates crc error */ ++ uint32 rxfwoos; /* frame rx header indicates write out of sync */ ++ uint32 rxfwft; /* frame rx header indicates write frame termination */ ++ uint32 rxfabort; /* frame rx header indicates frame aborted */ ++ uint32 woosint; /* write out of sync interrupt */ ++ uint32 roosint; /* read out of sync interrupt */ ++ uint32 rftermint; /* read frame terminate interrupt */ ++ uint32 wftermint; /* write frame terminate interrupt */ ++} sdpcmd_cnt_t; ++ ++/* ++ * Register Access Macros ++ */ ++ ++#define SDIODREV_IS(var, val) ((var) == (val)) ++#define SDIODREV_GE(var, val) ((var) >= (val)) ++#define SDIODREV_GT(var, val) ((var) > (val)) ++#define SDIODREV_LT(var, val) ((var) < (val)) ++#define SDIODREV_LE(var, val) ((var) <= (val)) ++ ++#define SDIODDMAREG32(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv)) ++ ++#define SDIODDMAREG64(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv)) ++ ++#define SDIODDMAREG(h, dir, chnl) \ ++ (SDIODREV_LT((h)->corerev, 1) ? \ ++ SDIODDMAREG32((h), (dir), (chnl)) : \ ++ SDIODDMAREG64((h), (dir), (chnl))) ++ ++#define PCMDDMAREG(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv)) ++ ++#define SDPCMDMAREG(h, dir, chnl, coreid) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODDMAREG(h, dir, chnl) : \ ++ PCMDDMAREG(h, dir, chnl)) ++ ++#define SDIODFIFOREG(h, corerev) \ ++ (SDIODREV_LT((corerev), 1) ? \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo))) ++ ++#define PCMDFIFOREG(h) \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo)) ++ ++#define SDPCMFIFOREG(h, coreid, corerev) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODFIFOREG(h, corerev) : \ ++ PCMDFIFOREG(h)) ++ ++/* ++ * Shared structure between dongle and the host. ++ * The structure contains pointers to trap or assert information. ++ */ ++#define SDPCM_SHARED_VERSION 0x0001 ++#define SDPCM_SHARED_VERSION_MASK 0x00FF ++#define SDPCM_SHARED_ASSERT_BUILT 0x0100 ++#define SDPCM_SHARED_ASSERT 0x0200 ++#define SDPCM_SHARED_TRAP 0x0400 ++#define SDPCM_SHARED_IN_BRPT 0x0800 ++#define SDPCM_SHARED_SET_BRPT 0x1000 ++#define SDPCM_SHARED_PENDING_BRPT 0x2000 ++ ++typedef struct { ++ uint32 flags; ++ uint32 trap_addr; ++ uint32 assert_exp_addr; ++ uint32 assert_file_addr; ++ uint32 assert_line; ++ uint32 console_addr; /* Address of hndrte_cons_t */ ++ uint32 msgtrace_addr; ++ uint32 fwid; ++} sdpcm_shared_t; ++ ++extern sdpcm_shared_t sdpcm_shared; ++ ++/* Function can be used to notify host of FW halt */ ++extern void sdpcmd_fwhalt(void); ++ ++#endif /* _bcmsdpcm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom.h +new file mode 100755 +index 0000000..0e6c210 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch new file mode 100644 index 00000000..24d77878 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch @@ -0,0 +1,61 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc useful routines to access NIC local SROM/OTP . ++ * ++ * $Id: bcmsrom.h 280889 2011-08-31 18:39:27Z $ ++ */ ++ ++#ifndef _bcmsrom_h_ ++#define _bcmsrom_h_ ++ ++#include ++ ++/* Prototypes */ ++extern int srom_var_init(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ char **vars, uint *count); ++extern void srom_var_deinit(si_t *sih); ++ ++extern int srom_read(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf, ++ bool check_crc); ++ ++extern int srom_write(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf); ++ ++extern int srom_otp_cisrwvar(si_t *sih, osl_t *osh, char *vars, int *count); ++#if defined(WLTEST) || defined(BCMDBG) ++extern int srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write); ++#endif ++ ++/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP ++ * and extract from it into name=value pairs ++ */ ++extern int srom_probe_boardtype(uint8 *pcis[], uint ciscnt); ++extern int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, ++ char **vars, uint *count); ++ ++#if defined(BCMUSBDEV) ++/* Return sprom size in 16-bit words */ ++extern uint srom_size(si_t *sih, osl_t *osh); ++#endif ++ ++#endif /* _bcmsrom_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h +new file mode 100755 +index 0000000..9f90ed8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch new file mode 100644 index 00000000..b6ad28b8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch @@ -0,0 +1,555 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h +@@ -0,0 +1,549 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SROM format definition. ++ * ++ * $Id: bcmsrom_fmt.h 322525 2012-03-21 01:28:39Z $ ++ */ ++ ++#ifndef _bcmsrom_fmt_h_ ++#define _bcmsrom_fmt_h_ ++ ++#define SROM_MAXREV 11 /* max revisiton supported by driver */ ++ ++/* Maximum srom: 6 Kilobits == 768 bytes */ ++#define SROM_MAX 768 ++#define SROM_MAXW 384 ++#define VARS_MAX 4096 ++ ++/* PCI fields */ ++#define PCI_F0DEVID 48 ++ ++ ++#define SROM_WORDS 64 ++ ++#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ ++ ++#define SROM_SSID 2 ++ ++#define SROM_WL1LHMAXP 29 ++ ++#define SROM_WL1LPAB0 30 ++#define SROM_WL1LPAB1 31 ++#define SROM_WL1LPAB2 32 ++ ++#define SROM_WL1HPAB0 33 ++#define SROM_WL1HPAB1 34 ++#define SROM_WL1HPAB2 35 ++ ++#define SROM_MACHI_IL0 36 ++#define SROM_MACMID_IL0 37 ++#define SROM_MACLO_IL0 38 ++#define SROM_MACHI_ET0 39 ++#define SROM_MACMID_ET0 40 ++#define SROM_MACLO_ET0 41 ++#define SROM_MACHI_ET1 42 ++#define SROM_MACMID_ET1 43 ++#define SROM_MACLO_ET1 44 ++#define SROM3_MACHI 37 ++#define SROM3_MACMID 38 ++#define SROM3_MACLO 39 ++ ++#define SROM_BXARSSI2G 40 ++#define SROM_BXARSSI5G 41 ++ ++#define SROM_TRI52G 42 ++#define SROM_TRI5GHL 43 ++ ++#define SROM_RXPO52G 45 ++ ++#define SROM2_ENETPHY 45 ++ ++#define SROM_AABREV 46 ++/* Fields in AABREV */ ++#define SROM_BR_MASK 0x00ff ++#define SROM_CC_MASK 0x0f00 ++#define SROM_CC_SHIFT 8 ++#define SROM_AA0_MASK 0x3000 ++#define SROM_AA0_SHIFT 12 ++#define SROM_AA1_MASK 0xc000 ++#define SROM_AA1_SHIFT 14 ++ ++#define SROM_WL0PAB0 47 ++#define SROM_WL0PAB1 48 ++#define SROM_WL0PAB2 49 ++ ++#define SROM_LEDBH10 50 ++#define SROM_LEDBH32 51 ++ ++#define SROM_WL10MAXP 52 ++ ++#define SROM_WL1PAB0 53 ++#define SROM_WL1PAB1 54 ++#define SROM_WL1PAB2 55 ++ ++#define SROM_ITT 56 ++ ++#define SROM_BFL 57 ++#define SROM_BFL2 28 ++#define SROM3_BFL2 61 ++ ++#define SROM_AG10 58 ++ ++#define SROM_CCODE 59 ++ ++#define SROM_OPO 60 ++ ++#define SROM3_LEDDC 62 ++ ++#define SROM_CRCREV 63 ++ ++/* SROM Rev 4: Reallocate the software part of the srom to accomodate ++ * MIMO features. It assumes up to two PCIE functions and 440 bytes ++ * of useable srom i.e. the useable storage in chips with OTP that ++ * implements hardware redundancy. ++ */ ++ ++#define SROM4_WORDS 220 ++ ++#define SROM4_SIGN 32 ++#define SROM4_SIGNATURE 0x5372 ++ ++#define SROM4_BREV 33 ++ ++#define SROM4_BFL0 34 ++#define SROM4_BFL1 35 ++#define SROM4_BFL2 36 ++#define SROM4_BFL3 37 ++#define SROM5_BFL0 37 ++#define SROM5_BFL1 38 ++#define SROM5_BFL2 39 ++#define SROM5_BFL3 40 ++ ++#define SROM4_MACHI 38 ++#define SROM4_MACMID 39 ++#define SROM4_MACLO 40 ++#define SROM5_MACHI 41 ++#define SROM5_MACMID 42 ++#define SROM5_MACLO 43 ++ ++#define SROM4_CCODE 41 ++#define SROM4_REGREV 42 ++#define SROM5_CCODE 34 ++#define SROM5_REGREV 35 ++ ++#define SROM4_LEDBH10 43 ++#define SROM4_LEDBH32 44 ++#define SROM5_LEDBH10 59 ++#define SROM5_LEDBH32 60 ++ ++#define SROM4_LEDDC 45 ++#define SROM5_LEDDC 45 ++ ++#define SROM4_AA 46 ++#define SROM4_AA2G_MASK 0x00ff ++#define SROM4_AA2G_SHIFT 0 ++#define SROM4_AA5G_MASK 0xff00 ++#define SROM4_AA5G_SHIFT 8 ++ ++#define SROM4_AG10 47 ++#define SROM4_AG32 48 ++ ++#define SROM4_TXPID2G 49 ++#define SROM4_TXPID5G 51 ++#define SROM4_TXPID5GL 53 ++#define SROM4_TXPID5GH 55 ++ ++#define SROM4_TXRXC 61 ++#define SROM4_TXCHAIN_MASK 0x000f ++#define SROM4_TXCHAIN_SHIFT 0 ++#define SROM4_RXCHAIN_MASK 0x00f0 ++#define SROM4_RXCHAIN_SHIFT 4 ++#define SROM4_SWITCH_MASK 0xff00 ++#define SROM4_SWITCH_SHIFT 8 ++ ++ ++/* Per-path fields */ ++#define MAX_PATH_SROM 4 ++#define SROM4_PATH0 64 ++#define SROM4_PATH1 87 ++#define SROM4_PATH2 110 ++#define SROM4_PATH3 133 ++ ++#define SROM4_2G_ITT_MAXP 0 ++#define SROM4_2G_PA 1 ++#define SROM4_5G_ITT_MAXP 5 ++#define SROM4_5GLH_MAXP 6 ++#define SROM4_5G_PA 7 ++#define SROM4_5GL_PA 11 ++#define SROM4_5GH_PA 15 ++ ++/* Fields in the ITT_MAXP and 5GLH_MAXP words */ ++#define B2G_MAXP_MASK 0xff ++#define B2G_ITT_SHIFT 8 ++#define B5G_MAXP_MASK 0xff ++#define B5G_ITT_SHIFT 8 ++#define B5GH_MAXP_MASK 0xff ++#define B5GL_MAXP_SHIFT 8 ++ ++/* All the miriad power offsets */ ++#define SROM4_2G_CCKPO 156 ++#define SROM4_2G_OFDMPO 157 ++#define SROM4_5G_OFDMPO 159 ++#define SROM4_5GL_OFDMPO 161 ++#define SROM4_5GH_OFDMPO 163 ++#define SROM4_2G_MCSPO 165 ++#define SROM4_5G_MCSPO 173 ++#define SROM4_5GL_MCSPO 181 ++#define SROM4_5GH_MCSPO 189 ++#define SROM4_CDDPO 197 ++#define SROM4_STBCPO 198 ++#define SROM4_BW40PO 199 ++#define SROM4_BWDUPPO 200 ++ ++#define SROM4_CRCREV 219 ++ ++ ++/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. ++ * This is acombined srom for both MIMO and SISO boards, usable in ++ * the .130 4Kilobit OTP with hardware redundancy. ++ */ ++ ++#define SROM8_SIGN 64 ++ ++#define SROM8_BREV 65 ++ ++#define SROM8_BFL0 66 ++#define SROM8_BFL1 67 ++#define SROM8_BFL2 68 ++#define SROM8_BFL3 69 ++ ++#define SROM8_MACHI 70 ++#define SROM8_MACMID 71 ++#define SROM8_MACLO 72 ++ ++#define SROM8_CCODE 73 ++#define SROM8_REGREV 74 ++ ++#define SROM8_LEDBH10 75 ++#define SROM8_LEDBH32 76 ++ ++#define SROM8_LEDDC 77 ++ ++#define SROM8_AA 78 ++ ++#define SROM8_AG10 79 ++#define SROM8_AG32 80 ++ ++#define SROM8_TXRXC 81 ++ ++#define SROM8_BXARSSI2G 82 ++#define SROM8_BXARSSI5G 83 ++#define SROM8_TRI52G 84 ++#define SROM8_TRI5GHL 85 ++#define SROM8_RXPO52G 86 ++ ++#define SROM8_FEM2G 87 ++#define SROM8_FEM5G 88 ++#define SROM8_FEM_ANTSWLUT_MASK 0xf800 ++#define SROM8_FEM_ANTSWLUT_SHIFT 11 ++#define SROM8_FEM_TR_ISO_MASK 0x0700 ++#define SROM8_FEM_TR_ISO_SHIFT 8 ++#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 ++#define SROM8_FEM_PDET_RANGE_SHIFT 3 ++#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 ++#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 ++#define SROM8_FEM_TSSIPOS_MASK 0x0001 ++#define SROM8_FEM_TSSIPOS_SHIFT 0 ++ ++#define SROM8_THERMAL 89 ++ ++/* Temp sense related entries */ ++#define SROM8_MPWR_RAWTS 90 ++#define SROM8_TS_SLP_OPT_CORRX 91 ++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */ ++#define SROM8_FOC_HWIQ_IQSWP 92 ++ ++#define SROM8_EXTLNAGAIN 93 ++ ++/* Temperature delta for PHY calibration */ ++#define SROM8_PHYCAL_TEMPDELTA 94 ++ ++/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */ ++#define SROM8_MPWR_1_AND_2 95 ++ ++ ++/* Per-path offsets & fields */ ++#define SROM8_PATH0 96 ++#define SROM8_PATH1 112 ++#define SROM8_PATH2 128 ++#define SROM8_PATH3 144 ++ ++#define SROM8_2G_ITT_MAXP 0 ++#define SROM8_2G_PA 1 ++#define SROM8_5G_ITT_MAXP 4 ++#define SROM8_5GLH_MAXP 5 ++#define SROM8_5G_PA 6 ++#define SROM8_5GL_PA 9 ++#define SROM8_5GH_PA 12 ++ ++/* All the miriad power offsets */ ++#define SROM8_2G_CCKPO 160 ++ ++#define SROM8_2G_OFDMPO 161 ++#define SROM8_5G_OFDMPO 163 ++#define SROM8_5GL_OFDMPO 165 ++#define SROM8_5GH_OFDMPO 167 ++ ++#define SROM8_2G_MCSPO 169 ++#define SROM8_5G_MCSPO 177 ++#define SROM8_5GL_MCSPO 185 ++#define SROM8_5GH_MCSPO 193 ++ ++#define SROM8_CDDPO 201 ++#define SROM8_STBCPO 202 ++#define SROM8_BW40PO 203 ++#define SROM8_BWDUPPO 204 ++ ++/* SISO PA parameters are in the path0 spaces */ ++#define SROM8_SISO 96 ++ ++/* Legacy names for SISO PA paramters */ ++#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) ++#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) ++#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) ++#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) ++#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) ++#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) ++#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) ++#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) ++#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) ++#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) ++#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) ++#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) ++#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) ++#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) ++#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) ++ ++#define SROM8_CRCREV 219 ++ ++/* SROM REV 9 */ ++#define SROM9_2GPO_CCKBW20 160 ++#define SROM9_2GPO_CCKBW20UL 161 ++#define SROM9_2GPO_LOFDMBW20 162 ++#define SROM9_2GPO_LOFDMBW20UL 164 ++ ++#define SROM9_5GLPO_LOFDMBW20 166 ++#define SROM9_5GLPO_LOFDMBW20UL 168 ++#define SROM9_5GMPO_LOFDMBW20 170 ++#define SROM9_5GMPO_LOFDMBW20UL 172 ++#define SROM9_5GHPO_LOFDMBW20 174 ++#define SROM9_5GHPO_LOFDMBW20UL 176 ++ ++#define SROM9_2GPO_MCSBW20 178 ++#define SROM9_2GPO_MCSBW20UL 180 ++#define SROM9_2GPO_MCSBW40 182 ++ ++#define SROM9_5GLPO_MCSBW20 184 ++#define SROM9_5GLPO_MCSBW20UL 186 ++#define SROM9_5GLPO_MCSBW40 188 ++#define SROM9_5GMPO_MCSBW20 190 ++#define SROM9_5GMPO_MCSBW20UL 192 ++#define SROM9_5GMPO_MCSBW40 194 ++#define SROM9_5GHPO_MCSBW20 196 ++#define SROM9_5GHPO_MCSBW20UL 198 ++#define SROM9_5GHPO_MCSBW40 200 ++ ++#define SROM9_PO_MCS32 202 ++#define SROM9_PO_LOFDM40DUP 203 ++#define SROM8_RXGAINERR_2G 205 ++#define SROM8_RXGAINERR_5GL 206 ++#define SROM8_RXGAINERR_5GM 207 ++#define SROM8_RXGAINERR_5GH 208 ++#define SROM8_RXGAINERR_5GU 209 ++#define SROM8_SUBBAND_PPR 210 ++#define SROM8_PCIEINGRESS_WAR 211 ++#define SROM9_SAR 212 ++ ++#define SROM8_NOISELVL_2G 213 ++#define SROM8_NOISELVL_5GL 214 ++#define SROM8_NOISELVL_5GM 215 ++#define SROM8_NOISELVL_5GH 216 ++#define SROM8_NOISELVL_5GU 217 ++ ++#define SROM9_REV_CRC 219 ++ ++#define SROM10_CCKPWROFFSET 218 ++#define SROM10_SIGN 219 ++#define SROM10_SWCTRLMAP_2G 220 ++#define SROM10_CRCREV 229 ++ ++#define SROM10_WORDS 230 ++#define SROM10_SIGNATURE SROM4_SIGNATURE ++ ++ ++/* SROM REV 11 */ ++#define SROM11_BREV 65 ++ ++#define SROM11_BFL0 66 ++#define SROM11_BFL1 67 ++#define SROM11_BFL2 68 ++#define SROM11_BFL3 69 ++#define SROM11_BFL4 70 ++#define SROM11_BFL5 71 ++ ++#define SROM11_MACHI 72 ++#define SROM11_MACMID 73 ++#define SROM11_MACLO 74 ++ ++#define SROM11_CCODE 75 ++#define SROM11_REGREV 76 ++ ++#define SROM11_LEDBH10 77 ++#define SROM11_LEDBH32 78 ++ ++#define SROM11_LEDDC 79 ++ ++#define SROM11_AA 80 ++ ++#define SROM11_AGBG10 81 ++#define SROM11_AGBG2A0 82 ++#define SROM11_AGA21 83 ++ ++#define SROM11_TXRXC 84 ++ ++#define SROM11_FEM_CFG1 85 ++#define SROM11_FEM_CFG2 86 ++ ++#define SROM11_THERMAL 87 ++#define SROM11_MPWR_RAWTS 88 ++#define SROM11_TS_SLP_OPT_CORRX 89 ++#define SROM11_PHYCAL_TEMPDELTA 92 ++#define SROM11_MPWR_1_AND_2 93 ++ ++#define SROM11_PDOFF_40M_A0 101 ++#define SROM11_PDOFF_40M_A1 102 ++#define SROM11_PDOFF_40M_A2 103 ++#define SROM11_PDOFF_80M_A0 104 ++#define SROM11_PDOFF_80M_A1 105 ++#define SROM11_PDOFF_80M_A2 106 ++ ++#define SROM11_SUBBAND5GVER 107 ++ ++/* Per-path fields and offset */ ++#define MAX_PATH_SROM_11 3 ++#define SROM11_PATH0 108 ++#define SROM11_PATH1 128 ++#define SROM11_PATH2 148 ++ ++#define SROM11_2G_MAXP 0 ++#define SROM11_2G_PA 1 ++#define SROM11_RXGAINS1 4 ++#define SROM11_RXGAINS 5 ++#define SROM11_5GB1B0_MAXP 6 ++#define SROM11_5GB3B2_MAXP 7 ++#define SROM11_5GB0_PA 8 ++#define SROM11_5GB1_PA 11 ++#define SROM11_5GB2_PA 14 ++#define SROM11_5GB3_PA 17 ++ ++/* Power per rate */ ++#define SROM11_CCKBW202GPO 168 ++#define SROM11_CCKBW20UL2GPO 169 ++#define SROM11_MCSBW202GPO 170 ++#define SROM11_MCSBW202GPO_1 171 ++#define SROM11_MCSBW402GPO 172 ++#define SROM11_MCSBW402GPO_1 173 ++#define SROM11_DOT11AGOFDMHRBW202GPO 174 ++#define SROM11_OFDMLRBW202GPO 175 ++ ++#define SROM11_MCSBW205GLPO 176 ++#define SROM11_MCSBW205GLPO_1 177 ++#define SROM11_MCSBW405GLPO 178 ++#define SROM11_MCSBW405GLPO_1 179 ++#define SROM11_MCSBW805GLPO 180 ++#define SROM11_MCSBW805GLPO_1 181 ++#define SROM11_MCSBW1605GLPO 182 ++#define SROM11_MCSBW1605GLPO_1 183 ++#define SROM11_MCSBW205GMPO 184 ++#define SROM11_MCSBW205GMPO_1 185 ++#define SROM11_MCSBW405GMPO 186 ++#define SROM11_MCSBW405GMPO_1 187 ++#define SROM11_MCSBW805GMPO 188 ++#define SROM11_MCSBW805GMPO_1 189 ++#define SROM11_MCSBW1605GMPO 190 ++#define SROM11_MCSBW1605GMPO_1 191 ++#define SROM11_MCSBW205GHPO 192 ++#define SROM11_MCSBW205GHPO_1 193 ++#define SROM11_MCSBW405GHPO 194 ++#define SROM11_MCSBW405GHPO_1 195 ++#define SROM11_MCSBW805GHPO 196 ++#define SROM11_MCSBW805GHPO_1 197 ++#define SROM11_MCSBW1605GHPO 198 ++#define SROM11_MCSBW1605GHPO_1 199 ++ ++#define SROM11_MCSLR5GLPO 200 ++#define SROM11_MCSLR5GMPO 201 ++#define SROM11_MCSLR5GHPO 202 ++ ++#define SROM11_SB20IN40HRPO 203 ++#define SROM11_SB20IN80AND160HR5GLPO 204 ++#define SROM11_SB40AND80HR5GLPO 205 ++#define SROM11_SB20IN80AND160HR5GMPO 206 ++#define SROM11_SB40AND80HR5GMPO 207 ++#define SROM11_SB20IN80AND160HR5GHPO 208 ++#define SROM11_SB40AND80HR5GHPO 209 ++#define SROM11_SB20IN40LRPO 210 ++#define SROM11_SB20IN80AND160LR5GLPO 211 ++#define SROM11_SB40AND80LR5GLPO 212 ++#define SROM11_SB20IN80AND160LR5GMPO 213 ++#define SROM11_SB40AND80LR5GMPO 214 ++#define SROM11_SB20IN80AND160LR5GHPO 215 ++#define SROM11_SB40AND80LR5GHPO 216 ++ ++#define SROM11_DOT11AGDUPHRPO 217 ++#define SROM11_DOT11AGDUPLRPO 218 ++ ++/* MISC */ ++#define SROM11_PCIEINGRESS_WAR 220 ++#define SROM11_SAR 221 ++ ++#define SROM11_NOISELVL_2G 222 ++#define SROM11_NOISELVL_5GL 223 ++#define SROM11_NOISELVL_5GM 224 ++#define SROM11_NOISELVL_5GH 225 ++#define SROM11_NOISELVL_5GU 226 ++ ++#define SROM11_RXGAINERR_2G 227 ++#define SROM11_RXGAINERR_5GL 228 ++#define SROM11_RXGAINERR_5GM 229 ++#define SROM11_RXGAINERR_5GH 230 ++#define SROM11_RXGAINERR_5GU 231 ++ ++#define SROM11_SIGN 64 ++#define SROM11_CRCREV 233 ++ ++#define SROM11_WORDS 234 ++#define SROM11_SIGNATURE 0x0634 ++ ++typedef struct { ++ uint8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */ ++ uint8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ ++ uint8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */ ++ uint8 triso; /* TR switch isolation */ ++ uint8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */ ++} srom_fem_t; ++ ++#endif /* _bcmsrom_fmt_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h +new file mode 100755 +index 0000000..2190d7e diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch new file mode 100644 index 00000000..2d6c06d6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch @@ -0,0 +1,884 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h +@@ -0,0 +1,878 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Table that encodes the srom formats for PCI/PCIe NICs. ++ * ++ * $Id: bcmsrom_tbl.h 324896 2012-03-30 19:35:36Z $ ++ */ ++ ++#ifndef _bcmsrom_tbl_h_ ++#define _bcmsrom_tbl_h_ ++ ++#include "sbpcmcia.h" ++#include "wlioctl.h" ++ ++typedef struct { ++ const char *name; ++ uint32 revmask; ++ uint32 flags; ++ uint16 off; ++ uint16 mask; ++} sromvar_t; ++ ++#define SRFL_MORE 1 /* value continues as described by the next entry */ ++#define SRFL_NOFFS 2 /* value bits can't be all one's */ ++#define SRFL_PRHEX 4 /* value is in hexdecimal format */ ++#define SRFL_PRSIGN 8 /* value is in signed decimal format */ ++#define SRFL_CCODE 0x10 /* value is in country code format */ ++#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ ++#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ ++#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */ ++#define SRFL_ARRAY 0x100 /* value is in an array. All elements EXCEPT FOR THE LAST ++ * ONE in the array should have this flag set. ++ */ ++ ++ ++/* Assumptions: ++ * - Ethernet address spans across 3 consective words ++ * ++ * Table rules: ++ * - Add multiple entries next to each other if a value spans across multiple words ++ * (even multiple fields in the same word) with each entry except the last having ++ * it's SRFL_MORE bit set. ++ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE ++ * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. ++ * - The last entry's name field must be NULL to indicate the end of the table. Other ++ * entries must have non-NULL name. ++ */ ++ ++static const sromvar_t pci_sromvars[] = { ++ {"devid", 0xffffff00, SRFL_PRHEX|SRFL_NOVAR, PCI_F0DEVID, 0xffff}, ++ {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, ++ {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, ++ {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, ++ {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, ++ {"boardflags", 0x00000004, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff}, ++ {"", 0, 0, SROM_BFL2, 0xffff}, ++ {"boardflags", 0x00000008, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff}, ++ {"", 0, 0, SROM3_BFL2, 0xffff}, ++ {"boardflags", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL0, 0xffff}, ++ {"", 0, 0, SROM4_BFL1, 0xffff}, ++ {"boardflags", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL0, 0xffff}, ++ {"", 0, 0, SROM5_BFL1, 0xffff}, ++ {"boardflags", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL0, 0xffff}, ++ {"", 0, 0, SROM8_BFL1, 0xffff}, ++ {"boardflags2", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL2, 0xffff}, ++ {"", 0, 0, SROM4_BFL3, 0xffff}, ++ {"boardflags2", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL2, 0xffff}, ++ {"", 0, 0, SROM5_BFL3, 0xffff}, ++ {"boardflags2", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL2, 0xffff}, ++ {"", 0, 0, SROM8_BFL3, 0xffff}, ++ {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, ++ ++ {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, ++ {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, ++ {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, ++ {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, ++ {"boardnum", 0x00000700, 0, SROM8_MACLO, 0xffff}, ++ {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, ++ {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, ++ {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff}, ++ {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff}, ++ {"regrev", 0x00000700, 0, SROM8_REGREV, 0x00ff}, ++ {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, ++ {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, ++ {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, ++ {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, ++ {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, ++ {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, ++ {"ledbh0", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, ++ {"ledbh2", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, ++ {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, ++ {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, ++ {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, ++ {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff}, ++ {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, ++ {"pa0b0", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, ++ {"pa0b1", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, ++ {"pa0b2", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, ++ {"pa0itssit", 0x00000700, 0, SROM8_W0_ITTMAXP, 0xff00}, ++ {"pa0maxpwr", 0x00000700, 0, SROM8_W0_ITTMAXP, 0x00ff}, ++ {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff}, ++ {"opo", 0x00000700, 0, SROM8_2G_OFDMPO, 0x00ff}, ++ {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, ++ {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff}, ++ {"aa2g", 0x00000700, 0, SROM8_AA, 0x00ff}, ++ {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, ++ {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, ++ {"aa5g", 0x00000700, 0, SROM8_AA, 0xff00}, ++ {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff}, ++ {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, ++ {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff}, ++ {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, ++ {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff}, ++ {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, ++ {"ag0", 0x00000700, 0, SROM8_AG10, 0x00ff}, ++ {"ag1", 0x00000700, 0, SROM8_AG10, 0xff00}, ++ {"ag2", 0x00000700, 0, SROM8_AG32, 0x00ff}, ++ {"ag3", 0x00000700, 0, SROM8_AG32, 0xff00}, ++ {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, ++ {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, ++ {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, ++ {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, ++ {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, ++ {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, ++ {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, ++ {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, ++ {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, ++ {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, ++ {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, ++ {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, ++ {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, ++ {"pa1b0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, ++ {"pa1b1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, ++ {"pa1b2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, ++ {"pa1lob0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, ++ {"pa1lob1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, ++ {"pa1lob2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, ++ {"pa1hib0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, ++ {"pa1hib1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, ++ {"pa1hib2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, ++ {"pa1itssit", 0x00000700, 0, SROM8_W1_ITTMAXP, 0xff00}, ++ {"pa1maxpwr", 0x00000700, 0, SROM8_W1_ITTMAXP, 0x00ff}, ++ {"pa1lomaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0xff00}, ++ {"pa1himaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, ++ {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, ++ {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, ++ {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, ++ {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, ++ {"bxa2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x1800}, ++ {"rssisav2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x0700}, ++ {"rssismc2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x00f0}, ++ {"rssismf2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x000f}, ++ {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, ++ {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, ++ {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, ++ {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, ++ {"bxa5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x1800}, ++ {"rssisav5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x0700}, ++ {"rssismc5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x00f0}, ++ {"rssismf5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x000f}, ++ {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff}, ++ {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, ++ {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, ++ {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, ++ {"tri2g", 0x00000700, 0, SROM8_TRI52G, 0x00ff}, ++ {"tri5g", 0x00000700, 0, SROM8_TRI52G, 0xff00}, ++ {"tri5gl", 0x00000700, 0, SROM8_TRI5GHL, 0x00ff}, ++ {"tri5gh", 0x00000700, 0, SROM8_TRI5GHL, 0xff00}, ++ {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, ++ {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, ++ {"rxpo2g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, ++ {"rxpo5g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, ++ {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, ++ {"txchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, ++ {"tssipos2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK}, ++ {"extpagain2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK}, ++ {"pdetrange2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK}, ++ {"triso2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, ++ {"antswctl2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK}, ++ {"tssipos5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK}, ++ {"extpagain5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK}, ++ {"pdetrange5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK}, ++ {"triso5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, ++ {"antswctl5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK}, ++ {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, ++ {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, ++ {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff}, ++ {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, ++ {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, ++ {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, ++ {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff}, ++ {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, ++ {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, ++ {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, ++ {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff}, ++ {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, ++ {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, ++ {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, ++ {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff}, ++ {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, ++ ++ {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, ++ {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, ++ {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, ++ {"ccode", 0x00000700, SRFL_CCODE, SROM8_CCODE, 0xffff}, ++ {"macaddr", 0x00000700, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, ++ {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, ++ {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, ++ {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, ++ {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, ++ {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, ++ {"leddc", 0x00000700, SRFL_NOFFS|SRFL_LEDDC, SROM8_LEDDC, 0xffff}, ++ {"leddc", 0x000000e0, SRFL_NOFFS|SRFL_LEDDC, SROM5_LEDDC, 0xffff}, ++ {"leddc", 0x00000010, SRFL_NOFFS|SRFL_LEDDC, SROM4_LEDDC, 0xffff}, ++ {"leddc", 0x00000008, SRFL_NOFFS|SRFL_LEDDC, SROM3_LEDDC, 0xffff}, ++ ++ {"tempthresh", 0x00000700, 0, SROM8_THERMAL, 0xff00}, ++ {"tempoffset", 0x00000700, 0, SROM8_THERMAL, 0x00ff}, ++ {"rawtempsense", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff}, ++ {"measpower", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00}, ++ {"tempsense_slope", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff}, ++ {"tempcorrx", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00}, ++ {"tempsense_option", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300}, ++ {"freqoffset_corr", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f}, ++ {"iqcal_swp_dis", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010}, ++ {"hw_iqcal_en", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020}, ++ {"elna2g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0x00ff}, ++ {"elna5g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0xff00}, ++ {"phycal_tempdelta", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff}, ++ {"temps_period", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x0f00}, ++ {"temps_hysteresis", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0xf000}, ++ {"measpower1", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x007f}, ++ {"measpower2", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x3f80}, ++ ++ {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, ++ {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, ++ {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, ++ {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, ++ {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, ++ {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, ++ {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, ++ {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, ++ {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, ++ {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, ++ {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, ++ {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, ++ {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, ++ {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, ++ {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, ++ {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, ++ {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, ++ {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, ++ {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, ++ {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, ++ {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, ++ {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, ++ {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, ++ {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, ++ {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, ++ {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, ++ {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, ++ {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, ++ {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, ++ {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, ++ {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, ++ {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, ++ {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, ++ {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, ++ {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, ++ {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, ++ {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, ++ {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, ++ {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, ++ {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, ++ {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, ++ {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, ++ {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, ++ {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, ++ {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, ++ {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, ++ {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, ++ {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, ++ {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, ++ {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, ++ {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, ++ {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, ++ {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, ++ {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, ++ {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, ++ {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, ++ {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, ++ {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, ++ {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, ++ {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, ++ {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, ++ {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, ++ {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, ++ {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, ++ {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, ++ {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, ++ {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, ++ {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, ++ {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, ++ {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, ++ {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, ++ {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, ++ {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, ++ {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, ++ {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, ++ {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, ++ {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, ++ {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, ++ {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff}, ++ {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff}, ++ {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff}, ++ {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, ++ ++ /* power per rate from sromrev 9 */ ++ {"cckbw202gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20, 0xffff}, ++ {"cckbw20ul2gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, ++ {"legofdmbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, ++ {"mcsbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw402gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, ++ {"mcs32po", 0x00000600, 0, SROM9_PO_MCS32, 0xffff}, ++ {"legofdm40duppo", 0x00000600, 0, SROM9_PO_LOFDM40DUP, 0xffff}, ++ {"pcieingress_war", 0x00000700, 0, SROM8_PCIEINGRESS_WAR, 0xf}, ++ {"rxgainerr2ga0", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x003f}, ++ {"rxgainerr2ga1", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x07c0}, ++ {"rxgainerr2ga2", 0x00000700, 0, SROM8_RXGAINERR_2G, 0xf800}, ++ {"rxgainerr5gla0", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x003f}, ++ {"rxgainerr5gla1", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x07c0}, ++ {"rxgainerr5gla2", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0xf800}, ++ {"rxgainerr5gma0", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x003f}, ++ {"rxgainerr5gma1", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x07c0}, ++ {"rxgainerr5gma2", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0xf800}, ++ {"rxgainerr5gha0", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x003f}, ++ {"rxgainerr5gha1", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x07c0}, ++ {"rxgainerr5gha2", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0xf800}, ++ {"rxgainerr5gua0", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x003f}, ++ {"rxgainerr5gua1", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x07c0}, ++ {"rxgainerr5gua2", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0xf800}, ++ {"sar2g", 0x00000600, 0, SROM9_SAR, 0x00ff}, ++ {"sar5g", 0x00000600, 0, SROM9_SAR, 0xff00}, ++ {"noiselvl2ga0", 0x00000700, 0, SROM8_NOISELVL_2G, 0x001f}, ++ {"noiselvl2ga1", 0x00000700, 0, SROM8_NOISELVL_2G, 0x03e0}, ++ {"noiselvl2ga2", 0x00000700, 0, SROM8_NOISELVL_2G, 0x7c00}, ++ {"noiselvl5gla0", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x001f}, ++ {"noiselvl5gla1", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x03e0}, ++ {"noiselvl5gla2", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x7c00}, ++ {"noiselvl5gma0", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x001f}, ++ {"noiselvl5gma1", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x03e0}, ++ {"noiselvl5gma2", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x7c00}, ++ {"noiselvl5gha0", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x001f}, ++ {"noiselvl5gha1", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x03e0}, ++ {"noiselvl5gha2", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x7c00}, ++ {"noiselvl5gua0", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x001f}, ++ {"noiselvl5gua1", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x03e0}, ++ {"noiselvl5gua2", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x7c00}, ++ {"subband5gver", 0x00000700, 0, SROM8_SUBBAND_PPR, 0x7}, ++ ++ {"cckPwrOffset", 0x00000400, 0, SROM10_CCKPWROFFSET, 0xffff}, ++ /* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */ ++ {"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 1, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 3, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 5, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 7, 0xffff}, ++ {"", 0x00000400, SRFL_PRHEX, SROM10_SWCTRLMAP_2G + 8, 0xffff}, ++ ++ /* sromrev 11 */ ++ {"boardflags3", 0xfffff800, SRFL_PRHEX|SRFL_MORE, SROM11_BFL3, 0xffff}, ++ {"", 0, 0, SROM11_BFL3, 0xffff}, ++ {"boardnum", 0xfffff800, 0, SROM11_MACLO, 0xffff}, ++ {"macaddr", 0xfffff800, SRFL_ETHADDR, SROM11_MACHI, 0xffff}, ++ {"ccode", 0xfffff800, SRFL_CCODE, SROM11_CCODE, 0xffff}, ++ {"regrev", 0xfffff800, 0, SROM11_REGREV, 0x00ff}, ++ {"ledbh0", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0x00ff}, ++ {"ledbh1", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0xff00}, ++ {"ledbh2", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0x00ff}, ++ {"ledbh3", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0xff00}, ++ {"leddc", 0xfffff800, SRFL_NOFFS|SRFL_LEDDC, SROM11_LEDDC, 0xffff}, ++ {"aa2g", 0xfffff800, 0, SROM11_AA, 0x00ff}, ++ {"aa5g", 0xfffff800, 0, SROM11_AA, 0xff00}, ++ {"agbg0", 0xfffff800, 0, SROM11_AGBG10, 0x00ff}, ++ {"agbg1", 0xfffff800, 0, SROM11_AGBG10, 0xff00}, ++ {"agbg2", 0xfffff800, 0, SROM11_AGBG2A0, 0x00ff}, ++ {"aga0", 0xfffff800, 0, SROM11_AGBG2A0, 0xff00}, ++ {"aga1", 0xfffff800, 0, SROM11_AGA21, 0x00ff}, ++ {"aga2", 0xfffff800, 0, SROM11_AGA21, 0xff00}, ++ {"txchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_SWITCH_MASK}, ++ ++ {"tssiposslope2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0001}, ++ {"epagain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x000e}, ++ {"pdgain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x01f0}, ++ {"tworangetssi2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0200}, ++ {"papdcap2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0400}, ++ {"femctrl", 0xfffff800, 0, SROM11_FEM_CFG1, 0xf800}, ++ ++ {"tssiposslope5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0001}, ++ {"epagain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x000e}, ++ {"pdgain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x01f0}, ++ {"tworangetssi5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0200}, ++ {"papdcap5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0400}, ++ {"gainctrlsph", 0xfffff800, 0, SROM11_FEM_CFG2, 0xf800}, ++ ++ {"tempthresh", 0xfffff800, 0, SROM11_THERMAL, 0xff00}, ++ {"tempoffset", 0xfffff800, 0, SROM11_THERMAL, 0x00ff}, ++ {"rawtempsense", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0x01ff}, ++ {"measpower", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0xfe00}, ++ {"tempsense_slope", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x00ff}, ++ {"tempcorrx", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0xfc00}, ++ {"tempsense_option", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x0300}, ++ {"phycal_tempdelta", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x00ff}, ++ {"temps_period", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x0f00}, ++ {"temps_hysteresis", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0xf000}, ++ {"measpower1", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x007f}, ++ {"measpower2", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x3f80}, ++ {"pdoffset40ma0", 0xfffff800, 0, SROM11_PDOFF_40M_A0, 0xffff}, ++ {"pdoffset40ma1", 0xfffff800, 0, SROM11_PDOFF_40M_A1, 0xffff}, ++ {"pdoffset40ma2", 0xfffff800, 0, SROM11_PDOFF_40M_A2, 0xffff}, ++ {"pdoffset80ma0", 0xfffff800, 0, SROM11_PDOFF_80M_A0, 0xffff}, ++ {"pdoffset80ma1", 0xfffff800, 0, SROM11_PDOFF_80M_A1, 0xffff}, ++ {"pdoffset80ma2", 0xfffff800, 0, SROM11_PDOFF_80M_A2, 0xffff}, ++ ++ {"subband5gver", 0xfffff800, SRFL_PRHEX, SROM11_SUBBAND5GVER, 0xffff}, ++ ++ /* power per rate */ ++ {"cckbw202gpo", 0xfffff800, 0, SROM11_CCKBW202GPO, 0xffff}, ++ {"cckbw20ul2gpo", 0xfffff800, 0, SROM11_CCKBW20UL2GPO, 0xffff}, ++ {"mcsbw202gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW202GPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW202GPO_1, 0xffff}, ++ {"mcsbw402gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW402GPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW402GPO_1, 0xffff}, ++ {"dot11agofdmhrbw202gpo", 0xfffff800, 0, SROM11_DOT11AGOFDMHRBW202GPO, 0xffff}, ++ {"ofdmlrbw202gpo", 0xfffff800, 0, SROM11_OFDMLRBW202GPO, 0xffff}, ++ {"mcsbw205glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GLPO_1, 0xffff}, ++ {"mcsbw405glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GLPO_1, 0xffff}, ++ {"mcsbw805glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GLPO_1, 0xffff}, ++ {"mcsbw1605glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GLPO_1, 0xffff}, ++ {"mcsbw205gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GMPO_1, 0xffff}, ++ {"mcsbw405gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GMPO_1, 0xffff}, ++ {"mcsbw805gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GMPO_1, 0xffff}, ++ {"mcsbw1605gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GMPO_1, 0xffff}, ++ {"mcsbw205ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GHPO_1, 0xffff}, ++ {"mcsbw405ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GHPO_1, 0xffff}, ++ {"mcsbw805ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GHPO_1, 0xffff}, ++ {"mcsbw1605ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GHPO_1, 0xffff}, ++ {"mcslr5glpo", 0xfffff800, 0, SROM11_MCSLR5GLPO, 0xffff}, ++ {"mcslr5gmpo", 0xfffff800, 0, SROM11_MCSLR5GMPO, 0xffff}, ++ {"mcslr5ghpo", 0xfffff800, 0, SROM11_MCSLR5GHPO, 0xffff}, ++ {"sb20in40hrrpo", 0xfffff800, 0, SROM11_SB20IN40HRPO, 0xffff}, ++ {"sb20in80and160hr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GLPO, 0xffff}, ++ {"sb40and80hr5glpo", 0xfffff800, 0, SROM11_SB40AND80HR5GLPO, 0xffff}, ++ {"sb20in80and160hr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GMPO, 0xffff}, ++ {"sb40and80hr5gmpo", 0xfffff800, 0, SROM11_SB40AND80HR5GMPO, 0xffff}, ++ {"sb20in80and160hr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GHPO, 0xffff}, ++ {"sb40and80hr5ghpo", 0xfffff800, 0, SROM11_SB40AND80HR5GHPO, 0xffff}, ++ {"sb20in40lrpo", 0xfffff800, 0, SROM11_SB20IN40LRPO, 0xffff}, ++ {"sb20in80and160lr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GLPO, 0xffff}, ++ {"sb40and80lr5glpo", 0xfffff800, 0, SROM11_SB40AND80LR5GLPO, 0xffff}, ++ {"sb20in80and160lr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GMPO, 0xffff}, ++ {"sb40and80lr5gmpo", 0xfffff800, 0, SROM11_SB40AND80LR5GMPO, 0xffff}, ++ {"sb20in80and160lr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GHPO, 0xffff}, ++ {"sb40and80lr5ghpo", 0xfffff800, 0, SROM11_SB40AND80LR5GHPO, 0xffff}, ++ {"dot11agduphrpo", 0xfffff800, 0, SROM11_DOT11AGDUPHRPO, 0xffff}, ++ {"dot11agduplrpo", 0xfffff800, 0, SROM11_DOT11AGDUPLRPO, 0xffff}, ++ ++ /* Misc */ ++ {"pcieingress_war", 0xfffff800, 0, SROM11_PCIEINGRESS_WAR, 0xf}, ++ {"sar2g", 0xfffff800, 0, SROM11_SAR, 0x00ff}, ++ {"sar5g", 0xfffff800, 0, SROM11_SAR, 0xff00}, ++ {"noiselvl2ga0", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x001f}, ++ {"noiselvl2ga1", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x03e0}, ++ {"noiselvl2ga2", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x7c00}, ++ {"noiselvl5gla0", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x001f}, ++ {"noiselvl5gla1", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x03e0}, ++ {"noiselvl5gla2", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x7c00}, ++ {"noiselvl5gma0", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x001f}, ++ {"noiselvl5gma1", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x03e0}, ++ {"noiselvl5gma2", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x7c00}, ++ {"noiselvl5gha0", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x001f}, ++ {"noiselvl5gha1", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x03e0}, ++ {"noiselvl5gha2", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x7c00}, ++ {"noiselvl5gua0", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x001f}, ++ {"noiselvl5gua1", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x03e0}, ++ {"noiselvl5gua2", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x7c00}, ++ {"rxgainerr2g", 0xfffff800, SRFL_PRHEX, SROM11_RXGAINERR_2G, 0xffff}, ++ {"rxgainerr5g", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GL, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_RXGAINERR_5GU, 0xffff}, ++ {NULL, 0, 0, 0, 0} ++}; ++ ++static const sromvar_t perpath_pci_sromvars[] = { ++ {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, ++ {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, ++ {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, ++ {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, ++ {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, ++ {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, ++ {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, ++ {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, ++ {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, ++ {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, ++ {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, ++ {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, ++ {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, ++ {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, ++ {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, ++ {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff}, ++ {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff}, ++ {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff}, ++ {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, ++ {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff}, ++ {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff}, ++ {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff}, ++ {"maxp2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0x00ff}, ++ {"itt2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0xff00}, ++ {"itt5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0xff00}, ++ {"pa2gw0a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, ++ {"pa2gw1a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, ++ {"pa2gw2a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, ++ {"maxp5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0x00ff}, ++ {"maxp5gha", 0x00000700, 0, SROM8_5GLH_MAXP, 0x00ff}, ++ {"maxp5gla", 0x00000700, 0, SROM8_5GLH_MAXP, 0xff00}, ++ {"pa5gw0a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, ++ {"pa5gw1a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, ++ {"pa5gw2a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, ++ {"pa5glw0a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, ++ {"pa5glw1a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff}, ++ {"pa5glw2a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff}, ++ {"pa5ghw0a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, ++ {"pa5ghw1a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff}, ++ {"pa5ghw2a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff}, ++ ++ /* sromrev 11 */ ++ {"maxp2ga", 0xfffff800, 0, SROM11_2G_MAXP, 0x00ff}, ++ {"pa2ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_2G_PA + 2, 0xffff}, ++ {"rxgains5gmelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0007}, ++ {"rxgains5gmtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0078}, ++ {"rxgains5gmtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0080}, ++ {"rxgains5ghelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0700}, ++ {"rxgains5ghtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x7800}, ++ {"rxgains5ghtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x8000}, ++ {"rxgains2gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0007}, ++ {"rxgains2gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x0078}, ++ {"rxgains2gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x0080}, ++ {"rxgains5gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0700}, ++ {"rxgains5gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x7800}, ++ {"rxgains5gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x8000}, ++ {"maxp5ga", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0x00ff}, ++ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0xff00}, ++ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB3B2_MAXP, 0x00ff}, ++ {"", 0xfffff800, 0, SROM11_5GB3B2_MAXP, 0xff00}, ++ {"pa5ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_5GB3_PA + 2, 0xffff}, ++ ++ {NULL, 0, 0, 0, 0} ++}; ++ ++#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) ++#define PHY_TYPE_HT 7 /* HT-Phy value */ ++#define PHY_TYPE_N 4 /* N-Phy value */ ++#define PHY_TYPE_LP 5 /* LP-Phy value */ ++#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */ ++#if !defined(PHY_TYPE_AC) ++#define PHY_TYPE_AC 11 /* AC-Phy value */ ++#endif /* !defined(PHY_TYPE_AC) */ ++#if !defined(PHY_TYPE_NULL) ++#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ ++#endif /* !defined(PHY_TYPE_NULL) */ ++ ++typedef struct { ++ uint16 phy_type; ++ uint16 bandrange; ++ uint16 chain; ++ const char *vars; ++} pavars_t; ++ ++static const pavars_t pavars[] = { ++ /* HTPHY */ ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, ++ /* HTPHY PPR_SUBBAND */ ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 2, "pa5gllw0a2 pa5gllw1a2 pa5gllw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 2, "pa5glhw0a2 pa5glhw1a2 pa5glhw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 2, "pa5gmlw0a2 pa5gmlw1a2 pa5gmlw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 2, "pa5gmhw0a2 pa5gmhw1a2 pa5gmhw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, ++ /* NPHY */ ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ /* LPPHY */ ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"}, ++ /* ACPHY */ ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 0, "pa2ga0"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2ga1"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 2, "pa2ga2"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 0, "pa5ga0"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 1, "pa5ga1"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 2, "pa5ga2"}, ++ {PHY_TYPE_NULL, 0, 0, ""} ++}; ++ ++typedef struct { ++ uint16 phy_type; ++ uint16 bandrange; ++ const char *vars; ++} povars_t; ++ ++static const povars_t povars[] = { ++ /* NPHY */ ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 " ++ "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 " ++ "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 " ++ "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 " ++ "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"}, ++ {PHY_TYPE_NULL, 0, ""} ++}; ++ ++typedef struct { ++ uint8 tag; /* Broadcom subtag name */ ++ uint32 revmask; /* Supported cis_sromrev */ ++ uint8 len; /* Length field of the tuple, note that it includes the ++ * subtag name (1 byte): 1 + tuple content length ++ */ ++ const char *params; ++} cis_tuple_t; ++ ++#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */ ++#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */ ++#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */ ++#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */ ++ ++static const cis_tuple_t cis_hnbuvars[] = { ++ {OTP_RAW1, 0xffffffff, 0, ""}, /* special case */ ++ {OTP_VERS_1, 0xffffffff, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */ ++ {OTP_MANFID, 0xffffffff, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */ ++ /* Unified OTP: tupple to embed USB manfid inside SDIO CIS */ ++ {HNBU_UMANFID, 0xffffffff, 8, "8usbmanfid"}, ++ {HNBU_SROMREV, 0xffffffff, 2, "1sromrev"}, ++ /* NOTE: subdevid is also written to boardtype. ++ * Need to write HNBU_BOARDTYPE to change it if it is different. ++ */ ++ {HNBU_CHIPID, 0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"}, ++ {HNBU_BOARDREV, 0xffffffff, 3, "2boardrev"}, ++ {HNBU_PAPARMS, 0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"}, ++ {HNBU_AA, 0xffffffff, 3, "1aa2g 1aa5g"}, ++ {HNBU_AA, 0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */ ++ {HNBU_AG, 0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"}, ++ {HNBU_BOARDFLAGS, 0xffffffff, 13, "4boardflags 4boardflags2 4boardflags3"}, ++ {HNBU_LEDS, 0xffffffff, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"}, ++ {HNBU_CCODE, 0xffffffff, 4, "2ccode 1cctl"}, ++ {HNBU_CCKPO, 0xffffffff, 3, "2cckpo"}, ++ {HNBU_OFDMPO, 0xffffffff, 5, "4ofdmpo"}, ++ {HNBU_PAPARMS5G, 0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 " ++ "2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit " ++ "1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"}, ++ {HNBU_RDLID, 0xffffffff, 3, "2rdlid"}, ++ {HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g " ++ "0rssisav2g 0bxa2g"}, /* special case */ ++ {HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g " ++ "0rssisav5g 0bxa5g"}, /* special case */ ++ {HNBU_XTALFREQ, 0xffffffff, 5, "4xtalfreq"}, ++ {HNBU_TRI2G, 0xffffffff, 2, "1tri2g"}, ++ {HNBU_TRI5G, 0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"}, ++ {HNBU_RXPO2G, 0xffffffff, 2, "1rxpo2g"}, ++ {HNBU_RXPO5G, 0xffffffff, 2, "1rxpo5g"}, ++ {HNBU_BOARDNUM, 0xffffffff, 3, "2boardnum"}, ++ {HNBU_MACADDR, 0xffffffff, 7, "6macaddr"}, /* special case */ ++ {HNBU_RDLSN, 0xffffffff, 3, "2rdlsn"}, ++ {HNBU_BOARDTYPE, 0xffffffff, 3, "2boardtype"}, ++ {HNBU_LEDDC, 0xffffffff, 3, "2leddc"}, ++ {HNBU_RDLRNDIS, 0xffffffff, 2, "1rdlndis"}, ++ {HNBU_CHAINSWITCH, 0xffffffff, 5, "1txchain 1rxchain 2antswitch"}, ++ {HNBU_REGREV, 0xffffffff, 2, "1regrev"}, ++ {HNBU_FEM, 0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g " ++ "0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */ ++ {HNBU_PAPARMS_C0, 0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 " ++ "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 " ++ "2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"}, ++ {HNBU_PAPARMS_C1, 0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 " ++ "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 " ++ "2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"}, ++ {HNBU_PO_CCKOFDM, 0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo " ++ "4ofdm5ghpo"}, ++ {HNBU_PO_MCS2G, 0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 " ++ "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"}, ++ {HNBU_PO_MCS5GM, 0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 " ++ "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"}, ++ {HNBU_PO_MCS5GLH, 0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 " ++ "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 " ++ "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 " ++ "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"}, ++ {HNBU_CCKFILTTYPE, 0xffffffff, 2, "1cckdigfilttype"}, ++ {HNBU_PO_CDD, 0xffffffff, 3, "2cddpo"}, ++ {HNBU_PO_STBC, 0xffffffff, 3, "2stbcpo"}, ++ {HNBU_PO_40M, 0xffffffff, 3, "2bw40po"}, ++ {HNBU_PO_40MDUP, 0xffffffff, 3, "2bwduppo"}, ++ {HNBU_RDLRWU, 0xffffffff, 2, "1rdlrwu"}, ++ {HNBU_WPS, 0xffffffff, 3, "1wpsgpio 1wpsled"}, ++ {HNBU_USBFS, 0xffffffff, 2, "1usbfs"}, ++ {HNBU_ELNA2G, 0xffffffff, 2, "1elna2g"}, ++ {HNBU_ELNA5G, 0xffffffff, 2, "1elna5g"}, ++ {HNBU_CUSTOM1, 0xffffffff, 5, "4customvar1"}, ++ {OTP_RAW, 0xffffffff, 0, ""}, /* special case */ ++ {HNBU_OFDMPO5G, 0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"}, ++ {HNBU_USBEPNUM, 0xffffffff, 3, "2usbepnum"}, ++ {HNBU_CCKBW202GPO, 0xffffffff, 5, "2cckbw202gpo 2cckbw20ul2gpo"}, ++ {HNBU_LEGOFDMBW202GPO, 0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gp"}, ++ {HNBU_LEGOFDMBW205GPO, 0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo " ++ "4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"}, ++ {HNBU_MCS2GPO, 0xffffffff, 13, "4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo"}, ++ {HNBU_MCS5GLPO, 0xffffffff, 13, "4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"}, ++ {HNBU_MCS5GMPO, 0xffffffff, 13, "4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"}, ++ {HNBU_MCS5GHPO, 0xffffffff, 13, "4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"}, ++ {HNBU_MCS32PO, 0xffffffff, 3, "2mcs32po"}, ++ {HNBU_LEG40DUPPO, 0xffffffff, 3, "2legofdm40duppo"}, ++ {HNBU_TEMPTHRESH, 0xffffffff, 6, "1tempthresh 1periodhyst 1tempoffset 1tempcoropt " ++ "1phycal_tempdelta"}, ++ {HNBU_FEM_CFG, 0xfffff800, 5, "2fem_cfg1 2fem_cfg2"}, ++ {HNBU_ACPA_C0, 0xfffff800, 41, "2subband5gver 2maxp2ga0 2*3pa2ga0 2rxgainsa0 " ++ "1*4maxp5ga0 2*12pa5ga0"}, ++ {HNBU_ACPA_C1, 0xfffff800, 39, "2maxp2ga1 2*3pa2ga1 2rxgainsa1 1*4maxp5ga1 " ++ "2*12pa5ga1"}, ++ {HNBU_ACPA_C2, 0xfffff800, 39, "2maxp2ga2 2*3pa2ga2 2rxgainsa2 1*4maxp5ga2 " ++ "2*12pa5ga2"}, ++ {HNBU_MEAS_PWR, 0xfffff800, 5, "1measpower 1measpower1 1measpower2 2rawtempsense"}, ++ {HNBU_PDOFF, 0xfffff800, 13, "2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 " ++ "2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"}, ++ {HNBU_ACPPR_2GPO, 0xfffff800, 5, "2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo"}, ++ {HNBU_ACPPR_5GPO, 0xfffff800, 31, "4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo " ++ "4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5rlpo 2mcslr5gmpo 2mcslr5ghpo"}, ++ {HNBU_ACPPR_SBPO, 0xfffff800, 33, "2sb20in40hrrpo 2sb20in80and160hr5glpo " ++ "2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo " ++ "2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo " ++ "2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo " ++ "2dot11agduphrpo 2dot11agduplrpo"}, ++ {HNBU_NOISELVL, 0xfffff800, 11, "2noiselvl2g 2noiselvl5gl 2noiselvl5gm " ++ "2noiselvl5gh 2noiselvl5gu"}, ++ {HNBU_RXGAIN_ERR, 0xfffff800, 11, "2rxgainerr2g 2*4rxgainerr5g"}, ++ {HNBU_AGBGA, 0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"}, ++ {HNBU_UUID, 0xffffffff, 17, "16uuid"}, ++ {0xFF, 0xffffffff, 0, ""} ++}; ++ ++#endif /* _bcmsrom_tbl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h b/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h +new file mode 100755 +index 0000000..de1686f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch new file mode 100644 index 00000000..a23cc894 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch @@ -0,0 +1,134 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h +@@ -0,0 +1,128 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * prototypes for functions defined in bcmstdlib.c ++ * ++ * $Id: bcmstdlib.h 289936 2011-10-14 21:06:33Z $: ++ */ ++ ++/* ++ * bcmstdlib.h file should be used only to construct an OSL or alone without any OSL ++ * It should not be used with any orbitarary OSL's as there could be a conflict ++ * with some of the routines defined here. ++*/ ++ ++#ifndef _BCMSTDLIB_H ++#define _BCMSTDLIB_H ++ ++#include ++#include ++#include ++ ++#ifndef INT_MAX ++#define INT_MAX 2147483647 /* from limits.h */ ++#endif ++ ++ ++/* For backwards compatibility, define "BWL_NO_INTERNAL_STDLIB_SUPPORT" to ++ * exclude support for the BRCM stdlib APIs. This should be cleaned-up such ++ * that platforms that require the BRCM stdlib API should simply define ++ * "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate the need for the ++ * following #ifndef check. ++ */ ++#ifndef BWL_NO_INTERNAL_STDLIB_SUPPORT ++#define BWL_INTERNAL_STDLIB_SUPPORT ++#endif ++ ++#ifdef BWL_INTERNAL_STDLIB_SUPPORT ++/* This should be cleaned-up such that platforms that require the BRCM stdlib ++ * API should simply define "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate ++ * the need for the following #ifdef check. ++ */ ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(EFI) ++ ++typedef int FILE; ++#define stdout ((FILE *)1) ++#define stderr ((FILE *)2) ++ ++/* i/o functions */ ++extern int fputc(int c, FILE *stream); ++extern void putc(int c); ++/* extern int putc(int c, FILE *stream); */ ++#define putchar(c) putc(c) ++extern int fputs(const char *s, FILE *stream); ++extern int puts(const char *s); ++extern int getc(void); ++extern bool keypressed(void); ++ ++/* bcopy, bcmp, and bzero */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++extern unsigned long rand(void); ++ ++#define atoi(s) ((int)(strtoul((s), NULL, 10))) ++ ++#endif ++ ++#if !defined(_WIN32) || defined(EFI) ++/* string functions */ ++#define PRINTF_BUFLEN 512 ++extern int printf(const char *fmt, ...) ++ __attribute__ ((format (__printf__, 1, 2))); ++extern int BCMROMFN(sprintf)(char *buf, const char *fmt, ...) ++ __attribute__ ((format (__printf__, 2, 3))); ++ ++extern int BCMROMFN(strcmp)(const char *s1, const char *s2); ++extern size_t BCMROMFN(strlen)(const char *s); ++extern char *BCMROMFN(strcpy)(char *dest, const char *src); ++extern char *BCMROMFN(strstr)(const char *s, const char *find); ++extern char *BCMROMFN(strncpy)(char *dest, const char *src, size_t n); ++extern char *BCMROMFN(strcat)(char *d, const char *s); ++ ++extern int BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n); ++extern char *BCMROMFN(strchr)(const char *str, int c); ++extern char *BCMROMFN(strrchr)(const char *str, int c); ++extern size_t BCMROMFN(strspn)(const char *s1, const char *s2); ++extern size_t BCMROMFN(strcspn)(const char *s1, const char *s2); ++extern unsigned long BCMROMFN(strtoul)(const char *cp, char **endp, int base); ++#define strtol(nptr, endptr, base) ((long)strtoul((nptr), (endptr), (base))) ++ ++extern void *BCMROMFN(memmove)(void *dest, const void *src, size_t n); ++extern void *BCMROMFN(memchr)(const void *s, int c, size_t n); ++ ++extern int BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap); ++/* mem functions */ ++/* For EFI, using EFIDriverLib versions */ ++/* Cannot use memmem in ROM because of character array initialization wiht "" in gcc */ ++extern void *memset(void *dest, int c, size_t n); ++/* Cannot use memcpy in ROM because of structure assignmnets in gcc */ ++extern void *memcpy(void *dest, const void *src, size_t n); ++extern int BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n); ++ ++#endif /* !_WIN32 || EFI */ ++#endif /* BWL_INTERNAL_STDLIB_SUPPORT */ ++ ++#if !defined(_WIN32) || defined(EFI) ++extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...) ++ __attribute__ ((format (__printf__, 3, 4))); ++#else ++extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...); ++#endif ++ ++extern int BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap); ++ ++#endif /* _BCMSTDLIB_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmutils.h b/drivers/bcmdrivers/gmac/src/include/bcmutils.h +new file mode 100755 +index 0000000..ac00a91 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch new file mode 100644 index 00000000..567c2854 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch @@ -0,0 +1,870 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmutils.h +@@ -0,0 +1,864 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc useful os-independent macros and functions. ++ * ++ * $Id: bcmutils.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _bcmutils_h_ ++#define _bcmutils_h_ ++ ++#if defined(UNDER_CE) ++#include ++#else ++#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src)) ++#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) ++#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src)) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef PKTQ_LOG ++#include ++#endif ++ ++/* ctype replacement */ ++#define _BCM_U 0x01 /* upper */ ++#define _BCM_L 0x02 /* lower */ ++#define _BCM_D 0x04 /* digit */ ++#define _BCM_C 0x08 /* cntrl */ ++#define _BCM_P 0x10 /* punct */ ++#define _BCM_S 0x20 /* white space (space/lf/tab) */ ++#define _BCM_X 0x40 /* hex digit */ ++#define _BCM_SP 0x80 /* hard space (0x20) */ ++ ++#if defined(BCMROMBUILD) ++extern const unsigned char BCMROMDATA(bcm_ctype)[]; ++#else ++extern const unsigned char bcm_ctype[]; ++#endif ++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) ++ ++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) ++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) ++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) ++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) ++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) ++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) ++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) ++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) ++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) ++#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) ++#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) ++ ++/* Buffer structure for collecting string-formatted data ++* using bcm_bprintf() API. ++* Use bcm_binit() to initialize before use ++*/ ++ ++struct bcmstrbuf { ++ char *buf; /* pointer to current position in origbuf */ ++ unsigned int size; /* current (residual) size in bytes */ ++ char *origbuf; /* unmodified pointer to orignal buffer */ ++ unsigned int origsize; /* unmodified orignal buffer size in bytes */ ++}; ++ ++/* ** driver-only section ** */ ++#ifdef BCMDRIVER ++#ifdef EFI ++/* forward declare structyre type */ ++struct spktq; ++#endif ++#include ++ ++#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ ++ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++} ++ ++/* osl multi-precedence packet queue */ ++#ifndef PKTQ_LEN_DEFAULT ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#endif ++#ifndef PKTQ_MAX_PREC ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ ++#endif ++ ++typedef struct pktq_prec { ++ void *head; /* first packet to dequeue */ ++ void *tail; /* last packet to dequeue */ ++ uint16 len; /* number of queued packets */ ++ uint16 max; /* maximum number of queued packets */ ++} pktq_prec_t; ++ ++#ifdef PKTQ_LOG ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_counters_t; ++#endif /* PKTQ_LOG */ ++ ++ ++#define PKTQ_COMMON \ ++ uint16 num_prec; /* number of precedences in use */ \ ++ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \ ++ uint16 max; /* total max packets */ \ ++ uint16 len; /* total number of packets */ ++ ++/* multi-priority pkt queue */ ++struct pktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[PKTQ_MAX_PREC]; ++#ifdef PKTQ_LOG ++ pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ ++#endif ++}; ++ ++/* simple, non-priority pkt queue */ ++struct spktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[1]; ++}; ++ ++#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) ++ ++/* fn(pkt, arg). return true if pkt belongs to if */ ++typedef bool (*ifpkt_cb_t)(void*, int); ++ ++#ifdef BCMPKTPOOL ++#define POOL_ENAB(pool) ((pool) && (pool)->inited) ++#if defined(BCM4329C0) ++#define SHARED_POOL (pktpool_shared_ptr) ++#else ++#define SHARED_POOL (pktpool_shared) ++#endif /* BCM4329C0 */ ++#else /* BCMPKTPOOL */ ++#define POOL_ENAB(bus) 0 ++#define SHARED_POOL ((struct pktpool *)NULL) ++#endif /* BCMPKTPOOL */ ++ ++#ifndef PKTPOOL_LEN_MAX ++#define PKTPOOL_LEN_MAX 40 ++#endif /* PKTPOOL_LEN_MAX */ ++#define PKTPOOL_CB_MAX 3 ++ ++struct pktpool; ++typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); ++typedef struct { ++ pktpool_cb_t cb; ++ void *arg; ++} pktpool_cbinfo_t; ++ ++#ifdef BCMDBG_POOL ++/* pkt pool debug states */ ++#define POOL_IDLE 0 ++#define POOL_RXFILL 1 ++#define POOL_RXDH 2 ++#define POOL_RXD11 3 ++#define POOL_TXDH 4 ++#define POOL_TXD11 5 ++#define POOL_AMPDU 6 ++#define POOL_TXENQ 7 ++ ++typedef struct { ++ void *p; ++ uint32 cycles; ++ uint32 dur; ++} pktpool_dbg_t; ++ ++typedef struct { ++ uint8 txdh; /* tx to host */ ++ uint8 txd11; /* tx to d11 */ ++ uint8 enq; /* waiting in q */ ++ uint8 rxdh; /* rx from host */ ++ uint8 rxd11; /* rx from d11 */ ++ uint8 rxfill; /* dma_rxfill */ ++ uint8 idle; /* avail in pool */ ++} pktpool_stats_t; ++#endif /* BCMDBG_POOL */ ++ ++typedef struct pktpool { ++ bool inited; ++ uint16 r; ++ uint16 w; ++ uint16 len; ++ uint16 maxlen; ++ uint16 plen; ++ bool istx; ++ bool empty; ++ uint8 cbtoggle; ++ uint8 cbcnt; ++ uint8 ecbcnt; ++ bool emptycb_disable; ++ pktpool_cbinfo_t *availcb_excl; ++ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX]; ++ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; ++ void *q[PKTPOOL_LEN_MAX + 1]; ++ ++#ifdef BCMDBG_POOL ++ uint8 dbg_cbcnt; ++ pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; ++ uint16 dbg_qlen; ++ pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; ++#endif ++} pktpool_t; ++ ++#if defined(BCM4329C0) ++extern pktpool_t *pktpool_shared_ptr; ++#else ++extern pktpool_t *pktpool_shared; ++#endif /* BCM4329C0 */ ++ ++extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx); ++extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); ++extern void* pktpool_get(pktpool_t *pktp); ++extern void pktpool_free(pktpool_t *pktp, void *p); ++extern int pktpool_add(pktpool_t *pktp, void *p); ++extern uint16 pktpool_avail(pktpool_t *pktp); ++extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); ++extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); ++extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); ++extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); ++extern bool pktpool_emptycb_disabled(pktpool_t *pktp); ++ ++#define POOLPTR(pp) ((pktpool_t *)(pp)) ++#define pktpool_len(pp) (POOLPTR(pp)->len - 1) ++#define pktpool_plen(pp) (POOLPTR(pp)->plen) ++#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) ++ ++#ifdef BCMDBG_POOL ++extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_start_trigger(pktpool_t *pktp, void *p); ++extern int pktpool_dbg_dump(pktpool_t *pktp); ++extern int pktpool_dbg_notify(pktpool_t *pktp); ++extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); ++#endif /* BCMDBG_POOL */ ++ ++/* forward definition of ether_addr structure used by some function prototypes */ ++ ++struct ether_addr; ++ ++extern int ether_isbcast(const void *ea); ++extern int ether_isnulladdr(const void *ea); ++ ++/* operations on a specific precedence in packet queue */ ++ ++#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) ++#define pktq_pmax(pq, prec) ((pq)->q[prec].max) ++#define pktq_plen(pq, prec) ((pq)->q[prec].len) ++#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) ++#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) ++#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) ++ ++#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) ++#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) ++ ++extern void *pktq_penq(struct pktq *pq, int prec, void *p); ++extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); ++extern void *pktq_pdeq(struct pktq *pq, int prec); ++extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); ++extern void *pktq_pdeq_tail(struct pktq *pq, int prec); ++/* Empty the queue at particular precedence level */ ++extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ++ ifpkt_cb_t fn, int arg); ++/* Remove a specified packet from its queue */ ++extern bool pktq_pdel(struct pktq *pq, void *p, int prec); ++ ++/* operations on a set of precedences in packet queue */ ++ ++extern int pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); ++extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); ++ ++/* operations on packet queue as a whole */ ++ ++#define pktq_len(pq) ((int)(pq)->len) ++#define pktq_max(pq) ((int)(pq)->max) ++#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) ++#define pktq_full(pq) ((pq)->len >= (pq)->max) ++#define pktq_empty(pq) ((pq)->len == 0) ++ ++/* operations for single precedence queues */ ++#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) ++#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) ++#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) ++#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) ++#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) ++ ++extern void pktq_init(struct pktq *pq, int num_prec, int max_len); ++extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); ++ ++/* prec_out may be NULL if caller is not interested in return value */ ++extern void *pktq_deq(struct pktq *pq, int *prec_out); ++extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); ++extern void *pktq_peek(struct pktq *pq, int *prec_out); ++extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); ++ ++/* externs */ ++/* packet */ ++extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pkttotlen(osl_t *osh, void *p); ++extern void *pktlast(osl_t *osh, void *p); ++extern uint pktsegcnt(osl_t *osh, void *p); ++extern uint pktsegcnt_war(osl_t *osh, void *p); ++extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); ++extern void *pktoffset(osl_t *osh, void *p, uint offset); ++ ++/* Get priority from a packet and pass it back in scb (or equiv) */ ++#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ ++#define PKTPRIO_VLAN 0x200 /* VLAN prio found */ ++#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ ++#define PKTPRIO_DSCP 0x800 /* DSCP prio found */ ++ ++extern uint pktsetprio(void *pkt, bool update_vtag); ++ ++/* string */ ++extern int BCMROMFN(bcm_atoi)(const char *s); ++extern ulong BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base); ++extern char *BCMROMFN(bcmstrstr)(const char *haystack, const char *needle); ++extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src); ++extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size); ++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); ++char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); ++int bcmstricmp(const char *s1, const char *s2); ++int bcmstrnicmp(const char* s1, const char* s2, int cnt); ++ ++ ++/* ethernet address */ ++extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); ++extern int BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea); ++ ++/* ip address */ ++struct ipv4_addr; ++extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); ++ ++/* delay */ ++extern void bcm_mdelay(uint ms); ++/* variable access */ ++#if defined(DONGLEBUILD) && !defined(WLTEST) ++#ifdef BCMDBG ++#define NVRAM_RECLAIM_CHECK(name) \ ++ if (attach_part_reclaimed == TRUE) { \ ++ printf("%s: NVRAM already reclaimed, %s\n", __FUNCTION__, (name)); \ ++ *(char*) 0 = 0; /* TRAP */ \ ++ return NULL; \ ++ } ++#else /* BCMDBG */ ++#define NVRAM_RECLAIM_CHECK(name) \ ++ if (attach_part_reclaimed == TRUE) { \ ++ *(char*) 0 = 0; /* TRAP */ \ ++ return NULL; \ ++ } ++#endif /* BCMDBG */ ++#else /* DONGLEBUILD && !WLTEST && !BCMINTERNAL && !BCMDBG_DUMP */ ++#define NVRAM_RECLAIM_CHECK(name) ++#endif ++ ++extern char *getvar(char *vars, const char *name); ++extern int getintvar(char *vars, const char *name); ++extern int getintvararray(char *vars, const char *name, int index); ++extern int getintvararraysize(char *vars, const char *name); ++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); ++extern int getwanport(void); ++extern int getbrcmtag(void); ++#ifdef BCMDBG ++extern void prpkt(const char *msg, osl_t *osh, void *p0); ++#endif /* BCMDBG */ ++#ifdef BCMPERFSTATS ++extern void bcm_perf_enable(void); ++extern void bcmstats(char *fmt); ++extern void bcmlog(char *fmt, uint a1, uint a2); ++extern void bcmdumplog(char *buf, int size); ++extern int bcmdumplogent(char *buf, uint idx); ++#else ++#define bcm_perf_enable() ++#define bcmstats(fmt) ++#define bcmlog(fmt, a1, a2) ++#define bcmdumplog(buf, size) *buf = '\0' ++#define bcmdumplogent(buf, idx) -1 ++#endif /* BCMPERFSTATS */ ++ ++#if defined(BCMTSTAMPEDLOGS) ++#define TSF_TICKS_PER_MS 1024 ++/* Store a TSF timestamp and a log line in the log buffer */ ++extern void bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2); ++/* Print out the log buffer with timestamps */ ++extern void bcmprinttslogs(void); ++/* Print out a microsecond timestamp as "sec.ms.us " */ ++extern void bcmprinttstamp(uint32 us); ++/* Dump to buffer a microsecond timestamp as "sec.ms.us " */ ++extern void bcmdumptslog(char *buf, int size); ++#else ++#define bcmtslog(tstamp, fmt, a1, a2) ++#define bcmprinttslogs() ++#define bcmprinttstamp(us) ++#define bcmdumptslog(buf, size) ++#endif /* BCMTSTAMPEDLOGS */ ++ ++extern char *bcm_nvram_vars(uint *length); ++extern int bcm_nvram_cache(void *sih); ++ ++/* Support for sharing code across in-driver iovar implementations. ++ * The intent is that a driver use this structure to map iovar names ++ * to its (private) iovar identifiers, and the lookup function to ++ * find the entry. Macros are provided to map ids and get/set actions ++ * into a single number space for a switch statement. ++ */ ++ ++/* iovar structure */ ++typedef struct bcm_iovar { ++ const char *name; /* name for lookup and display */ ++ uint16 varid; /* id for switch */ ++ uint16 flags; /* driver-specific flag bits */ ++ uint16 type; /* base type of argument */ ++ uint16 minlen; /* min length for buffer vars */ ++} bcm_iovar_t; ++ ++/* varid definitions are per-driver, may use these get/set bits */ ++ ++/* IOVar action bits for id mapping */ ++#define IOV_GET 0 /* Get an iovar */ ++#define IOV_SET 1 /* Set an iovar */ ++ ++/* Varid to actionid mapping */ ++#define IOV_GVAL(id) ((id) * 2) ++#define IOV_SVAL(id) ((id) * 2 + IOV_SET) ++#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) ++#define IOV_ID(actionid) (actionid >> 1) ++ ++/* flags are per-driver based on driver attributes */ ++ ++extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); ++extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); ++#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ ++ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); ++#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ ++#endif /* BCMDRIVER */ ++ ++/* Base type definitions */ ++#define IOVT_VOID 0 /* no value (implictly set only) */ ++#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ ++#define IOVT_INT8 2 /* integer values are range-checked */ ++#define IOVT_UINT8 3 /* unsigned int 8 bits */ ++#define IOVT_INT16 4 /* int 16 bits */ ++#define IOVT_UINT16 5 /* unsigned int 16 bits */ ++#define IOVT_INT32 6 /* int 32 bits */ ++#define IOVT_UINT32 7 /* unsigned int 32 bits */ ++#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ ++#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) ++ ++/* Initializer for IOV type strings */ ++#define BCM_IOV_TYPE_INIT { \ ++ "void", \ ++ "bool", \ ++ "int8", \ ++ "uint8", \ ++ "int16", \ ++ "uint16", \ ++ "int32", \ ++ "uint32", \ ++ "buffer", \ ++ "" } ++ ++#define BCM_IOVT_IS_INT(type) (\ ++ (type == IOVT_BOOL) || \ ++ (type == IOVT_INT8) || \ ++ (type == IOVT_UINT8) || \ ++ (type == IOVT_INT16) || \ ++ (type == IOVT_UINT16) || \ ++ (type == IOVT_INT32) || \ ++ (type == IOVT_UINT32)) ++ ++/* ** driver/apps-shared section ** */ ++ ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) ++ ++ ++/* ++ * error codes could be added but the defined ones shouldn't be changed/deleted ++ * these error codes are exposed to the user code ++ * when ever a new error code is added to this list ++ * please update errorstring table with the related error string and ++ * update osl files with os specific errorcode map ++*/ ++ ++#define BCME_OK 0 /* Success */ ++#define BCME_ERROR -1 /* Error generic */ ++#define BCME_BADARG -2 /* Bad Argument */ ++#define BCME_BADOPTION -3 /* Bad option */ ++#define BCME_NOTUP -4 /* Not up */ ++#define BCME_NOTDOWN -5 /* Not down */ ++#define BCME_NOTAP -6 /* Not AP */ ++#define BCME_NOTSTA -7 /* Not STA */ ++#define BCME_BADKEYIDX -8 /* BAD Key Index */ ++#define BCME_RADIOOFF -9 /* Radio Off */ ++#define BCME_NOTBANDLOCKED -10 /* Not band locked */ ++#define BCME_NOCLK -11 /* No Clock */ ++#define BCME_BADRATESET -12 /* BAD Rate valueset */ ++#define BCME_BADBAND -13 /* BAD Band */ ++#define BCME_BUFTOOSHORT -14 /* Buffer too short */ ++#define BCME_BUFTOOLONG -15 /* Buffer too long */ ++#define BCME_BUSY -16 /* Busy */ ++#define BCME_NOTASSOCIATED -17 /* Not Associated */ ++#define BCME_BADSSIDLEN -18 /* Bad SSID len */ ++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ ++#define BCME_BADCHAN -20 /* Bad Channel */ ++#define BCME_BADADDR -21 /* Bad Address */ ++#define BCME_NORESOURCE -22 /* Not Enough Resources */ ++#define BCME_UNSUPPORTED -23 /* Unsupported */ ++#define BCME_BADLEN -24 /* Bad length */ ++#define BCME_NOTREADY -25 /* Not Ready */ ++#define BCME_EPERM -26 /* Not Permitted */ ++#define BCME_NOMEM -27 /* No Memory */ ++#define BCME_ASSOCIATED -28 /* Associated */ ++#define BCME_RANGE -29 /* Not In Range */ ++#define BCME_NOTFOUND -30 /* Not Found */ ++#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ ++#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ ++#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ ++#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ ++#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ ++#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ ++#define BCME_VERSION -37 /* Incorrect version */ ++#define BCME_TXFAIL -38 /* TX failure */ ++#define BCME_RXFAIL -39 /* RX failure */ ++#define BCME_NODEVICE -40 /* Device not present */ ++#define BCME_NMODE_DISABLED -41 /* NMODE disabled */ ++#define BCME_NONRESIDENT -42 /* access to nonresident overlay */ ++#define BCME_LAST BCME_NONRESIDENT ++ ++/* These are collection of BCME Error strings */ ++#define BCMERRSTRINGTABLE { \ ++ "OK", \ ++ "Undefined error", \ ++ "Bad Argument", \ ++ "Bad Option", \ ++ "Not up", \ ++ "Not down", \ ++ "Not AP", \ ++ "Not STA", \ ++ "Bad Key Index", \ ++ "Radio Off", \ ++ "Not band locked", \ ++ "No clock", \ ++ "Bad Rate valueset", \ ++ "Bad Band", \ ++ "Buffer too short", \ ++ "Buffer too long", \ ++ "Busy", \ ++ "Not Associated", \ ++ "Bad SSID len", \ ++ "Out of Range Channel", \ ++ "Bad Channel", \ ++ "Bad Address", \ ++ "Not Enough Resources", \ ++ "Unsupported", \ ++ "Bad length", \ ++ "Not Ready", \ ++ "Not Permitted", \ ++ "No Memory", \ ++ "Associated", \ ++ "Not In Range", \ ++ "Not Found", \ ++ "WME Not Enabled", \ ++ "TSPEC Not Found", \ ++ "ACM Not Supported", \ ++ "Not WME Association", \ ++ "SDIO Bus Error", \ ++ "Dongle Not Accessible", \ ++ "Incorrect version", \ ++ "TX Failure", \ ++ "RX Failure", \ ++ "Device Not Present", \ ++ "NMODE Disabled", \ ++ "Nonresident overlay access", \ ++} ++ ++#ifndef ABS ++#define ABS(a) (((a) < 0) ? -(a) : (a)) ++#endif /* ABS */ ++ ++#ifndef MIN ++#define MIN(a, b) (((a) < (b)) ? (a) : (b)) ++#endif /* MIN */ ++ ++#ifndef MAX ++#define MAX(a, b) (((a) > (b)) ? (a) : (b)) ++#endif /* MAX */ ++ ++#define CEIL(x, y) (((x) + ((y) - 1)) / (y)) ++#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) ++#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) ++#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0) ++#define VALID_MASK(mask) !((mask) & ((mask) + 1)) ++ ++#ifndef OFFSETOF ++#ifdef __ARMCC_VERSION ++/* ++ * The ARM RVCT compiler complains when using OFFSETOF where a constant ++ * expression is expected, such as an initializer for a static object. ++ * offsetof from the runtime library doesn't have that problem. ++ */ ++#include ++#define OFFSETOF(type, member) offsetof(type, member) ++#else ++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) ++#endif /* __ARMCC_VERSION */ ++#endif /* OFFSETOF */ ++ ++#ifndef ARRAYSIZE ++#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) ++#endif ++ ++/* Reference a function; used to prevent a static function from being optimized out */ ++extern void *_bcmutils_dummy_fn; ++#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) ++ ++/* bit map related macros */ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) ++#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) ++#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) ++#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) ++#endif /* setbit */ ++ ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) ++ ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) ++ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) ++ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) ++ ++/* modulo add/sub - assumes x, y E [0, bound - 1] */ ++#define MODADD(x, y, bound) \ ++ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) ++#define MODSUB(x, y, bound) \ ++ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) ++ ++/* module add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) ++ ++/* crc defines */ ++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ ++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ ++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ ++ ++/* use for direct output of MAC address in printf etc */ ++#define MACF "%02x:%02x:%02x:%02x:%02x:%02x" ++#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ ++ ((struct ether_addr *) (ea))->octet[1], \ ++ ((struct ether_addr *) (ea))->octet[2], \ ++ ((struct ether_addr *) (ea))->octet[3], \ ++ ((struct ether_addr *) (ea))->octet[4], \ ++ ((struct ether_addr *) (ea))->octet[5] ++ ++#define ETHER_TO_MACF(ea) (ea).octet[0], \ ++ (ea).octet[1], \ ++ (ea).octet[2], \ ++ (ea).octet[3], \ ++ (ea).octet[4], \ ++ (ea).octet[5] ++ ++/* bcm_format_flags() bit description structure */ ++typedef struct bcm_bit_desc { ++ uint32 bit; ++ const char* name; ++} bcm_bit_desc_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef struct bcm_tlv { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} bcm_tlv_t; ++ ++/* Check that bcm_tlv_t fits into the given buflen */ ++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) ++ ++/* buffer length for ethernet address from bcm_ether_ntoa() */ ++#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ ++ ++/* crypto utility function */ ++/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */ ++static INLINE void ++xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) ++{ ++ if ( ++#ifdef __i386__ ++ 1 || ++#endif ++ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { ++ /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ ++ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ ++ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0]; ++ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1]; ++ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2]; ++ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3]; ++ } else { ++ /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */ ++ int k; ++ for (k = 0; k < 16; k++) ++ dst[k] = src1[k] ^ src2[k]; ++ } ++} ++ ++/* externs */ ++/* crc */ ++extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc); ++extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc); ++extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc); ++ ++/* format/print */ ++#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ ++ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) ++extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); ++#endif ++ ++#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ ++ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ ++ defined(WLMEDIA_PEAKRATE) ++extern int bcm_format_hex(char *str, const void *bytes, int len); ++#endif ++ ++#ifdef BCMDBG ++extern void deadbeef(void *p, size_t len); ++#endif ++extern const char *bcm_crypto_algo_name(uint algo); ++extern char *bcm_chipname(uint chipid, char *buf, uint len); ++extern char *bcm_brev_str(uint32 brev, char *buf); ++extern void printbig(char *buf); ++extern void prhex(const char *msg, uchar *buf, uint len); ++ ++/* IE parsing */ ++extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); ++ ++/* bcmerror */ ++extern const char *bcmerrorstr(int bcmerror); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++typedef uint32 mbool; ++#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ ++#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ ++#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++/* generic datastruct to help dump routines */ ++struct fielddesc { ++ const char *nameandfmt; ++ uint32 offset; ++ uint32 len; ++}; ++ ++extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); ++extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len); ++ ++extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); ++extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes); ++extern void bcm_print_bytes(const char *name, const uchar *cdata, int len); ++ ++typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); ++extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, ++ char *buf, uint32 bufsize); ++extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength); ++ ++extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); ++ ++/* power conversion */ ++extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm); ++extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw); ++ ++extern int32 exthdr_validate(char *ptr, uint size); ++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); ++ ++unsigned int process_nvram_vars(char *varbuf, unsigned int len); ++ ++#ifdef __cplusplus ++ } ++#endif ++ ++#endif /* _bcmutils_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmwifi.h b/drivers/bcmdrivers/gmac/src/include/bcmwifi.h +new file mode 100755 +index 0000000..1470332 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch new file mode 100644 index 00000000..d7a1c5b8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch @@ -0,0 +1,462 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmwifi.h +@@ -0,0 +1,456 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for WL and Apps ++ * This header file housing the define and function prototype use by ++ * both the wl driver, tools & Apps. ++ * ++ * $Id: bcmwifi.h 293848 2011-11-03 12:31:04Z $ ++ */ ++ ++#ifndef _bcmwifi_h_ ++#define _bcmwifi_h_ ++ ++ ++/* A chanspec holds the channel number, band, bandwidth and control sideband */ ++typedef uint16 chanspec_t; ++ ++/* channel defines */ ++#define CH_UPPER_SB 0x01 ++#define CH_LOWER_SB 0x02 ++#define CH_EWA_VALID 0x04 ++#define CH_80MHZ_APART 16 ++#define CH_40MHZ_APART 8 ++#define CH_20MHZ_APART 4 ++#define CH_10MHZ_APART 2 ++#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ ++#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ ++#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, ++ * this is that + 1 rounded up to a multiple of NBBY (8). ++ * DO NOT MAKE it > 255: channels are uint8's all over ++ */ ++#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) ++ ++#ifndef D11AC_IOTYPES ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_CHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_CHANSPEC_BW_MASK 0x0C00 ++#define WL_CHANSPEC_BW_SHIFT 10 ++#define WL_CHANSPEC_BW_10 0x0400 ++#define WL_CHANSPEC_BW_20 0x0800 ++#define WL_CHANSPEC_BW_40 0x0C00 ++ ++#define WL_CHANSPEC_BAND_MASK 0xf000 ++#define WL_CHANSPEC_BAND_SHIFT 12 ++#define WL_CHANSPEC_BAND_5G 0x1000 ++#define WL_CHANSPEC_BAND_2G 0x2000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++ ++/* chanspec stores radio channel & flags to indicate control channel location, i.e. upper/lower */ ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) ++#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) ++#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) ++#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ ++ (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ ++ (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++#define CHANSPEC_STR_LEN 8 ++ ++#else /* D11AC_IOTYPES */ ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++#define WL_CHANSPEC_CHAN1_MASK 0x000f ++#define WL_CHANSPEC_CHAN1_SHIFT 0 ++#define WL_CHANSPEC_CHAN2_MASK 0x00f0 ++#define WL_CHANSPEC_CHAN2_SHIFT 4 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0700 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LLL 0x0000 ++#define WL_CHANSPEC_CTL_SB_LLU 0x0100 ++#define WL_CHANSPEC_CTL_SB_LUL 0x0200 ++#define WL_CHANSPEC_CTL_SB_LUU 0x0300 ++#define WL_CHANSPEC_CTL_SB_ULL 0x0400 ++#define WL_CHANSPEC_CTL_SB_ULU 0x0500 ++#define WL_CHANSPEC_CTL_SB_UUL 0x0600 ++#define WL_CHANSPEC_CTL_SB_UUU 0x0700 ++#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL ++#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU ++#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU ++ ++#define WL_CHANSPEC_BW_MASK 0x3800 ++#define WL_CHANSPEC_BW_SHIFT 11 ++#define WL_CHANSPEC_BW_5 0x0000 ++#define WL_CHANSPEC_BW_10 0x0800 ++#define WL_CHANSPEC_BW_20 0x1000 ++#define WL_CHANSPEC_BW_40 0x1800 ++#define WL_CHANSPEC_BW_80 0x2000 ++#define WL_CHANSPEC_BW_160 0x2800 ++#define WL_CHANSPEC_BW_8080 0x3000 ++ ++#define WL_CHANSPEC_BAND_MASK 0xc000 ++#define WL_CHANSPEC_BAND_SHIFT 14 ++#define WL_CHANSPEC_BAND_2G 0x0000 ++#define WL_CHANSPEC_BAND_3G 0x4000 ++#define WL_CHANSPEC_BAND_4G 0x8000 ++#define WL_CHANSPEC_BAND_5G 0xc000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ ++ ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_80 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_160 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++ ++/* simple MACROs to get different fields of chanspec */ ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) ++#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_UPPER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC_SB_LOWER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++/** ++ * Number of chars needed for wf_chspec_ntoa() destination character buffer. ++ */ ++#define CHANSPEC_STR_LEN 20 ++ ++ ++/* Legacy Chanspec defines ++ * These are the defines for the previous format of the chanspec_t ++ */ ++#define WL_LCHANSPEC_CHAN_MASK 0x00ff ++#define WL_LCHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_LCHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_LCHANSPEC_CTL_SB_SHIFT 8 ++#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_LCHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_LCHANSPEC_BW_MASK 0x0C00 ++#define WL_LCHANSPEC_BW_SHIFT 10 ++#define WL_LCHANSPEC_BW_10 0x0400 ++#define WL_LCHANSPEC_BW_20 0x0800 ++#define WL_LCHANSPEC_BW_40 0x0C00 ++ ++#define WL_LCHANSPEC_BAND_MASK 0xf000 ++#define WL_LCHANSPEC_BAND_SHIFT 12 ++#define WL_LCHANSPEC_BAND_5G 0x1000 ++#define WL_LCHANSPEC_BAND_2G 0x2000 ++ ++#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) ++#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) ++#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) ++#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) ++#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) ++#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) ++#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) ++#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) ++#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) ++ ++#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) ++ ++#endif /* D11AC_IOTYPES */ ++ ++/* ++ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency ++ * given a channel number. ++ * chan_freq = chan_factor * 500Mhz + chan_number * 5 ++ */ ++ ++/** ++ * Channel Factor for the starting frequence of 2.4 GHz channels. ++ * The value corresponds to 2407 MHz. ++ */ ++#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 5 GHz channels. ++ * The value corresponds to 5000 MHz. ++ */ ++#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 4.9 GHz channels. ++ * The value corresponds to 4000 MHz. ++ */ ++#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ ++ ++/* defined rate in 500kbps */ ++#define WLC_MAXRATE 108 /* in 500kbps units */ ++#define WLC_RATE_1M 2 /* in 500kbps units */ ++#define WLC_RATE_2M 4 /* in 500kbps units */ ++#define WLC_RATE_5M5 11 /* in 500kbps units */ ++#define WLC_RATE_11M 22 /* in 500kbps units */ ++#define WLC_RATE_6M 12 /* in 500kbps units */ ++#define WLC_RATE_9M 18 /* in 500kbps units */ ++#define WLC_RATE_12M 24 /* in 500kbps units */ ++#define WLC_RATE_18M 36 /* in 500kbps units */ ++#define WLC_RATE_24M 48 /* in 500kbps units */ ++#define WLC_RATE_36M 72 /* in 500kbps units */ ++#define WLC_RATE_48M 96 /* in 500kbps units */ ++#define WLC_RATE_54M 108 /* in 500kbps units */ ++ ++#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ ++ ++/** ++ * Convert chanspec to ascii string ++ * ++ * @param chspec chanspec format ++ * @param buf ascii string of chanspec ++ * ++ * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes ++ * ++ * @see CHANSPEC_STR_LEN ++ */ ++extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); ++ ++/** ++ * Convert ascii string to chanspec ++ * ++ * @param a pointer to input string ++ * ++ * @return >= 0 if successful or 0 otherwise ++ */ ++extern chanspec_t wf_chspec_aton(const char *a); ++ ++/** ++ * Verify the chanspec fields are valid. ++ * ++ * Verify the chanspec is using a legal set field values, i.e. that the chanspec ++ * specified a band, bw, ctl_sb and channel and that the combination could be ++ * legal given some set of circumstances. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is malformed, FALSE if it looks good. ++ */ ++extern bool wf_chspec_malformed(chanspec_t chanspec); ++ ++/** ++ * Verify the chanspec specifies a valid channel according to 802.11. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is a valid 802.11 channel ++ */ ++extern bool wf_chspec_valid(chanspec_t chanspec); ++ ++/** ++ * Return the primary (control) channel. ++ * ++ * This function returns the channel number of the primary 20MHz channel. For ++ * 20MHz channels this is just the channel number. For 40MHz or wider channels ++ * it is the primary 20MHz channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the channel number of the primary 20MHz channel ++ */ ++extern uint8 wf_chspec_ctlchan(chanspec_t chspec); ++ ++/** ++ * Return the primary (control) chanspec. ++ * ++ * This function returns the chanspec of the primary 20MHz channel. For 20MHz ++ * channels this is just the chanspec. For 40MHz or wider channels it is the ++ * chanspec of the primary 20MHZ channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the chanspec of the primary 20MHz channel ++ */ ++extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); ++ ++/** ++ * Return a channel number corresponding to a frequency. ++ * ++ * Return the channel number for a given frequency and base frequency. ++ * The returned channel number is relative to the given base frequency. ++ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for ++ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. ++ * ++ * Frequency is specified in MHz. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * ++ * The returned channel will be in the range [1, 14] in the 2.4 GHz band ++ * and [0, 200] otherwise. ++ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the ++ * frequency is not a 2.4 GHz channel, or if the frequency is not and even ++ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param freq frequency in MHz ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a channel number ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_mhz2channel(uint freq, uint start_factor); ++ ++/** ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * The channel number is interpreted relative to the given base frequency. ++ * ++ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * The channel range of [1, 14] is only checked for a start_factor of ++ * WF_CHAN_FACTOR_2_4_G (4814). ++ * Odd start_factors produce channels on .5 MHz boundaries, in which case ++ * the answer is rounded down to an integral MHz. ++ * -1 is returned for an out of range channel. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param channel input channel number ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a frequency in MHz ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_channel2mhz(uint channel, uint start_factor); ++ ++#endif /* _bcmwifi_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/compvers.sh b/drivers/bcmdrivers/gmac/src/include/compvers.sh +new file mode 100755 +index 0000000..3f6fd6a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch new file mode 100644 index 00000000..c15e50f8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_compvers.sh.patch @@ -0,0 +1,128 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/compvers.sh +@@ -0,0 +1,122 @@ ++#!/bin/bash ++# ++# Given a list of components, generate _version.h ++# from version.h.in in 's directory ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: compvers.sh 281527 2011-09-02 17:12:53Z $ ++# ++ ++# Optional argument ++ACTION=$1 ++[ -n "$VERBOSE" ] && export VERBOSE ++ ++SRCBASE=.. ++ ++# List of components ++# TODO: In the long term component versioning model, following list ++# TODO: or table of components will come from a central file ++COMPONENTS=( \ ++ upnp \ ++ phy \ ++ router \ ++ wps \ ++) ++ ++# Component dirs. Need one entry for each of above COMPONENTS ++COMPONENT_DIR_upnp=${SRCBASE}/router/libupnp/include ++COMPONENT_DIR_phy=${SRCBASE}/wl/phy ++COMPONENT_DIR_router=${SRCBASE}/router/shared ++COMPONENT_DIR_wps=${SRCBASE}/wps/common/include ++ ++# For a given component, query automerger for a different ++# path than COMPONENT_DIR_. ++# Force router component to be pointing to local branch or tag. ++COMPONENT_QUERY_router=src_force_local_component ++ ++ ++ ++# ===== DO NOT CHANGE ANYTHING BELOW THIS LINE ===== ++ ++NULL=/dev/null ++MKCOMPVER=${SRCBASE}/tools/release/mkversion.sh ++MERGERLOG=${SRCBASE}/../merger_sources.log ++ ++# TODO: Post svn transition, network paths will be taken away ++GETCOMPVER=getcompver.py ++GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER ++GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} ++ ++# ++# If there is a local copy GETCOMPVER use it ahead of network copy ++# ++if [ -s "$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER" ++elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" ++elif [ -s "$GETCOMPVER_NET" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET" ++elif [ -s "$GETCOMPVER_NET_WIN" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" ++fi ++ ++# ++# If $GETCOMPVER isn't found, fetch it from SVN ++# (this is very rare) ++# ++if [ ! -s "$GETCOMPVER_PATH" ]; then ++ svn export -q \ ++ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ ++ ${GETCOMPVER} 2> $NULL ++ GETCOMPVER_PATH=$GETCOMPVER ++fi ++ ++# ++# Now walk through each specified component to generate its ++# component_version.h file from version.h.in template ++# ++for component in ${COMPONENTS[*]} ++do ++ # Get relative path of component from current dir ++ tmp="COMPONENT_DIR_$component" ++ eval rel_path=\$$tmp ++ ++ # Get query path for component ++ tmp="COMPONENT_QUERY_$component" ++ eval query_path=\$$tmp ++ ++ if [ ! -d "$rel_path" ]; then ++ continue ++ fi ++ ++ if [ "$query_path" != "" ]; then ++ abs_path=$(echo $query_path | sed -e "s%\.\.%src%g") ++ else ++ abs_path=$(echo $rel_path | sed -e "s%\.\.%src%g") ++ fi ++ ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG $abs_path" ++ ++ tag=$(python $GETCOMPVER_PATH $MERGERLOG $abs_path 2> $NULL | sed -e 's/[[:space:]]*//g') ++ ++ template=$rel_path/version.h.in ++ verfile=$rel_path/${component}_version.h ++ ++ if [ "$ACTION" == "clean" ]; then ++ rm -fv $verfile ++ continue ++ fi ++ ++ # MKCOMPVER always has defaults if tag isn't set correctly ++ if [ ! -f "$verfile" -o "$FORCE" != "" ]; then ++ echo "" ++ echo ">>> Generate $abs_path/${component}_version.h from $tag" ++ ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: bash $MKCOMPVER $template $verfile $tag" ++ ++ bash $MKCOMPVER $template $verfile $tag ++ fi ++done +diff --git a/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h b/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h +new file mode 100755 +index 0000000..a44e08b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch new file mode 100644 index 00000000..6e84f000 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch @@ -0,0 +1,82 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: $ ++ */ ++ ++#ifndef _CTF_CFG_H_ ++#define _CTF_CFG_H_ ++ ++#define NETLINK_CTF 20 ++ ++#define SUCCESS 0 ++#define FAILURE -1 ++ ++#define CTFCFG_MAX_SIZE sizeof(ctf_cfg_request_t) ++#define CTFCFG_MAX_ARG_SIZE 1024 ++ ++#define CTFCFG_CMD_SUSPEND 1 ++#define CTFCFG_CMD_RESUME 2 ++#define CTFCFG_CMD_TUPLE_VALID 3 ++#define CTFCFG_CMD_DEFAULT_FWD_GET 4 ++#define CTFCFG_CMD_DEFAULT_FWD_SET 5 ++ ++#define CTFCFG_STATUS_SUCCESS 1 ++#define CTFCFG_STATUS_FAILURE 2 ++#define CTFCFG_STATUS_TUPLE_INVALID 3 ++#define CTFCFG_STATUS_FLOW_ALREADY_SUSPENDED 4 ++#define CTFCFG_STATUS_FLOW_NOT_SUSPENDED 5 ++#define CTFCFG_STATUS_DEFAULT_FWD_INVALID 6 ++#define CTFCFG_STATUS_PROTOCOL_NOT_SUPPORTED 7 ++ ++typedef union ++{ ++ struct in_addr ip_v4; ++ struct in6_addr ip_v6; ++} ip_address_t; ++ ++typedef struct ++{ ++ int family; ++ ++ ip_address_t src_addr; ++ ip_address_t dst_addr; ++ ++ uint16_t src_port; ++ uint16_t dst_port; ++ ++ uint8_t protocol; ++} ctf_tuple_t; ++ ++typedef enum { ++ CTF_FWD_FASTPATH, ++ CTF_FWD_HOST, /* i.e. send to network stack */ ++} ctf_fwd_t; ++ ++typedef struct ctf_cfg_request ++{ ++ uint32_t command_id; ++ uint32_t status; /* Command status */ ++ uint32_t size; /* Size of the argument */ ++ uint8_t arg[CTFCFG_MAX_ARG_SIZE]; ++} ctf_cfg_request_t; ++ ++#endif /* _CTF_CFG_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h b/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h +new file mode 100755 +index 0000000..e4385dd diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch new file mode 100644 index 00000000..a08289ba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch @@ -0,0 +1,305 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h +@@ -0,0 +1,299 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: hndctf.h 418247 2013-08-14 11:16:42Z $ ++ */ ++ ++#ifndef _HNDCTF_H_ ++#define _HNDCTF_H_ ++ ++#include ++#include ++#include ++#include ++/* ++ * Define to enable couting VLAN tx and rx packets and bytes. This could be ++ * disabled if the functionality has impact on performance. ++ */ ++#define CTFVLSTATS ++ ++#define CTF_ENAB(ci) (((ci) != NULL) && (ci)->_ctf) ++ ++#define CTF_ACTION_TAG (1 << 0) ++#define CTF_ACTION_UNTAG (1 << 1) ++#define CTF_ACTION_SNAT (1 << 2) ++#define CTF_ACTION_DNAT (1 << 3) ++#define CTF_ACTION_SUSPEND (1 << 4) ++#define CTF_ACTION_TOS (1 << 5) ++#define CTF_ACTION_MARK (1 << 6) ++#define CTF_ACTION_BYTECNT (1 << 7) ++#define CTF_ACTION_PPPOE_ADD (1 << 8) ++#define CTF_ACTION_PPPOE_DEL (1 << 9) ++ ++#define CTF_SUSPEND_TCP (1 << 0) ++#define CTF_SUSPEND_UDP (1 << 1) ++ ++#define ctf_attach(osh, n, m, c, a) \ ++ (ctf_attach_fn ? ctf_attach_fn(osh, n, m, c, a) : NULL) ++#define ctf_forward(ci, p, d) (ci)->fn.forward(ci, p, d) ++#define ctf_isenabled(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isenabled(ci, d) : FALSE) ++#define ctf_isbridge(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isbridge(ci, d) : FALSE) ++#define ctf_enable(ci, d, e, b) (CTF_ENAB(ci) ? (ci)->fn.enable(ci, d, e, b) : BCME_OK) ++#define ctf_brc_add(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_add(ci, b) : BCME_OK) ++#define ctf_brc_delete(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_delete(ci, e) : BCME_OK) ++#define ctf_brc_update(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_update(ci, b) : BCME_OK) ++#define ctf_brc_lkup(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_lkup(ci, e) : NULL) ++#define ctf_brc_release(ci, b) do { if (CTF_ENAB(ci)) (ci)->fn.brc_release(ci, b); } while (0) ++#define ctf_ipc_add(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.ipc_add(ci, i, v6) : BCME_OK) ++#define ctf_ipc_delete(ci, i, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete(ci, i, v6) : BCME_OK) ++#define ctf_ipc_count_get(ci, i) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_count_get(ci, i) : BCME_OK) ++#define ctf_ipc_delete_multi(ci, i, im, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_multi(ci, i, im, v6) : BCME_OK) ++#define ctf_ipc_delete_range(ci, s, e, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_range(ci, s, e, v6) : BCME_OK) ++#define ctf_ipc_action(ci, s, e, am, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_action(ci, s, e, am, v6) : BCME_OK) ++#define ctf_ipc_lkup(ci, i, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_lkup(ci, i, v6) : NULL) ++#ifdef CTF_IPV6 ++#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (CTF_ENAB(ci) && (ci)->fn.ipc_lkup_l4proto? \ ++ (ci)->fn.ipc_lkup_l4proto((uint8 *)iph, l4p) : NULL) ++#else ++#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (NULL) ++#endif /* CTF_IPV6 */ ++#define ctf_ipc_release(ci, i) do { if (CTF_ENAB(ci)) (ci)->fn.ipc_release(ci, i); } while (0) ++#define ctf_dev_register(ci, d, b) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_register(ci, d, b) : BCME_OK) ++#define ctf_dev_vlan_add(ci, d, vid, vd) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_add(ci, d, vid, vd) : BCME_OK) ++#define ctf_dev_vlan_delete(ci, d, vid) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_delete(ci, d, vid) : BCME_OK) ++#define ctf_detach(ci) if (CTF_ENAB(ci)) (ci)->fn.detach(ci) ++#define ctf_dump(ci, b) if (CTF_ENAB(ci)) (ci)->fn.dump(ci, b) ++#define ctf_cfg_req_process(ci, c) if (CTF_ENAB(ci)) (ci)->fn.cfg_req_process(ci, c) ++#define ctf_dev_unregister(ci, d) if (CTF_ENAB(ci)) (ci)->fn.dev_unregister(ci, d) ++#ifdef BCMFA ++#define ctf_fa_register(ci, d, i) if (CTF_ENAB(ci)) (ci)->fn.fa_register(ci, d, i) ++#define ctf_live(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.live(ci, i, v6) : FALSE) ++#endif /* BCMFA */ ++ ++#define CTFCNTINCR(s) ((s)++) ++#define CTFCNTADD(s, c) ((s) += (c)) ++ ++#define PPPOE_ETYPE_OFFSET 12 ++#define PPPOE_VER_OFFSET 14 ++#define PPPOE_SESID_OFFSET 16 ++#define PPPOE_LEN_OFFSET 18 ++ ++#define PPPOE_HLEN 20 ++#define PPPOE_PPP_HLEN 8 ++ ++#define PPPOE_PROT_PPP 0x0021 ++#define PPPOE_PROT_PPP_IP6 0x0057 ++ ++ ++typedef struct ctf_pub ctf_t; ++typedef struct ctf_brc ctf_brc_t; ++typedef struct ctf_ipc ctf_ipc_t; ++typedef struct ctf_conn_tuple ctf_conn_tuple_t; ++typedef struct ctf_brc_hot ctf_brc_hot_t; ++ ++typedef void (*ctf_detach_cb_t)(ctf_t *ci, void *arg); ++typedef ctf_t * (*ctf_attach_t)(osl_t *osh, uint8 *name, uint32 *msg_level, ++ ctf_detach_cb_t cb, void *arg); ++typedef void (*ctf_detach_t)(ctf_t *ci); ++typedef int32 (*ctf_forward_t)(ctf_t *ci, void *p, void *rxifp); ++typedef bool (*ctf_isenabled_t)(ctf_t *ci, void *dev); ++typedef bool (*ctf_isbridge_t)(ctf_t *ci, void *dev); ++typedef int32 (*ctf_brc_add_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef int32 (*ctf_brc_delete_t)(ctf_t *ci, uint8 *ea); ++typedef int32 (*ctf_brc_update_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef ctf_brc_t * (*ctf_brc_lkup_t)(ctf_t *ci, uint8 *da); ++typedef void (*ctf_brc_release_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef int32 (*ctf_ipc_add_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef int32 (*ctf_ipc_delete_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef int32 (*ctf_ipc_count_get_t)(ctf_t *ci); ++typedef int32 (*ctf_ipc_delete_multi_t)(ctf_t *ci, ctf_ipc_t *ipc, ++ ctf_ipc_t *ipcm, bool v6); ++typedef int32 (*ctf_ipc_delete_range_t)(ctf_t *ci, ctf_ipc_t *start, ++ ctf_ipc_t *end, bool v6); ++typedef int32 (*ctf_ipc_action_t)(ctf_t *ci, ctf_ipc_t *start, ++ ctf_ipc_t *end, uint32 action_mask, bool v6); ++typedef ctf_ipc_t * (*ctf_ipc_lkup_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef uint8 * (*ctf_ipc_lkup_l4proto_t)(uint8 *iph, uint8 *proto_num); ++typedef void (*ctf_ipc_release_t)(ctf_t *ci, ctf_ipc_t *ipc); ++typedef int32 (*ctf_enable_t)(ctf_t *ci, void *dev, bool enable, ctf_brc_hot_t **brc_hot); ++typedef int32 (*ctf_dev_register_t)(ctf_t *ci, void *dev, bool br); ++typedef void (*ctf_dev_unregister_t)(ctf_t *ci, void *dev); ++typedef int32 (*ctf_dev_vlan_add_t)(ctf_t *ci, void *dev, uint16 vid, void *vldev); ++typedef int32 (*ctf_dev_vlan_delete_t)(ctf_t *ci, void *dev, uint16 vid); ++typedef void (*ctf_dump_t)(ctf_t *ci, struct bcmstrbuf *b); ++typedef void (*ctf_cfg_req_process_t)(ctf_t *ci, void *arg); ++#ifdef BCMFA ++typedef int (*ctf_fa_cb_t)(void *dev, ctf_ipc_t *ipc, bool v6, int cmd); ++ ++typedef int32 (*ctf_fa_register_t)(ctf_t *ci, ctf_fa_cb_t facb, void *fa); ++typedef void (*ctf_live_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++#endif /* BCMFA */ ++ ++struct ctf_brc_hot { ++ struct ether_addr ea; /* Dest address */ ++ ctf_brc_t *brcp; /* BRC entry corresp to dest mac */ ++}; ++ ++typedef struct ctf_fn { ++ ctf_detach_t detach; ++ ctf_forward_t forward; ++ ctf_isenabled_t isenabled; ++ ctf_isbridge_t isbridge; ++ ctf_brc_add_t brc_add; ++ ctf_brc_delete_t brc_delete; ++ ctf_brc_update_t brc_update; ++ ctf_brc_lkup_t brc_lkup; ++ ctf_brc_release_t brc_release; ++ ctf_ipc_add_t ipc_add; ++ ctf_ipc_delete_t ipc_delete; ++ ctf_ipc_count_get_t ipc_count_get; ++ ctf_ipc_delete_multi_t ipc_delete_multi; ++ ctf_ipc_delete_range_t ipc_delete_range; ++ ctf_ipc_action_t ipc_action; ++ ctf_ipc_lkup_t ipc_lkup; ++ ctf_ipc_lkup_l4proto_t ipc_lkup_l4proto; ++ ctf_ipc_release_t ipc_release; ++ ctf_enable_t enable; ++ ctf_dev_register_t dev_register; ++ ctf_dev_unregister_t dev_unregister; ++ ctf_detach_cb_t detach_cb; ++ void *detach_cb_arg; ++ ctf_dev_vlan_add_t dev_vlan_add; ++ ctf_dev_vlan_delete_t dev_vlan_delete; ++ ctf_dump_t dump; ++ ctf_cfg_req_process_t cfg_req_process; ++#ifdef BCMFA ++ ctf_fa_register_t fa_register; ++ ctf_live_t live; ++#endif /* BCMFA */ ++} ctf_fn_t; ++ ++struct ctf_pub { ++ bool _ctf; /* Global CTF enable/disable */ ++ ctf_fn_t fn; /* Exported functions */ ++ void *nl_sk; /* Netlink socket */ ++ uint32 ipc_suspend; /* Global IPC suspend flags */ ++}; ++ ++struct ctf_mark; /* Connection Mark */ ++ ++struct ctf_brc { ++ struct ctf_brc *next; /* Pointer to brc entry */ ++ struct ether_addr dhost; /* MAC addr of host */ ++ uint16 vid; /* VLAN id to use on txif */ ++ void *txifp; /* Interface connected to host */ ++ uint32 action; /* Tag or untag the frames */ ++ uint32 live; /* Counter used to expire the entry */ ++ uint32 hits; /* Num frames matching brc entry */ ++ uint64 *bytecnt_ptr; /* Pointer to the byte counter */ ++}; ++ ++#ifdef CTF_IPV6 ++#define IPADDR_U32_SZ (IPV6_ADDR_LEN / sizeof(uint32)) ++#else ++#define IPADDR_U32_SZ 1 ++#endif ++ ++struct ctf_conn_tuple { ++ uint32 sip[IPADDR_U32_SZ], dip[IPADDR_U32_SZ]; ++ uint16 sp, dp; ++ uint8 proto; ++}; ++ ++typedef struct ctf_nat { ++ uint32 ip; ++ uint16 port; ++} ctf_nat_t; ++ ++#ifdef BCMFA ++#define CTF_FA_PEND_ADD_ENTRY 0x1 ++#define CTF_FA_ADD_ISPEND(ipc) ((ipc)->flags & CTF_FA_PEND_ADD_ENTRY) ++#define CTF_FA_SET_ADD_PEND(ipc) ((ipc)->flags |= CTF_FA_PEND_ADD_ENTRY) ++#define CTF_FA_CLR_ADD_PEND(ipc) ((ipc)->flags &= ~(CTF_FA_PEND_ADD_ENTRY)) ++#endif /* BCMFA */ ++ ++struct ctf_ipc { ++ struct ctf_ipc *next; /* Pointer to ipc entry */ ++ ctf_conn_tuple_t tuple; /* Tuple to uniquely id the flow */ ++ uint16 vid; /* VLAN id to use on txif */ ++ struct ether_addr dhost; /* Destination MAC address */ ++ struct ether_addr shost; /* Source MAC address */ ++ void *txif; /* Target interface to send */ ++ uint32 action; /* NAT and/or VLAN actions */ ++ ctf_brc_t *brcp; /* BRC entry corresp to source mac */ ++ uint32 live; /* Counter used to expire the entry */ ++ struct ctf_nat nat; /* Manip data for SNAT, DNAT */ ++ struct ether_addr sa; /* MAC address of sender */ ++ uint8 tos; /* IPv4 tos or IPv6 traff class excl ECN */ ++ uint16 pppoe_sid; /* PPPOE session to use */ ++ void *ppp_ifp; /* PPP interface handle */ ++ uint32 hits; /* Num frames matching ipc entry */ ++ uint64 *bytecnt_ptr; /* Pointer to the byte counter */ ++ struct ctf_mark mark; /* Mark value to use for the connection */ ++#ifdef BCMFA ++ void *rxif; /* Receive interface */ ++ void *pkt; /* Received packet */ ++ uint8 flags; /* Flags for multiple purpose */ ++#endif /* BCMFA */ ++}; ++ ++extern ctf_t *ctf_kattach(osl_t *osh, uint8 *name); ++extern void ctf_kdetach(ctf_t *kci); ++extern ctf_attach_t ctf_attach_fn; ++extern ctf_t *_ctf_attach(osl_t *osh, uint8 *name, uint32 *msg_level, ++ ctf_detach_cb_t cb, void *arg); ++extern ctf_t *kcih; ++ ++/* Hot bridge cache lkup */ ++#define MAXBRCHOT 4 ++#define MAXBRCHOTIF 4 ++#define CTF_BRC_HOT_HASH(da) ((((uint8 *)da)[4] ^ ((uint8 *)da)[5]) & (MAXBRCHOT - 1)) ++#define CTF_HOTBRC_CMP(hbrc, da, rxifp) \ ++({ \ ++ ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(da); \ ++ ((eacmp((bh)->ea.octet, (da)) == 0) && (bh->brcp->txifp != (rxifp))); \ ++}) ++ ++/* Header prep for packets matching hot bridge cache entry */ ++#define CTF_HOTBRC_L2HDR_PREP(osh, hbrc, prio, data, p) \ ++do { \ ++ uint8 *l2h; \ ++ ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(data); \ ++ ASSERT(*(uint16 *)((data) + VLAN_TPID_OFFSET) == HTON16(ETHER_TYPE_8021Q)); \ ++ if (bh->brcp->action & CTF_ACTION_UNTAG) { \ ++ /* Remove vlan header */ \ ++ l2h = PKTPULL((osh), (p), VLAN_TAG_LEN); \ ++ ether_rcopy(l2h - VLAN_TAG_LEN + ETHER_ADDR_LEN, \ ++ l2h + ETHER_ADDR_LEN); \ ++ ether_rcopy(l2h - VLAN_TAG_LEN, l2h); \ ++ } else { \ ++ /* Update vlan header */ \ ++ l2h = (data); \ ++ *(uint16 *)(l2h + VLAN_TCI_OFFSET) = \ ++ HTON16((prio) << VLAN_PRI_SHIFT | bh->brcp->vid); \ ++ } \ ++} while (0) ++ ++ ++#endif /* _HNDCTF_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.h b/drivers/bcmdrivers/gmac/src/include/epivers.h +new file mode 100644 +index 0000000..6b067dd diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch new file mode 100644 index 00000000..ecdecc3d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch @@ -0,0 +1,52 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.h.in +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ ++ * ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION @EPI_MAJOR_VERSION@ ++ ++#define EPI_MINOR_VERSION @EPI_MINOR_VERSION@ ++ ++#define EPI_RC_NUMBER @EPI_RC_NUMBER@ ++ ++#define EPI_INCREMENTAL_NUMBER @EPI_INCREMENTAL_NUMBER@ ++ ++#define EPI_BUILD_NUMBER @EPI_BUILD_NUMBER@ ++ ++#define EPI_VERSION @EPI_VERSION@ ++ ++#define EPI_VERSION_NUM @EPI_VERSION_NUM@ ++ ++#define EPI_VERSION_DEV @EPI_VERSION_DEV@ ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef WLTEST ++#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@ WLTEST)" ++#else ++#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@)" ++#endif ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.sh b/drivers/bcmdrivers/gmac/src/include/epivers.sh +new file mode 100755 +index 0000000..4424501 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch new file mode 100644 index 00000000..846b3b68 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.h.patch @@ -0,0 +1,51 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION 6 ++ ++#define EPI_MINOR_VERSION 30 ++ ++#define EPI_RC_NUMBER 40 ++ ++#define EPI_INCREMENTAL_NUMBER 0 ++ ++#define EPI_BUILD_NUMBER 2 ++ ++#define EPI_VERSION 6, 30, 40, 0 ++ ++#define EPI_VERSION_NUM 0x061e2800 ++ ++#define EPI_VERSION_DEV 6.30.40 ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef WLTEST ++#define EPI_VERSION_STR "6.30.40 (TOB) (r WLTEST)" ++#else ++#define EPI_VERSION_STR "6.30.40 (TOB) (r)" ++#endif ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.h.in b/drivers/bcmdrivers/gmac/src/include/epivers.h.in +new file mode 100755 +index 0000000..790f8d4 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch new file mode 100644 index 00000000..56fbd0d4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_epivers.sh.patch @@ -0,0 +1,301 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.sh +@@ -0,0 +1,295 @@ ++#! /bin/bash ++# ++# Create the epivers.h file from epivers.h.in ++# ++# Epivers.h generation mechanism supports svn based checkouts ++# ++# $Id: epivers.sh 299409 2011-11-30 00:52:43Z $ ++# ++# GetCompVer.py return value and action needed ++# i. trunk => use current date as version string ++# ii. local => use SVNURL expanded by HeadURL keyword ++# iii. => use it as as is ++# (some components can override and say give me native ver) ++# iv. empty => ++# a) If TAG is specified use it ++# a) If no TAG is specified use date ++# ++ ++# If the version header file already exists, increment its build number. ++# Otherwise, create a new file. ++if [ -f epivers.h ]; then ++ ++ # If REUSE_VERSION is set, epivers iteration is not incremented ++ # This can be used precommit and continuous integration projects ++ if [ -n "$REUSE_VERSION" ]; then ++ echo "Previous epivers.h exists. Skipping version increment" ++ exit 0 ++ fi ++ ++ build=`grep EPI_BUILD_NUMBER epivers.h | sed -e "s,.*BUILD_NUMBER[ ]*,,"` ++ build=`expr ${build} + 1` ++ echo build=${build} ++ sed -e "s,.*_BUILD_NUMBER.*,#define EPI_BUILD_NUMBER ${build}," \ ++ < epivers.h > epivers.h.new ++ mv epivers.h epivers.h.prev ++ mv epivers.h.new epivers.h ++ exit 0 ++ ++else # epivers.h doesn't exist ++ ++ NULL="/dev/null" ++ svncmd="svn --non-interactive" ++ ++ # Check for the in file, if not there we're in the wrong directory ++ if [ ! -f epivers.h.in ]; then ++ echo "ERROR: No epivers.h.in found" ++ exit 1 ++ fi ++ ++ # Following SVNURL should be expanded on checkout ++ SVNURL='$HeadURL: http://svn.sj.broadcom.com/svn/wlansvn/users/kenlo/northstar/AARDVARK_TWIG_6_30_40/src/include/epivers.sh $' ++ ++ # If SVNURL isn't expanded, extract it from svn info ++ if echo "$SVNURL" | grep -vq '$.*HeadURL.*epivers.sh.*$'; then ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: SVN URL wasn't expanded. Getting it from svn info" ++ SVNURL=$($svncmd info epivers.sh 2> $NULL | egrep "^URL:") ++ fi ++ ++ if echo "${TAG}" | grep -q "_BRANCH_\|_TWIG_"; then ++ branchtag=$TAG ++ else ++ branchtag="" ++ fi ++ ++ # If this is a tagged build, use the tag to supply the numbers ++ # Tag should be in the form ++ # _REL__ ++ # or ++ # _REL___RC ++ # or ++ # _REL___RC_ ++ ++ SRCBASE=.. ++ MERGERLOG=${SRCBASE}/../merger_sources.log ++ GETCOMPVER=getcompver.py ++ GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER ++ GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} ++ ++ # ++ # If there is a local copy GETCOMPVER use it ahead of network copy ++ # ++ if [ -s "$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER" ++ elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" ++ elif [ -s "$GETCOMPVER_NET" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET" ++ elif [ -s "$GETCOMPVER_NET_WIN" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" ++ fi ++ ++ # ++ # If $GETCOMPVER isn't found, fetch it from SVN ++ # (this should be very rare) ++ # ++ if [ ! -s "$GETCOMPVER_PATH" ]; then ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: Fetching $GETCOMPVER from trunk" ++ ++ $svncmd export -q \ ++ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ ++ ${GETCOMPVER} 2> $NULL ++ ++ GETCOMPVER_PATH=$GETCOMPVER ++ fi ++ ++ # Now get tag for src/include from automerger log ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG src/include" ++ ++ COMPTAG=$(python $GETCOMPVER_PATH $MERGERLOG src/include 2> $NULL | sed -e 's/[[:space:]]*//g') ++ ++ echo "DBG: Component Tag String Derived = $COMPTAG" ++ ++ # Process COMPTAG values ++ # Rule: ++ # If trunk is returned, use date as component tag ++ # If LOCAL_COMPONENT is returned, use SVN URL to get native tag ++ # If component is returned or empty, assign it to SVNTAG ++ # GetCompVer.py return value and action needed ++ # i. trunk => use current date as version string ++ # ii. local => use SVNURL expanded by HeadURL keyword ++ # iii. => use it as as is ++ # iv. empty => ++ # a) If TAG is specified use it ++ # a) If no TAG is specified use SVNURL from HeadURL ++ ++ SVNURL_VER=false ++ ++ if [ "$COMPTAG" == "" ]; then ++ SVNURL_VER=true ++ elif [ "$COMPTAG" == "LOCAL_COMPONENT" ]; then ++ SVNURL_VER=true ++ elif [ "$COMPTAG" == "trunk" ]; then ++ SVNTAG=$(date '+TRUNKCOMP_REL_%Y_%m_%d') ++ else ++ SVNTAG=$COMPTAG ++ fi ++ ++ # Given SVNURL path conventions or naming conventions, derive SVNTAG ++ # TO-DO: SVNTAG derivation logic can move to a central common API ++ # TO-DO: ${SRCBASE}/tools/build/svnurl2tag.sh ++ if [ "$SVNURL_VER" == "true" ]; then ++ case "${SVNURL}" in ++ */branches/*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%.*/branches/\(.*\)/src.*%\1%g' | xargs printf "%s") ++ ;; ++ *_BRANCH_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _BRANCH_ | xargs printf "%s") ++ ;; ++ *_TWIG_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _TWIG_ | xargs printf "%s") ++ ;; ++ */tags/*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%.*/tags/.*/\(.*\)/src.*%\1%g' | xargs printf "%s") ++ ;; ++ *_REL_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _REL_ | xargs printf "%s") ++ ;; ++ */trunk/*) ++ SVNTAG=$(date '+TRUNKURL_REL_%Y_%m_%d') ++ ;; ++ *) ++ SVNTAG=$(date '+OTHER_REL_%Y_%m_%d') ++ ;; ++ esac ++ echo "DBG: Native Tag String Derived from URL: $SVNTAG" ++ else ++ echo "DBG: Native Tag String Derived: $SVNTAG" ++ fi ++ ++ TAG=${SVNTAG} ++ ++ # Normalize the branch name portion to "D11" in case it has underscores in it ++ branch_name=`expr match "$TAG" '\(.*\)_\(BRANCH\|TWIG\|REL\)_.*'` ++ TAG=`echo $TAG | sed -e "s%^$branch_name%D11%"` ++ ++ # Split the tag into an array on underbar or whitespace boundaries. ++ IFS="_ " tag=(${TAG}) ++ unset IFS ++ ++ tagged=1 ++ if [ ${#tag[*]} -eq 0 ]; then ++ tag=(`date '+TOT REL %Y %m %d 0 %y'`); ++ # reconstruct a TAG from the date ++ TAG=${tag[0]}_${tag[1]}_${tag[2]}_${tag[3]}_${tag[4]}_${tag[5]} ++ tagged=0 ++ fi ++ ++ # Allow environment variable to override values. ++ # Missing values default to 0 ++ # ++ maj=${EPI_MAJOR_VERSION:-${tag[2]:-0}} ++ min=${EPI_MINOR_VERSION:-${tag[3]:-0}} ++ rcnum=${EPI_RC_NUMBER:-${tag[4]:-0}} ++ ++ # If increment field is 0, set it to date suffix if on TOB ++ if [ -n "$branchtag" ]; then ++ [ "${tag[5]:-0}" -eq 0 ] && echo "Using date suffix for incr" ++ today=`date '+%Y%m%d'` ++ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-${today:-0}}} ++ else ++ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} ++ fi ++ origincr=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} ++ build=${EPI_BUILD_NUMBER:-0} ++ ++ # Strip 'RC' from front of rcnum if present ++ rcnum=${rcnum/#RC/} ++ ++ # strip leading zero off the number (otherwise they look like octal) ++ maj=${maj/#0/} ++ min=${min/#0/} ++ rcnum=${rcnum/#0/} ++ incremental=${incremental/#0/} ++ origincr=${origincr/#0/} ++ build=${build/#0/} ++ ++ # some numbers may now be null. replace with with zero. ++ maj=${maj:-0} ++ min=${min:-0} ++ ++ rcnum=${rcnum:-0} ++ incremental=${incremental:-0} ++ origincr=${origincr:-0} ++ build=${build:-0} ++ ++ if [ ${tagged} -eq 1 ]; then ++ # vernum is 32chars max ++ vernum=`printf "0x%02x%02x%02x%02x" ${maj} ${min} ${rcnum} ${origincr}` ++ else ++ vernum=`printf "0x00%02x%02x%02x" ${tag[7]} ${min} ${rcnum}` ++ fi ++ ++ # make sure the size of vernum is under 32 bits. ++ # Otherwise, truncate. The string will keep full information. ++ vernum=${vernum:0:10} ++ ++ # build the string directly from the tag, irrespective of its length ++ # remove the name , the tag type, then replace all _ by . ++ tag_ver_str=${TAG/${tag[0]}_} ++ tag_ver_str=${tag_ver_str/${tag[1]}_} ++ tag_ver_str=${tag_ver_str//_/.} ++ ++ # record tag type ++ tagtype= ++ ++ if [ "${tag[1]}" = "BRANCH" -o "${tag[1]}" = "TWIG" ]; then ++ tagtype=" (TOB)" ++ echo "tag type: $tagtype" ++ fi ++ ++ echo "Effective version string: $tag_ver_str" ++ ++ if [ "$(uname -s)" == "Darwin" ]; then ++ # Mac does not like 2-digit numbers so convert the number to single ++ # digit. 5.100 becomes 5.1 ++ if [ $min -gt 99 ]; then ++ minmac=`expr $min / 100` ++ else ++ minmac=$min ++ fi ++ epi_ver_dev="${maj}.${minmac}.0" ++ else ++ epi_ver_dev="${maj}.${min}.${rcnum}" ++ fi ++ ++ # Finally get version control revision number of (if any) ++ vc_version_num=$($svncmd info ${SRCBASE} 2> $NULL | awk -F': ' '/^Revision: /{printf "%s", $2}') ++ ++ # OK, go do it ++ echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}" ++ ++ sed \ ++ -e "s;@EPI_MAJOR_VERSION@;${maj};" \ ++ -e "s;@EPI_MINOR_VERSION@;${min};" \ ++ -e "s;@EPI_RC_NUMBER@;${rcnum};" \ ++ -e "s;@EPI_INCREMENTAL_NUMBER@;${incremental};" \ ++ -e "s;@EPI_BUILD_NUMBER@;${build};" \ ++ -e "s;@EPI_VERSION@;${maj}, ${min}, ${rcnum}, ${incremental};" \ ++ -e "s;@EPI_VERSION_STR@;${tag_ver_str};" \ ++ -e "s;@EPI_VERSION_TYPE@;${tagtype};" \ ++ -e "s;@VERSION_TYPE@;${tagtype};" \ ++ -e "s;@EPI_VERSION_NUM@;${vernum};" \ ++ -e "s;@EPI_VERSION_DEV@;${epi_ver_dev};" \ ++ -e "s;@VC_VERSION_NUM@;r${vc_version_num};" \ ++ < epivers.h.in > epivers.h ++ ++ # In shared workspaces across different platforms, ensure that ++ # windows generated file is made platform neutral without CRLF ++ if uname -s | egrep -i -q "cygwin"; then ++ dos2unix epivers.h > $NULL 2>&1 ++ fi ++fi # epivers.h +diff --git a/drivers/bcmdrivers/gmac/src/include/etioctl.h b/drivers/bcmdrivers/gmac/src/include/etioctl.h +new file mode 100755 +index 0000000..2fbddf9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch new file mode 100644 index 00000000..cac11272 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_etioctl.h.patch @@ -0,0 +1,164 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/etioctl.h +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM44XX Ethernet Windows device driver custom OID definitions. ++ * ++ * $Id: etioctl.h 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#ifndef _etioctl_h_ ++#define _etioctl_h_ ++ ++/* ++ * Minor kludge alert: ++ * Duplicate a few definitions that irelay requires from epiioctl.h here ++ * so caller doesn't have to include this file and epiioctl.h . ++ * If this grows any more, it would be time to move these irelay-specific ++ * definitions out of the epiioctl.h and into a separate driver common file. ++ */ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* common ioctl definitions */ ++#define ETCUP 0 ++#define ETCDOWN 1 ++#define ETCLOOP 2 ++#define ETCDUMP 3 ++#define ETCSETMSGLEVEL 4 ++#define ETCPROMISC 5 ++#define ETCVAR 6 ++#define ETCSPEED 7 ++#define ETCPHYRD 9 ++#define ETCPHYWR 10 ++#define ETCQOS 11 ++#define ETCPHYRD2 12 ++#define ETCPHYWR2 13 ++#define ETCROBORD 14 ++#define ETCROBOWR 15 ++ ++/* ++ * A set of iovars defined for ET set/get ++ */ ++#define IOV_ET_POWER_SAVE_MODE 1 ++#define IOV_ET_CLEAR_DUMP 2 ++#define IOV_ET_ROBO_DEVID 3 ++#define IOV_PKTC 4 ++#define IOV_PKTCBND 5 ++#define IOV_COUNTERS 6 ++#define IOV_DUMP_CTF 7 ++ ++#if defined(linux) || defined(__ECOS) ++#define SIOCSETCUP (SIOCDEVPRIVATE + ETCUP) ++#define SIOCSETCDOWN (SIOCDEVPRIVATE + ETCDOWN) ++#define SIOCSETCLOOP (SIOCDEVPRIVATE + ETCLOOP) ++#define SIOCGETCDUMP (SIOCDEVPRIVATE + ETCDUMP) ++#define SIOCSETCSETMSGLEVEL (SIOCDEVPRIVATE + ETCSETMSGLEVEL) ++#define SIOCSETCPROMISC (SIOCDEVPRIVATE + ETCPROMISC) ++#define SIOCSETGETVAR (SIOCDEVPRIVATE + ETCVAR) ++#define SIOCSETCSPEED (SIOCDEVPRIVATE + ETCSPEED) ++#define SIOCTXGEN (SIOCDEVPRIVATE + 8) ++#define SIOCGETCPHYRD (SIOCDEVPRIVATE + ETCPHYRD) ++#define SIOCSETCPHYWR (SIOCDEVPRIVATE + ETCPHYWR) ++#define SIOCSETCQOS (SIOCDEVPRIVATE + ETCQOS) ++#define SIOCGETCPHYRD2 (SIOCDEVPRIVATE + ETCPHYRD2) ++#define SIOCSETCPHYWR2 (SIOCDEVPRIVATE + ETCPHYWR2) ++#define SIOCGETCROBORD (SIOCDEVPRIVATE + ETCROBORD) ++#define SIOCSETCROBOWR (SIOCDEVPRIVATE + ETCROBOWR) ++ ++/* structure to send a generic var set/get */ ++typedef struct et_var_s { ++ uint cmd; ++ uint set; ++ void *buf; ++ uint len; ++} et_var_t; ++ ++/* arg to SIOCTXGEN */ ++struct txg { ++ uint32 num; /* number of frames to send */ ++ uint32 delay; /* delay in microseconds between sending each */ ++ uint32 size; /* size of ether frame to send */ ++ uchar buf[1514]; /* starting ether frame data */ ++}; ++#endif /* linux */ ++ ++ ++#if defined(__NetBSD__) ++#define SIOCSETCUP _IOW('e', 0, struct ifreq) ++#define SIOCSETCDOWN _IOW('e', 1, struct ifreq) ++#define SIOCSETCLOOP _IOW('e', 2, struct ifreq) ++#define SIOCGETCDUMP _IOWR('e', 3, struct ifreq) ++#define SIOCSETCSETMSGLEVEL _IOW('e', 4, struct ifreq) ++#define SIOCSETCPROMISC _IOW('e', 5, struct ifreq) ++#define SIOCSETCTXDOWN _IOW('e', 6, struct ifreq) /* obsolete */ ++#define SIOCSETCSPEED _IOW('e', 7, struct ifreq) ++#define SIOCTXGEN _IOW('e', 8, struct ifreq) ++#define SIOCGETCPHYRD _IOWR('e', 9, struct ifreq) ++#define SIOCSETCPHYWR _IOW('e', 10, struct ifreq) ++#define SIOCSETCQOS _IOW('e', 11, struct ifreq) ++#define SIOCGETCPHYRD2 _IOWR('e', 12, struct ifreq) ++#define SIOCSETCPHYWR2 _IOW('e', 13, struct ifreq) ++#define SIOCGETCROBORD _IOWR('e', 14, struct ifreq) ++#define SIOCSETCROBOWR _IOW('e', 15, struct ifreq) ++ ++/* arg to SIOCTXGEN */ ++struct txg { ++ uint32 num; /* number of frames to send */ ++ uint32 delay; /* delay in microseconds between sending each */ ++ uint32 size; /* size of ether frame to send */ ++ uchar buf[1514]; /* starting ether frame data */ ++}; ++#endif /* __NetBSD__ */ ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++#define ET_OID_BASE 0xFFE41400 /* OID Base for ET */ ++ ++#define OID_ET_UP (ET_OID_BASE + ETCUP) ++#define OID_ET_DOWN (ET_OID_BASE + ETCDOWN) ++#define OID_ET_LOOP (ET_OID_BASE + ETCLOOP) ++#define OID_ET_DUMP (ET_OID_BASE + ETCDUMP) ++#define OID_ET_SETMSGLEVEL (ET_OID_BASE + ETCSETMSGLEVEL) ++#define OID_ET_PROMISC (ET_OID_BASE + ETCPROMISC) ++#define OID_ET_TXDOWN (ET_OID_BASE + 6) ++#define OID_ET_SPEED (ET_OID_BASE + ETCSPEED) ++#define OID_ET_GETINSTANCE (ET_OID_BASE + 8) ++#define OID_ET_SETCALLBACK (ET_OID_BASE + 9) ++#define OID_ET_UNSETCALLBACK (ET_OID_BASE + 10) ++ ++#define IS_ET_OID(oid) (((oid) & 0xFFFFFF00) == 0xFFE41400) ++ ++#define ET_ISQUERYOID(oid) ((oid == OID_ET_DUMP) || (oid == OID_ET_GETINSTANCE)) ++ ++/* OID_ET_SETCALLBACK data type */ ++typedef struct et_cb { ++ void (*fn)(void *, int); /* Callback function */ ++ void *context; /* Passed to callback function */ ++} et_cb_t; ++ ++#endif /* _etioctl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/gmac_common.h b/drivers/bcmdrivers/gmac/src/include/gmac_common.h +new file mode 100755 +index 0000000..145e587 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch new file mode 100644 index 00000000..71abb6a9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch @@ -0,0 +1,566 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/gmac_common.h +@@ -0,0 +1,560 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * gmacdefs - Broadcom gmac (Unimac) specific definitions ++ * ++ * $Id: gmac_common.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _gmac_common_core_h_ ++#define _gmac_common_core_h_ ++ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD XSTR(__LINE__) ++#endif ++ ++typedef volatile struct _gmac_commonregs { ++ uint32 stag0; ++ uint32 stag1; ++ uint32 stag2; ++ uint32 stag3; ++ uint32 PAD[4]; ++ uint32 parsercontrol; ++ uint32 mib_max_len; ++ uint32 PAD[54]; ++ uint32 phyaccess; ++ uint32 phycontrol; ++ uint32 PAD[2]; ++ uint32 gmac0_rgmii_cntl; ++ uint32 PAD[59]; ++ uint32 cfp_access; ++ uint32 PAD[3]; ++ uint32 cfp_tcam_data0; ++ uint32 cfp_tcam_data1; ++ uint32 cfp_tcam_data2; ++ uint32 cfp_tcam_data3; ++ uint32 cfp_tcam_data4; ++ uint32 cfp_tcam_data5; ++ uint32 cfp_tcam_data6; ++ uint32 cfp_tcam_data7; ++ uint32 cfp_tcam_mask0; ++ uint32 cfp_tcam_mask1; ++ uint32 cfp_tcam_mask2; ++ uint32 cfp_tcam_mask3; ++ uint32 cfp_tcam_mask4; ++ uint32 cfp_tcam_mask5; ++ uint32 cfp_tcam_mask6; ++ uint32 cfp_tcam_mask7; ++ uint32 cfp_action_data; ++ uint32 PAD[19]; ++ uint32 tcam_bist_cntl; ++ uint32 tcam_bist_status; ++ uint32 tcam_cmp_status; ++ uint32 tcam_disable; ++ uint32 PAD[16]; ++ uint32 tcam_test_cntl; ++ uint32 PAD[3]; ++ uint32 udf_0_a3_a0; ++ uint32 udf_0_a7_a4; ++ uint32 udf_0_a8; ++ uint32 PAD[1]; ++ uint32 udf_1_a3_a0; ++ uint32 udf_1_a7_a4; ++ uint32 udf_1_a8; ++ uint32 PAD[1]; ++ uint32 udf_2_a3_a0; ++ uint32 udf_2_a7_a4; ++ uint32 udf_2_a8; ++ uint32 PAD[1]; ++ uint32 udf_0_b3_b0; ++ uint32 udf_0_b7_b4; ++ uint32 udf_0_b8; ++ uint32 PAD[1]; ++ uint32 udf_1_b3_b0; ++ uint32 udf_1_b7_b4; ++ uint32 udf_1_b8; ++ uint32 PAD[1]; ++ uint32 udf_2_b3_b0; ++ uint32 udf_2_b7_b4; ++ uint32 udf_2_b8; ++ uint32 PAD[1]; ++ uint32 udf_0_c3_c0; ++ uint32 udf_0_c7_c4; ++ uint32 udf_0_c8; ++ uint32 PAD[1]; ++ uint32 udf_1_c3_c0; ++ uint32 udf_1_c7_c4; ++ uint32 udf_1_c8; ++ uint32 PAD[1]; ++ uint32 udf_2_c3_c0; ++ uint32 udf_2_c7_c4; ++ uint32 udf_2_c8; ++ uint32 PAD[1]; ++ uint32 udf_0_d3_d0; ++ uint32 udf_0_d7_d4; ++ uint32 udf_0_d11_d8; ++} gmac_commonregs_t; ++ ++/* stag0 offset0x0 */ ++#define STAG0_TPID_SHIFT 0 ++#define STAG0_TPID_MASK 0xffff ++ ++/* stag1 offset0x4 */ ++#define STAG1_TPID_SHIFT 0 ++#define STAG1_TPID_MASK 0xffff ++ ++/* stag2 offset0x8 */ ++#define STAG2_TPID_SHIFT 0 ++#define STAG2_TPID_MASK 0xffff ++ ++/* stag3 offset0xc */ ++#define STAG3_TPID_SHIFT 0 ++#define STAG3_TPID_MASK 0xffff ++ ++/* parsercontrol offset0x20 */ ++#define PARSERCONTROL_MAX_PARSER_LEN_TH_SHIFT 0 ++#define PARSERCONTROL_MAX_PARSER_LEN_TH_MASK 0x3fff ++ ++/* mib_max_len offset0x24 */ ++#define MIB_MAX_LEN_MIB_MAX_LEN_SHIFT 0 ++#define MIB_MAX_LEN_MIB_MAX_LEN_MASK 0x3fff ++ ++/* phyaccess offset0x100 */ ++#define PHYACCESS_TRIGGER_SHIFT 30 ++#define PHYACCESS_TRIGGER_MASK 0x40000000 ++#define PHYACCESS_WR_CMD_SHIFT 29 ++#define PHYACCESS_WR_CMD_MASK 0x20000000 ++#define PHYACCESS_CPU_REG_ADDR_SHIFT 24 ++#define PHYACCESS_CPU_REG_ADDR_MASK 0x1f000000 ++#define PHYACCESS_CPU_PHY_ADDR_SHIFT 16 ++#define PHYACCESS_CPU_PHY_ADDR_MASK 0x1f0000 ++#define PHYACCESS_ACC_DATA_SHIFT 0 ++#define PHYACCESS_ACC_DATA_MASK 0xffff ++ ++/* phycontrol offset0x104 */ ++#define PHYCONTROL_SD_ACCESS_EN_SHIFT 25 ++#define PHYCONTROL_SD_ACCESS_EN_MASK 0x2000000 ++#define PHYCONTROL_NWAY_AUTO_POLLING_EN_SHIFT 24 ++#define PHYCONTROL_NWAY_AUTO_POLLING_EN_MASK 0x1000000 ++#define PHYCONTROL_MDC_TRANSITION_EN_SHIFT 23 ++#define PHYCONTROL_MDC_TRANSITION_EN_MASK 0x800000 ++#define PHYCONTROL_MDC_CYCLE_TH_SHIFT 16 ++#define PHYCONTROL_MDC_CYCLE_TH_MASK 0x7f0000 ++#define PHYCONTROL_EXT_PHY_ADDR_SHIFT 0 ++#define PHYCONTROL_EXT_PHY_ADDR_MASK 0x1f ++ ++/* gmac0_rgmii_cntl offset0x110 */ ++#define GMAC0_RGMII_CNTL_TIMING_SEL_SHIFT 0 ++#define GMAC0_RGMII_CNTL_TIMING_SEL_MASK 0x1 ++#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_SHIFT 1 ++#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_MASK 0x2 ++#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_SHIFT 2 ++#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_MASK 0x4 ++#define GMAC0_RGMII_CNTL_DEL_STRB_SHIFT 3 ++#define GMAC0_RGMII_CNTL_DEL_STRB_MASK 0x8 ++#define GMAC0_RGMII_CNTL_DEL_VALUE_SHIFT 4 ++#define GMAC0_RGMII_CNTL_DEL_VALUE_MASK 0x70 ++#define GMAC0_RGMII_CNTL_DEL_ADDR_SHIFT 7 ++#define GMAC0_RGMII_CNTL_DEL_ADDR_MASK 0x780 ++ ++/* cfp_access offset0x200 */ ++#define CFP_ACCESS_OP_START_DONE_SHIFT 0 ++#define CFP_ACCESS_OP_START_DONE_MASK 0x1 ++#define CFP_ACCESS_OP_SEL_SHIFT 1 ++#define CFP_ACCESS_OP_SEL_MASK 0xe ++#define CFP_ACCESS_CFP_RAM_CLEAR_SHIFT 4 ++#define CFP_ACCESS_CFP_RAM_CLEAR_MASK 0x10 ++#define CFP_ACCESS_RESERVED1_SHIFT 5 ++#define CFP_ACCESS_RESERVED1_MASK 0x3e0 ++#define CFP_ACCESS_RAM_SEL_SHIFT 10 ++#define CFP_ACCESS_RAM_SEL_MASK 0x7c00 ++#define CFP_ACCESS_TCAM_RESET_SHIFT 15 ++#define CFP_ACCESS_TCAM_RESET_MASK 0x8000 ++#define CFP_ACCESS_XCESS_ADDR_SHIFT 16 ++#define CFP_ACCESS_XCESS_ADDR_MASK 0x1ff0000 ++#define CFP_ACCESS_RESERVED0_SHIFT 25 ++#define CFP_ACCESS_RESERVED0_MASK 0xe000000 ++#define CFP_ACCESS_RD_STATUS_SHIFT 28 ++#define CFP_ACCESS_RD_STATUS_MASK 0xf0000000 ++ ++/* cfp_tcam_data0 offset0x210 */ ++#define CFP_TCAM_DATA0_DATA_SHIFT 0 ++#define CFP_TCAM_DATA0_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data1 offset0x214 */ ++#define CFP_TCAM_DATA1_DATA_SHIFT 0 ++#define CFP_TCAM_DATA1_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data2 offset0x218 */ ++#define CFP_TCAM_DATA2_DATA_SHIFT 0 ++#define CFP_TCAM_DATA2_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data3 offset0x21c */ ++#define CFP_TCAM_DATA3_DATA_SHIFT 0 ++#define CFP_TCAM_DATA3_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data4 offset0x220 */ ++#define CFP_TCAM_DATA4_DATA_SHIFT 0 ++#define CFP_TCAM_DATA4_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data5 offset0x224 */ ++#define CFP_TCAM_DATA5_DATA_SHIFT 0 ++#define CFP_TCAM_DATA5_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data6 offset0x228 */ ++#define CFP_TCAM_DATA6_DATA_SHIFT 0 ++#define CFP_TCAM_DATA6_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data7 offset0x22c */ ++#define CFP_TCAM_DATA7_DATA_SHIFT 0 ++#define CFP_TCAM_DATA7_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask0 offset0x230 */ ++#define CFP_TCAM_MASK0_DATA_SHIFT 0 ++#define CFP_TCAM_MASK0_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask1 offset0x234 */ ++#define CFP_TCAM_MASK1_DATA_SHIFT 0 ++#define CFP_TCAM_MASK1_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask2 offset0x238 */ ++#define CFP_TCAM_MASK2_DATA_SHIFT 0 ++#define CFP_TCAM_MASK2_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask3 offset0x23c */ ++#define CFP_TCAM_MASK3_DATA_SHIFT 0 ++#define CFP_TCAM_MASK3_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask4 offset0x240 */ ++#define CFP_TCAM_MASK4_DATA_SHIFT 0 ++#define CFP_TCAM_MASK4_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask5 offset0x244 */ ++#define CFP_TCAM_MASK5_DATA_SHIFT 0 ++#define CFP_TCAM_MASK5_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask6 offset0x248 */ ++#define CFP_TCAM_MASK6_DATA_SHIFT 0 ++#define CFP_TCAM_MASK6_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask7 offset0x24c */ ++#define CFP_TCAM_MASK7_DATA_SHIFT 0 ++#define CFP_TCAM_MASK7_DATA_MASK 0xffffffff ++ ++/* cfp_action_data offset0x250 */ ++#define CFP_ACTION_DATA_CHAINID_SHIFT 0 ++#define CFP_ACTION_DATA_CHAINID_MASK 0xff ++#define CFP_ACTION_DATA_CHANNELID_SHIFT 8 ++#define CFP_ACTION_DATA_CHANNELID_MASK 0xf00 ++#define CFP_ACTION_DATA_DROP_SHIFT 12 ++#define CFP_ACTION_DATA_DROP_MASK 0x1000 ++#define CFP_ACTION_DATA_RESERVED_SHIFT 13 ++#define CFP_ACTION_DATA_RESERVED_MASK 0xffffe000 ++ ++/* tcam_bist_cntl offset0x2a0 */ ++#define TCAM_BIST_CNTL_TCAM_BIST_EN_SHIFT 0 ++#define TCAM_BIST_CNTL_TCAM_BIST_EN_MASK 0x1 ++#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_SHIFT 1 ++#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_MASK 0x6 ++#define TCAM_BIST_CNTL_RESERVED1_SHIFT 3 ++#define TCAM_BIST_CNTL_RESERVED1_MASK 0x8 ++#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_SHIFT 4 ++#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_MASK 0xf0 ++#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_SHIFT 8 ++#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_MASK 0xff00 ++#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_SHIFT 16 ++#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_MASK 0x10000 ++#define TCAM_BIST_CNTL_RESERVED_SHIFT 17 ++#define TCAM_BIST_CNTL_RESERVED_MASK 0x7ffe0000 ++#define TCAM_BIST_CNTL_TCAM_BIST_DONE_SHIFT 31 ++#define TCAM_BIST_CNTL_TCAM_BIST_DONE_MASK 0x80000000 ++ ++/* tcam_bist_status offset0x2a4 */ ++#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_SHIFT 0 ++#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_MASK 0xffff ++#define TCAM_BIST_STATUS_RESERVED_SHIFT 16 ++#define TCAM_BIST_STATUS_RESERVED_MASK 0xffff0000 ++ ++/* tcam_cmp_status offset0x2a8 */ ++#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_SHIFT 0 ++#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_MASK 0x1ff ++#define TCAM_CMP_STATUS_RESERVED2_SHIFT 9 ++#define TCAM_CMP_STATUS_RESERVED2_MASK 0x7e00 ++#define TCAM_CMP_STATUS_TCAM_HIT_SHIFT 15 ++#define TCAM_CMP_STATUS_TCAM_HIT_MASK 0x8000 ++#define TCAM_CMP_STATUS_RESERVED1_SHIFT 16 ++#define TCAM_CMP_STATUS_RESERVED1_MASK 0xffff0000 ++ ++/* tcam_disable offset0x2ac */ ++#define TCAM_DISABLE_TCAM_DISABLE_SHIFT 0 ++#define TCAM_DISABLE_TCAM_DISABLE_MASK 0xf ++#define TCAM_DISABLE_RESERVED_SHIFT 4 ++#define TCAM_DISABLE_RESERVED_MASK 0xfffffff0 ++ ++/* tcam_test_cntl offset0x2f0 */ ++#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_SHIFT 0 ++#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_MASK 0x7ff ++#define TCAM_TEST_CNTL_RESERVED_SHIFT 11 ++#define TCAM_TEST_CNTL_RESERVED_MASK 0xfffff800 ++ ++/* udf_0_a3_a0 offset0x300 */ ++#define UDF_0_A3_A0_CFG_UDF_0_A0_SHIFT 0 ++#define UDF_0_A3_A0_CFG_UDF_0_A0_MASK 0xff ++#define UDF_0_A3_A0_CFG_UDF_0_A1_SHIFT 8 ++#define UDF_0_A3_A0_CFG_UDF_0_A1_MASK 0xff00 ++#define UDF_0_A3_A0_CFG_UDF_0_A2_SHIFT 16 ++#define UDF_0_A3_A0_CFG_UDF_0_A2_MASK 0xff0000 ++#define UDF_0_A3_A0_CFG_UDF_0_A3_SHIFT 24 ++#define UDF_0_A3_A0_CFG_UDF_0_A3_MASK 0xff000000 ++ ++/* udf_0_a7_a4 offset0x304 */ ++#define UDF_0_A7_A4_CFG_UDF_0_A4_SHIFT 0 ++#define UDF_0_A7_A4_CFG_UDF_0_A4_MASK 0xff ++#define UDF_0_A7_A4_CFG_UDF_0_A5_SHIFT 8 ++#define UDF_0_A7_A4_CFG_UDF_0_A5_MASK 0xff00 ++#define UDF_0_A7_A4_CFG_UDF_0_A6_SHIFT 16 ++#define UDF_0_A7_A4_CFG_UDF_0_A6_MASK 0xff0000 ++#define UDF_0_A7_A4_CFG_UDF_0_A7_SHIFT 24 ++#define UDF_0_A7_A4_CFG_UDF_0_A7_MASK 0xff000000 ++ ++/* udf_0_a8 offset0x308 */ ++#define UDF_0_A8_CFG_UDF_0_A8_SHIFT 0 ++#define UDF_0_A8_CFG_UDF_0_A8_MASK 0xff ++ ++/* udf_1_a3_a0 offset0x310 */ ++#define UDF_1_A3_A0_CFG_UDF_1_A0_SHIFT 0 ++#define UDF_1_A3_A0_CFG_UDF_1_A0_MASK 0xff ++#define UDF_1_A3_A0_CFG_UDF_1_A1_SHIFT 8 ++#define UDF_1_A3_A0_CFG_UDF_1_A1_MASK 0xff00 ++#define UDF_1_A3_A0_CFG_UDF_1_A2_SHIFT 16 ++#define UDF_1_A3_A0_CFG_UDF_1_A2_MASK 0xff0000 ++#define UDF_1_A3_A0_CFG_UDF_1_A3_SHIFT 24 ++#define UDF_1_A3_A0_CFG_UDF_1_A3_MASK 0xff000000 ++ ++/* udf_1_a7_a4 offset0x314 */ ++#define UDF_1_A7_A4_CFG_UDF_1_A4_SHIFT 0 ++#define UDF_1_A7_A4_CFG_UDF_1_A4_MASK 0xff ++#define UDF_1_A7_A4_CFG_UDF_1_A5_SHIFT 8 ++#define UDF_1_A7_A4_CFG_UDF_1_A5_MASK 0xff00 ++#define UDF_1_A7_A4_CFG_UDF_1_A6_SHIFT 16 ++#define UDF_1_A7_A4_CFG_UDF_1_A6_MASK 0xff0000 ++#define UDF_1_A7_A4_CFG_UDF_1_A7_SHIFT 24 ++#define UDF_1_A7_A4_CFG_UDF_1_A7_MASK 0xff000000 ++ ++/* udf_1_a8 offset0x318 */ ++#define UDF_1_A8_CFG_UDF_1_A8_SHIFT 0 ++#define UDF_1_A8_CFG_UDF_1_A8_MASK 0xff ++ ++/* udf_2_a3_a0 offset0x320 */ ++#define UDF_2_A3_A0_CFG_UDF_2_A0_SHIFT 0 ++#define UDF_2_A3_A0_CFG_UDF_2_A0_MASK 0xff ++#define UDF_2_A3_A0_CFG_UDF_2_A1_SHIFT 8 ++#define UDF_2_A3_A0_CFG_UDF_2_A1_MASK 0xff00 ++#define UDF_2_A3_A0_CFG_UDF_2_A2_SHIFT 16 ++#define UDF_2_A3_A0_CFG_UDF_2_A2_MASK 0xff0000 ++#define UDF_2_A3_A0_CFG_UDF_2_A3_SHIFT 24 ++#define UDF_2_A3_A0_CFG_UDF_2_A3_MASK 0xff000000 ++ ++/* udf_2_a7_a4 offset0x324 */ ++#define UDF_2_A7_A4_CFG_UDF_2_A4_SHIFT 0 ++#define UDF_2_A7_A4_CFG_UDF_2_A4_MASK 0xff ++#define UDF_2_A7_A4_CFG_UDF_2_A5_SHIFT 8 ++#define UDF_2_A7_A4_CFG_UDF_2_A5_MASK 0xff00 ++#define UDF_2_A7_A4_CFG_UDF_2_A6_SHIFT 16 ++#define UDF_2_A7_A4_CFG_UDF_2_A6_MASK 0xff0000 ++#define UDF_2_A7_A4_CFG_UDF_2_A7_SHIFT 24 ++#define UDF_2_A7_A4_CFG_UDF_2_A7_MASK 0xff000000 ++ ++/* udf_2_a8 offset0x328 */ ++#define UDF_2_A8_CFG_UDF_2_A8_SHIFT 0 ++#define UDF_2_A8_CFG_UDF_2_A8_MASK 0xff ++ ++/* udf_0_b3_b0 offset0x330 */ ++#define UDF_0_B3_B0_CFG_UDF_0_B0_SHIFT 0 ++#define UDF_0_B3_B0_CFG_UDF_0_B0_MASK 0xff ++#define UDF_0_B3_B0_CFG_UDF_0_B1_SHIFT 8 ++#define UDF_0_B3_B0_CFG_UDF_0_B1_MASK 0xff00 ++#define UDF_0_B3_B0_CFG_UDF_0_B2_SHIFT 16 ++#define UDF_0_B3_B0_CFG_UDF_0_B2_MASK 0xff0000 ++#define UDF_0_B3_B0_CFG_UDF_0_B3_SHIFT 24 ++#define UDF_0_B3_B0_CFG_UDF_0_B3_MASK 0xff000000 ++ ++/* udf_0_b7_b4 offset0x334 */ ++#define UDF_0_B7_B4_CFG_UDF_0_B4_SHIFT 0 ++#define UDF_0_B7_B4_CFG_UDF_0_B4_MASK 0xff ++#define UDF_0_B7_B4_CFG_UDF_0_B5_SHIFT 8 ++#define UDF_0_B7_B4_CFG_UDF_0_B5_MASK 0xff00 ++#define UDF_0_B7_B4_CFG_UDF_0_B6_SHIFT 16 ++#define UDF_0_B7_B4_CFG_UDF_0_B6_MASK 0xff0000 ++#define UDF_0_B7_B4_CFG_UDF_0_B7_SHIFT 24 ++#define UDF_0_B7_B4_CFG_UDF_0_B7_MASK 0xff000000 ++ ++/* udf_0_b8 offset0x338 */ ++#define UDF_0_B8_CFG_UDF_0_B8_SHIFT 0 ++#define UDF_0_B8_CFG_UDF_0_B8_MASK 0xff ++ ++/* udf_1_b3_b0 offset0x340 */ ++#define UDF_1_B3_B0_CFG_UDF_1_B0_SHIFT 0 ++#define UDF_1_B3_B0_CFG_UDF_1_B0_MASK 0xff ++#define UDF_1_B3_B0_CFG_UDF_1_B1_SHIFT 8 ++#define UDF_1_B3_B0_CFG_UDF_1_B1_MASK 0xff00 ++#define UDF_1_B3_B0_CFG_UDF_1_B2_SHIFT 16 ++#define UDF_1_B3_B0_CFG_UDF_1_B2_MASK 0xff0000 ++#define UDF_1_B3_B0_CFG_UDF_1_B3_SHIFT 24 ++#define UDF_1_B3_B0_CFG_UDF_1_B3_MASK 0xff000000 ++ ++/* udf_1_b7_b4 offset0x344 */ ++#define UDF_1_B7_B4_CFG_UDF_1_B4_SHIFT 0 ++#define UDF_1_B7_B4_CFG_UDF_1_B4_MASK 0xff ++#define UDF_1_B7_B4_CFG_UDF_1_B5_SHIFT 8 ++#define UDF_1_B7_B4_CFG_UDF_1_B5_MASK 0xff00 ++#define UDF_1_B7_B4_CFG_UDF_1_B6_SHIFT 16 ++#define UDF_1_B7_B4_CFG_UDF_1_B6_MASK 0xff0000 ++#define UDF_1_B7_B4_CFG_UDF_1_B7_SHIFT 24 ++#define UDF_1_B7_B4_CFG_UDF_1_B7_MASK 0xff000000 ++ ++/* udf_1_b8 offset0x348 */ ++#define UDF_1_B8_CFG_UDF_1_B8_SHIFT 0 ++#define UDF_1_B8_CFG_UDF_1_B8_MASK 0xff ++ ++/* udf_2_b3_b0 offset0x350 */ ++#define UDF_2_B3_B0_CFG_UDF_2_B0_SHIFT 0 ++#define UDF_2_B3_B0_CFG_UDF_2_B0_MASK 0xff ++#define UDF_2_B3_B0_CFG_UDF_2_B1_SHIFT 8 ++#define UDF_2_B3_B0_CFG_UDF_2_B1_MASK 0xff00 ++#define UDF_2_B3_B0_CFG_UDF_2_B2_SHIFT 16 ++#define UDF_2_B3_B0_CFG_UDF_2_B2_MASK 0xff0000 ++#define UDF_2_B3_B0_CFG_UDF_2_B3_SHIFT 24 ++#define UDF_2_B3_B0_CFG_UDF_2_B3_MASK 0xff000000 ++ ++/* udf_2_b7_b4 offset0x354 */ ++#define UDF_2_B7_B4_CFG_UDF_2_B4_SHIFT 0 ++#define UDF_2_B7_B4_CFG_UDF_2_B4_MASK 0xff ++#define UDF_2_B7_B4_CFG_UDF_2_B5_SHIFT 8 ++#define UDF_2_B7_B4_CFG_UDF_2_B5_MASK 0xff00 ++#define UDF_2_B7_B4_CFG_UDF_2_B6_SHIFT 16 ++#define UDF_2_B7_B4_CFG_UDF_2_B6_MASK 0xff0000 ++#define UDF_2_B7_B4_CFG_UDF_2_B7_SHIFT 24 ++#define UDF_2_B7_B4_CFG_UDF_2_B7_MASK 0xff000000 ++ ++/* udf_2_b8 offset0x358 */ ++#define UDF_2_B8_CFG_UDF_2_B8_SHIFT 0 ++#define UDF_2_B8_CFG_UDF_2_B8_MASK 0xff ++ ++/* udf_0_c3_c0 offset0x360 */ ++#define UDF_0_C3_C0_CFG_UDF_0_C0_SHIFT 0 ++#define UDF_0_C3_C0_CFG_UDF_0_C0_MASK 0xff ++#define UDF_0_C3_C0_CFG_UDF_0_C1_SHIFT 8 ++#define UDF_0_C3_C0_CFG_UDF_0_C1_MASK 0xff00 ++#define UDF_0_C3_C0_CFG_UDF_0_C2_SHIFT 16 ++#define UDF_0_C3_C0_CFG_UDF_0_C2_MASK 0xff0000 ++#define UDF_0_C3_C0_CFG_UDF_0_C3_SHIFT 24 ++#define UDF_0_C3_C0_CFG_UDF_0_C3_MASK 0xff000000 ++ ++/* udf_0_c7_c4 offset0x364 */ ++#define UDF_0_C7_C4_CFG_UDF_0_C4_SHIFT 0 ++#define UDF_0_C7_C4_CFG_UDF_0_C4_MASK 0xff ++#define UDF_0_C7_C4_CFG_UDF_0_C5_SHIFT 8 ++#define UDF_0_C7_C4_CFG_UDF_0_C5_MASK 0xff00 ++#define UDF_0_C7_C4_CFG_UDF_0_C6_SHIFT 16 ++#define UDF_0_C7_C4_CFG_UDF_0_C6_MASK 0xff0000 ++#define UDF_0_C7_C4_CFG_UDF_0_C7_SHIFT 24 ++#define UDF_0_C7_C4_CFG_UDF_0_C7_MASK 0xff000000 ++ ++/* udf_0_c8 offset0x368 */ ++#define UDF_0_C8_CFG_UDF_0_C8_SHIFT 0 ++#define UDF_0_C8_CFG_UDF_0_C8_MASK 0xff ++ ++/* udf_1_c3_c0 offset0x370 */ ++#define UDF_1_C3_C0_CFG_UDF_1_C0_SHIFT 0 ++#define UDF_1_C3_C0_CFG_UDF_1_C0_MASK 0xff ++#define UDF_1_C3_C0_CFG_UDF_1_C1_SHIFT 8 ++#define UDF_1_C3_C0_CFG_UDF_1_C1_MASK 0xff00 ++#define UDF_1_C3_C0_CFG_UDF_1_C2_SHIFT 16 ++#define UDF_1_C3_C0_CFG_UDF_1_C2_MASK 0xff0000 ++#define UDF_1_C3_C0_CFG_UDF_1_C3_SHIFT 24 ++#define UDF_1_C3_C0_CFG_UDF_1_C3_MASK 0xff000000 ++ ++/* udf_1_c7_c4 offset0x374 */ ++#define UDF_1_C7_C4_CFG_UDF_1_C4_SHIFT 0 ++#define UDF_1_C7_C4_CFG_UDF_1_C4_MASK 0xff ++#define UDF_1_C7_C4_CFG_UDF_1_C5_SHIFT 8 ++#define UDF_1_C7_C4_CFG_UDF_1_C5_MASK 0xff00 ++#define UDF_1_C7_C4_CFG_UDF_1_C6_SHIFT 16 ++#define UDF_1_C7_C4_CFG_UDF_1_C6_MASK 0xff0000 ++#define UDF_1_C7_C4_CFG_UDF_1_C7_SHIFT 24 ++#define UDF_1_C7_C4_CFG_UDF_1_C7_MASK 0xff000000 ++ ++/* udf_1_c8 offset0x378 */ ++#define UDF_1_C8_CFG_UDF_1_C8_SHIFT 0 ++#define UDF_1_C8_CFG_UDF_1_C8_MASK 0xff ++ ++/* udf_2_c3_c0 offset0x380 */ ++#define UDF_2_C3_C0_CFG_UDF_2_C0_SHIFT 0 ++#define UDF_2_C3_C0_CFG_UDF_2_C0_MASK 0xff ++#define UDF_2_C3_C0_CFG_UDF_2_C1_SHIFT 8 ++#define UDF_2_C3_C0_CFG_UDF_2_C1_MASK 0xff00 ++#define UDF_2_C3_C0_CFG_UDF_2_C2_SHIFT 16 ++#define UDF_2_C3_C0_CFG_UDF_2_C2_MASK 0xff0000 ++#define UDF_2_C3_C0_CFG_UDF_2_C3_SHIFT 24 ++#define UDF_2_C3_C0_CFG_UDF_2_C3_MASK 0xff000000 ++ ++/* udf_2_c7_c4 offset0x384 */ ++#define UDF_2_C7_C4_CFG_UDF_2_C4_SHIFT 0 ++#define UDF_2_C7_C4_CFG_UDF_2_C4_MASK 0xff ++#define UDF_2_C7_C4_CFG_UDF_2_C5_SHIFT 8 ++#define UDF_2_C7_C4_CFG_UDF_2_C5_MASK 0xff00 ++#define UDF_2_C7_C4_CFG_UDF_2_C6_SHIFT 16 ++#define UDF_2_C7_C4_CFG_UDF_2_C6_MASK 0xff0000 ++#define UDF_2_C7_C4_CFG_UDF_2_C7_SHIFT 24 ++#define UDF_2_C7_C4_CFG_UDF_2_C7_MASK 0xff000000 ++ ++/* udf_2_c8 offset0x388 */ ++#define UDF_2_C8_CFG_UDF_2_C8_SHIFT 0 ++#define UDF_2_C8_CFG_UDF_2_C8_MASK 0xff ++ ++/* udf_0_d3_d0 offset0x390 */ ++#define UDF_0_D3_D0_CFG_UDF_0_D0_SHIFT 0 ++#define UDF_0_D3_D0_CFG_UDF_0_D0_MASK 0xff ++#define UDF_0_D3_D0_CFG_UDF_0_D1_SHIFT 8 ++#define UDF_0_D3_D0_CFG_UDF_0_D1_MASK 0xff00 ++#define UDF_0_D3_D0_CFG_UDF_0_D2_SHIFT 16 ++#define UDF_0_D3_D0_CFG_UDF_0_D2_MASK 0xff0000 ++#define UDF_0_D3_D0_CFG_UDF_0_D3_SHIFT 24 ++#define UDF_0_D3_D0_CFG_UDF_0_D3_MASK 0xff000000 ++ ++/* udf_0_d7_d4 offset0x394 */ ++#define UDF_0_D7_D4_CFG_UDF_0_D4_SHIFT 0 ++#define UDF_0_D7_D4_CFG_UDF_0_D4_MASK 0xff ++#define UDF_0_D7_D4_CFG_UDF_0_D5_SHIFT 8 ++#define UDF_0_D7_D4_CFG_UDF_0_D5_MASK 0xff00 ++#define UDF_0_D7_D4_CFG_UDF_0_D6_SHIFT 16 ++#define UDF_0_D7_D4_CFG_UDF_0_D6_MASK 0xff0000 ++#define UDF_0_D7_D4_CFG_UDF_0_D7_SHIFT 24 ++#define UDF_0_D7_D4_CFG_UDF_0_D7_MASK 0xff000000 ++ ++/* udf_0_d11_d8 offset0x398 */ ++#define UDF_0_D11_D8_CFG_UDF_0_D8_SHIFT 0 ++#define UDF_0_D11_D8_CFG_UDF_0_D8_MASK 0xff ++#define UDF_0_D11_D8_CFG_UDF_0_D9_SHIFT 8 ++#define UDF_0_D11_D8_CFG_UDF_0_D9_MASK 0xff00 ++#define UDF_0_D11_D8_CFG_UDF_0_D10_SHIFT 16 ++#define UDF_0_D11_D8_CFG_UDF_0_D10_MASK 0xff0000 ++#define UDF_0_D11_D8_CFG_UDF_0_D11_SHIFT 24 ++#define UDF_0_D11_D8_CFG_UDF_0_D11_MASK 0xff000000 ++ ++#endif /* _gmac_common_core_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/gmac_core.h b/drivers/bcmdrivers/gmac/src/include/gmac_core.h +new file mode 100755 +index 0000000..090c327 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch new file mode 100644 index 00000000..b1d35542 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch @@ -0,0 +1,308 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/gmac_core.h +@@ -0,0 +1,302 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * gmacdefs - Broadcom gmac (Unimac) specific definitions ++ * ++ * $Id: gmac_core.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _gmac_core_h_ ++#define _gmac_core_h_ ++ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* We have 4 DMA TX channels */ ++#define GMAC_NUM_DMA_TX 4 ++ ++typedef volatile struct { ++ dma64regs_t dmaxmt; /* dma tx */ ++ uint32 PAD[2]; ++ dma64regs_t dmarcv; /* dma rx */ ++ uint32 PAD[2]; ++} dma64_t; ++ ++/* ++ * Host Interface Registers ++ */ ++typedef volatile struct _gmacregs { ++ uint32 devcontrol; /* 0x000 */ ++ uint32 devstatus; /* 0x004 */ ++ uint32 PAD; ++ uint32 biststatus; /* 0x00c */ ++ uint32 PAD[4]; ++ uint32 intstatus; /* 0x020 */ ++ uint32 intmask; /* 0x024 */ ++ uint32 gptimer; /* 0x028 */ ++ uint32 PAD[53]; ++ uint32 intrecvlazy; /* 0x100 */ ++ uint32 flowctlthresh; /* 0x104 */ ++ uint32 wrrthresh; /* 0x108 */ ++ uint32 gmac_idle_cnt_thresh; /* 0x10c */ ++ uint32 PAD[28]; ++ uint32 phyaccess; /* 0x180 */ ++ uint32 PAD; ++ uint32 phycontrol; /* 0x188 */ ++ uint32 txqctl; /* 0x18c */ ++ uint32 rxqctl; /* 0x190 */ ++ uint32 gpioselect; /* 0x194 */ ++ uint32 gpio_output_en; /* 0x198 */ ++ uint32 PAD; /* 0x19c */ ++ uint32 txq_rxq_mem_ctl; /* 0x1a0 */ ++ uint32 memory_ecc_status; /* 0x1a4 */ ++ uint32 serdes_ctl; /* 0x1a8 */ ++ uint32 serdes_status0; /* 0x1ac */ ++ uint32 serdes_status1; /* 0x1b0 */ ++ uint32 PAD[11]; /* 0x1b4-1dc */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; /* 0x1e4 */ ++ uint32 pwrctl; /* 0x1e8 */ ++ uint32 PAD[5]; ++ ++ dma64_t dmaregs[GMAC_NUM_DMA_TX]; ++ ++ /* GAMC MIB counters */ ++ gmacmib_t mib; ++ uint32 PAD[245]; ++ ++ uint32 unimacversion; /* 0x800 */ ++ uint32 hdbkpctl; /* 0x804 */ ++ uint32 cmdcfg; /* 0x808 */ ++ uint32 macaddrhigh; /* 0x80c */ ++ uint32 macaddrlow; /* 0x810 */ ++ uint32 rxmaxlength; /* 0x814 */ ++ uint32 pausequanta; /* 0x818 */ ++ uint32 PAD[10]; ++ uint32 macmode; /* 0x844 */ ++ uint32 outertag; /* 0x848 */ ++ uint32 innertag; /* 0x84c */ ++ uint32 PAD[3]; ++ uint32 txipg; /* 0x85c */ ++ uint32 PAD[180]; ++ uint32 pausectl; /* 0xb30 */ ++ uint32 txflush; /* 0xb34 */ ++ uint32 rxstatus; /* 0xb38 */ ++ uint32 txstatus; /* 0xb3c */ ++} gmacregs_t; ++ ++#define GM_MIB_BASE 0x300 ++#define GM_MIB_LIMIT 0x800 ++ ++/* ++ * register-specific flag definitions ++ */ ++ ++/* device control */ ++#define DC_TSM 0x00000002 ++#define DC_CFCO 0x00000004 ++#define DC_RLSS 0x00000008 ++#define DC_MROR 0x00000010 ++#define DC_FCM_MASK 0x00000060 ++#define DC_FCM_SHIFT 5 ++#define DC_NAE 0x00000080 ++#define DC_TF 0x00000100 ++#define DC_RDS_MASK 0x00030000 ++#define DC_RDS_SHIFT 16 ++#define DC_TDS_MASK 0x000c0000 ++#define DC_TDS_SHIFT 18 ++ ++/* device status */ ++#define DS_RBF 0x00000001 ++#define DS_RDF 0x00000002 ++#define DS_RIF 0x00000004 ++#define DS_TBF 0x00000008 ++#define DS_TDF 0x00000010 ++#define DS_TIF 0x00000020 ++#define DS_PO 0x00000040 ++#define DS_MM_MASK 0x00000300 ++#define DS_MM_SHIFT 8 ++ ++/* bist status */ ++#define BS_MTF 0x00000001 ++#define BS_MRF 0x00000002 ++#define BS_TDB 0x00000004 ++#define BS_TIB 0x00000008 ++#define BS_TBF 0x00000010 ++#define BS_RDB 0x00000020 ++#define BS_RIB 0x00000040 ++#define BS_RBF 0x00000080 ++#define BS_URTF 0x00000100 ++#define BS_UTF 0x00000200 ++#define BS_URF 0x00000400 ++ ++/* interrupt status and mask registers */ ++#define I_MRO 0x00000001 ++#define I_MTO 0x00000002 ++#define I_TFD 0x00000004 ++#define I_LS 0x00000008 ++#define I_MDIO 0x00000010 ++#define I_MR 0x00000020 ++#define I_MT 0x00000040 ++#define I_TO 0x00000080 ++#define I_PDEE 0x00000400 ++#define I_PDE 0x00000800 ++#define I_DE 0x00001000 ++#define I_RDU 0x00002000 ++#define I_RFO 0x00004000 ++#define I_XFU 0x00008000 ++#define I_RI 0x00010000 ++#define I_XI0 0x01000000 ++#define I_XI1 0x02000000 ++#define I_XI2 0x04000000 ++#define I_XI3 0x08000000 ++#define I_INTMASK 0x0f01fcff ++#define I_ERRMASK 0x0000fc00 ++ ++/* interrupt receive lazy */ ++#define IRL_TO_MASK 0x00ffffff ++#define IRL_FC_MASK 0xff000000 ++#define IRL_FC_SHIFT 24 ++ ++/* flow control thresholds */ ++#define FCT_TT_MASK 0x00000fff ++#define FCT_RT_MASK 0x0fff0000 ++#define FCT_RT_SHIFT 16 ++ ++/* txq aribter wrr thresholds */ ++#define WRRT_Q0T_MASK 0x000000ff ++#define WRRT_Q1T_MASK 0x0000ff00 ++#define WRRT_Q1T_SHIFT 8 ++#define WRRT_Q2T_MASK 0x00ff0000 ++#define WRRT_Q2T_SHIFT 16 ++#define WRRT_Q3T_MASK 0xff000000 ++#define WRRT_Q3T_SHIFT 24 ++ ++/* phy access */ ++#define PA_DATA_MASK 0x0000ffff ++#define PA_ADDR_MASK 0x001f0000 ++#define PA_ADDR_SHIFT 16 ++#define PA_REG_MASK 0x1f000000 ++#define PA_REG_SHIFT 24 ++#define PA_WRITE 0x20000000 ++#define PA_START 0x40000000 ++ ++/* phy control */ ++#define PC_EPA_MASK 0x0000001f ++#define PC_MCT_MASK 0x007f0000 ++#define PC_MCT_SHIFT 16 ++#define PC_MTE 0x00800000 ++ ++/* rxq control */ ++#define RC_DBT_MASK 0x00000fff ++#define RC_DBT_SHIFT 0 ++#define RC_PTE 0x00001000 ++#define RC_MDP_MASK 0x3f000000 ++#define RC_MDP_SHIFT 24 ++ ++#define RC_MAC_DATA_PERIOD 9 ++ ++/* txq control */ ++#define TC_DBT_MASK 0x00000fff ++#define TC_DBT_SHIFT 0 ++ ++/* gpio select */ ++#define GS_GSC_MASK 0x0000000f ++#define GS_GSC_SHIFT 0 ++ ++/* gpio output enable */ ++#define GS_GOE_MASK 0x0000ffff ++#define GS_GOE_SHIFT 0 ++ ++/* gpio output enable */ ++#define SC_TX1G_FIFO_RST_MASK 0x00f00000 ++#define SC_TX1G_FIFO_RST_VAL 0x00f00000 ++#define SC_FORCE_SPD_STRAP_MASK 0x00060000 ++#define SC_FORCE_SPD_STRAP_VAL 0x00040000 ++#define SC_REF_TERM_SEL_MASK 0x00001000 ++#define SC_REFSEL_MASK 0x00000c00 ++#define SC_REFSEL_VAL 0x00000400 ++#define SC_REFDIV_MASK 0x00000300 ++#define SC_REFDIV_VAL 0x00000000 ++#define SC_LCREF_EN_MASK 0x00000040 ++#define SC_RSTB_PLL_MASK 0x00000010 ++#define SC_RSTB_MDIOREGS_MASK 0x00000008 ++#define SC_RSTB_HW_MASK 0x00000004 ++#define SC_IDDQ_MASK 0x00000002 ++#define SC_PWR_DOWN_MASK 0x00000001 ++ ++/* clk control status */ ++#define CS_FA 0x00000001 ++#define CS_FH 0x00000002 ++#define CS_FI 0x00000004 ++#define CS_AQ 0x00000008 ++#define CS_HQ 0x00000010 ++#define CS_FC 0x00000020 ++#define CS_ER 0x00000100 ++#define CS_AA 0x00010000 ++#define CS_HA 0x00020000 ++#define CS_BA 0x00040000 ++#define CS_BH 0x00080000 ++#define CS_ES 0x01000000 ++ ++/* command config */ ++#define CC_TE 0x00000001 ++#define CC_RE 0x00000002 ++#define CC_ES_MASK 0x0000000c ++#define CC_ES_SHIFT 2 ++#define CC_PROM 0x00000010 ++#define CC_PAD_EN 0x00000020 ++#define CC_CF 0x00000040 ++#define CC_PF 0x00000080 ++#define CC_RPI 0x00000100 ++#define CC_TAI 0x00000200 ++#define CC_HD 0x00000400 ++#define CC_HD_SHIFT 10 ++#define CC_SR 0x00002000 ++#define CC_ML 0x00008000 ++#define CC_OT 0x00020000 ++#define CC_OR 0x00040000 ++#define CC_AE 0x00400000 ++#define CC_CFE 0x00800000 ++#define CC_NLC 0x01000000 ++#define CC_RL 0x02000000 ++#define CC_RED 0x04000000 ++#define CC_PE 0x08000000 ++#define CC_TPI 0x10000000 ++#define CC_AT 0x20000000 ++ ++/* mac addr high */ ++#define MH_HI_MASK 0xffff ++#define MH_HI_SHIFT 16 ++#define MH_MID_MASK 0xffff ++#define MH_MID_SHIFT 0 ++ ++/* mac addr low */ ++#define ML_LO_MASK 0xffff ++#define ML_LO_SHIFT 0 ++ ++/* Core specific control flags */ ++#define SICF_SWCLKE 0x0004 ++#define SICF_SWRST 0x0008 ++ ++/* Core specific status flags */ ++#define SISF_SW_ATTACHED 0x0800 ++ ++#endif /* _gmac_core_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndarm.h b/drivers/bcmdrivers/gmac/src/include/hndarm.h +new file mode 100755 +index 0000000..c105b958 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch new file mode 100644 index 00000000..8a200152 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndarm.h.patch @@ -0,0 +1,102 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndarm.h +@@ -0,0 +1,96 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane ARM core software interface. ++ * ++ * $Id: hndarm.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _hndarm_h_ ++#define _hndarm_h_ ++ ++#include ++ ++extern void *hndarm_armr; ++extern uint32 hndarm_rev; ++ ++ ++extern void si_arm_init(si_t *sih); ++ ++#ifdef __ARM_ARCH_7A__ ++extern uint32 si_memc_get_ncdl(si_t *sih); ++#endif ++ ++extern void enable_arm_ints(uint32 which); ++extern void disable_arm_ints(uint32 which); ++ ++extern uint32 get_arm_cyclecount(void); ++extern void set_arm_cyclecount(uint32 ticks); ++ ++#ifdef __ARM_ARCH_7R__ ++extern uint32 get_arm_perfcount_enable(void); ++extern void set_arm_perfcount_enable(uint32 which); ++extern uint32 set_arm_perfcount_disable(void); ++ ++extern uint32 get_arm_perfcount_sel(void); ++extern void set_arm_perfcount_sel(uint32 which); ++ ++extern uint32 get_arm_perfcount_event(void); ++extern void set_arm_perfcount_event(uint32 which); ++ ++extern uint32 get_arm_perfcount(void); ++extern void set_arm_perfcount(uint32 which); ++ ++extern void enable_arm_cyclecount(void); ++extern void disable_arm_cyclecount(void); ++#endif /* __ARM_ARCH_7R__ */ ++ ++extern uint32 get_arm_inttimer(void); ++extern void set_arm_inttimer(uint32 ticks); ++ ++extern uint32 get_arm_intmask(void); ++extern void set_arm_intmask(uint32 ticks); ++ ++extern uint32 get_arm_intstatus(void); ++extern void set_arm_intstatus(uint32 ticks); ++ ++extern uint32 get_arm_firqmask(void); ++extern void set_arm_firqmask(uint32 ticks); ++ ++extern uint32 get_arm_firqstatus(void); ++extern void set_arm_firqstatus(uint32 ticks); ++ ++extern void arm_wfi(si_t *sih); ++extern void arm_jumpto(void *addr); ++ ++extern void traptest(void); ++ ++#ifdef BCMOVLHW ++#define BCMOVLHW_ENAB(sih) TRUE ++ ++extern int si_arm_ovl_remap(si_t *sih, void *virt, void *phys, uint size); ++extern int si_arm_ovl_reset(si_t *sih); ++extern bool si_arm_ovl_vaildaddr(si_t *sih, void *virt); ++extern bool si_arm_ovl_isenab(si_t *sih); ++extern bool si_arm_ovl_int(si_t *sih, uint32 pc); ++#else ++#define BCMOVLHW_ENAB(sih) FALSE ++ ++#define si_arm_ovl_remap(a, b, c, d) do {} while (0) ++#define si_arm_ovl_reset(a) do {} while (0) ++#define si_arm_ovl_int(a, b) FALSE ++#endif ++ ++#endif /* _hndarm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndchipc.h b/drivers/bcmdrivers/gmac/src/include/hndchipc.h +new file mode 100755 +index 0000000..878276f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch new file mode 100644 index 00000000..a97882b5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch @@ -0,0 +1,44 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndchipc.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane chipcommon support. ++ * ++ * $Id: hndchipc.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _hndchipc_h_ ++#define _hndchipc_h_ ++ ++typedef void (*si_serial_init_fn)(void *regs, uint irq, uint baud_base, uint reg_shift); ++ ++extern void si_serial_init(si_t *sih, si_serial_init_fn add); ++ ++extern void *hnd_jtagm_init(si_t *sih, uint clkd, bool exttap); ++extern void hnd_jtagm_disable(si_t *sih, void *h); ++extern uint32 jtag_scan(si_t *sih, void *h, uint irsz, uint32 ir0, uint32 ir1, ++ uint drsz, uint32 dr0, uint32 *dr1, bool rti); ++ ++typedef void (*cc_isr_fn)(void* cbdata, uint32 ccintst); ++ ++extern bool si_cc_register_isr(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata); ++extern void si_cc_isr(si_t *sih, chipcregs_t *regs); ++ ++#endif /* _hndchipc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndcpu.h b/drivers/bcmdrivers/gmac/src/include/hndcpu.h +new file mode 100755 +index 0000000..8a4ee4c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch new file mode 100644 index 00000000..8c43025d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch @@ -0,0 +1,46 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndcpu.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane MIPS/ARM cores software interface. ++ * ++ * $Id: hndcpu.h 258983 2011-05-11 09:59:25Z $ ++ */ ++ ++#ifndef _hndcpu_h_ ++#define _hndcpu_h_ ++ ++#if defined(mips) ++#include ++#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) ++#include ++#endif ++ ++extern uint si_irq(si_t *sih); ++extern uint32 si_cpu_clock(si_t *sih); ++extern uint32 si_mem_clock(si_t *sih); ++extern void hnd_cpu_wait(si_t *sih); ++extern void hnd_cpu_jumpto(void *addr); ++extern void hnd_cpu_reset(si_t *sih); ++extern void hnd_cpu_deadman_timer(si_t *sih, uint32 val); ++extern void si_router_coma(si_t *sih, int reset, int delay); ++extern void si_dmc_phyctl(si_t *sih, uint32 phyctl_val); ++ ++#endif /* _hndcpu_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hnddma.h b/drivers/bcmdrivers/gmac/src/include/hnddma.h +new file mode 100755 +index 0000000..64f0349 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch new file mode 100644 index 00000000..ba57efee --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hnddma.h.patch @@ -0,0 +1,323 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hnddma.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: hnddma.h 321146 2012-03-14 08:27:23Z $ ++ */ ++ ++#ifndef _hnddma_h_ ++#define _hnddma_h_ ++ ++#ifndef _hnddma_pub_ ++#define _hnddma_pub_ ++typedef const struct hnddma_pub hnddma_t; ++#endif /* _hnddma_pub_ */ ++ ++/* range param for dma_getnexttxp() and dma_txreclaim */ ++typedef enum txd_range { ++ HNDDMA_RANGE_ALL = 1, ++ HNDDMA_RANGE_TRANSMITTED, ++ HNDDMA_RANGE_TRANSFERED ++} txd_range_t; ++ ++/* dma parameters id */ ++enum dma_param_id { ++ HNDDMA_PID_TX_MULTI_OUTSTD_RD = 0, ++ HNDDMA_PID_TX_PREFETCH_CTL, ++ HNDDMA_PID_TX_PREFETCH_THRESH, ++ HNDDMA_PID_TX_BURSTLEN, ++ ++ HNDDMA_PID_RX_PREFETCH_CTL = 0x100, ++ HNDDMA_PID_RX_PREFETCH_THRESH, ++ HNDDMA_PID_RX_BURSTLEN ++}; ++ ++/* dma function type */ ++typedef void (*di_detach_t)(hnddma_t *dmah); ++typedef bool (*di_txreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxidle_t)(hnddma_t *dmah); ++typedef void (*di_txinit_t)(hnddma_t *dmah); ++typedef bool (*di_txenabled_t)(hnddma_t *dmah); ++typedef void (*di_rxinit_t)(hnddma_t *dmah); ++typedef void (*di_txsuspend_t)(hnddma_t *dmah); ++typedef void (*di_txresume_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspended_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah); ++#ifdef WL_MULTIQUEUE ++typedef void (*di_txflush_t)(hnddma_t *dmah); ++typedef void (*di_txflush_clear_t)(hnddma_t *dmah); ++#endif /* WL_MULTIQUEUE */ ++typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit); ++typedef int (*di_txunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); ++typedef int (*di_rxunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); ++typedef void* (*di_getpos_t)(hnddma_t *di, bool direction); ++typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah); ++typedef bool (*di_txstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxenable_t)(hnddma_t *dmah); ++typedef bool (*di_rxenabled_t)(hnddma_t *dmah); ++typedef void* (*di_rx_t)(hnddma_t *dmah); ++typedef bool (*di_rxfill_t)(hnddma_t *dmah); ++typedef void (*di_txreclaim_t)(hnddma_t *dmah, txd_range_t range); ++typedef void (*di_rxreclaim_t)(hnddma_t *dmah); ++typedef uintptr (*di_getvar_t)(hnddma_t *dmah, const char *name); ++typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, txd_range_t range); ++typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall); ++typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah); ++typedef void* (*di_peekntxp_t)(hnddma_t *dmah, int *len, void *txps[], txd_range_t range); ++typedef void* (*di_peeknextrxp_t)(hnddma_t *dmah); ++typedef void (*di_rxparam_get_t)(hnddma_t *dmah, uint16 *rxoffset, uint16 *rxbufsize); ++typedef void (*di_txblock_t)(hnddma_t *dmah); ++typedef void (*di_txunblock_t)(hnddma_t *dmah); ++typedef uint (*di_txactive_t)(hnddma_t *dmah); ++typedef void (*di_txrotate_t)(hnddma_t *dmah); ++typedef void (*di_counterreset_t)(hnddma_t *dmah); ++typedef uint (*di_ctrlflags_t)(hnddma_t *dmah, uint mask, uint flags); ++typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef uint (*di_rxactive_t)(hnddma_t *dmah); ++typedef uint (*di_txpending_t)(hnddma_t *dmah); ++typedef uint (*di_txcommitted_t)(hnddma_t *dmah); ++typedef int (*di_pktpool_set_t)(hnddma_t *dmah, pktpool_t *pool); ++typedef bool (*di_rxtxerror_t)(hnddma_t *dmah, bool istx); ++typedef void (*di_burstlen_set_t)(hnddma_t *dmah, uint8 rxburstlen, uint8 txburstlen); ++typedef uint (*di_avoidancecnt_t)(hnddma_t *dmah); ++typedef void (*di_param_set_t)(hnddma_t *dmah, uint16 paramid, uint16 paramval); ++typedef bool (*dma_glom_enable_t) (hnddma_t *dmah, uint32 val); ++typedef uint (*dma_active_rxbuf_t) (hnddma_t *dmah); ++/* dma opsvec */ ++typedef struct di_fcn_s { ++ di_detach_t detach; ++ di_txinit_t txinit; ++ di_txreset_t txreset; ++ di_txenabled_t txenabled; ++ di_txsuspend_t txsuspend; ++ di_txresume_t txresume; ++ di_txsuspended_t txsuspended; ++ di_txsuspendedidle_t txsuspendedidle; ++#ifdef WL_MULTIQUEUE ++ di_txflush_t txflush; ++ di_txflush_clear_t txflush_clear; ++#endif /* WL_MULTIQUEUE */ ++ di_txfast_t txfast; ++ di_txunframed_t txunframed; ++ di_getpos_t getpos; ++ di_txstopped_t txstopped; ++ di_txreclaim_t txreclaim; ++ di_getnexttxp_t getnexttxp; ++ di_peeknexttxp_t peeknexttxp; ++ di_peekntxp_t peekntxp; ++ di_txblock_t txblock; ++ di_txunblock_t txunblock; ++ di_txactive_t txactive; ++ di_txrotate_t txrotate; ++ ++ di_rxinit_t rxinit; ++ di_rxreset_t rxreset; ++ di_rxidle_t rxidle; ++ di_rxstopped_t rxstopped; ++ di_rxenable_t rxenable; ++ di_rxenabled_t rxenabled; ++ di_rx_t rx; ++ di_rxfill_t rxfill; ++ di_rxreclaim_t rxreclaim; ++ di_getnextrxp_t getnextrxp; ++ di_peeknextrxp_t peeknextrxp; ++ di_rxparam_get_t rxparam_get; ++ ++ di_fifoloopbackenable_t fifoloopbackenable; ++ di_getvar_t d_getvar; ++ di_counterreset_t counterreset; ++ di_ctrlflags_t ctrlflags; ++ di_dump_t dump; ++ di_dumptx_t dumptx; ++ di_dumprx_t dumprx; ++ di_rxactive_t rxactive; ++ di_txpending_t txpending; ++ di_txcommitted_t txcommitted; ++ di_pktpool_set_t pktpool_set; ++ di_rxtxerror_t rxtxerror; ++ di_burstlen_set_t burstlen_set; ++ di_avoidancecnt_t avoidancecnt; ++ di_param_set_t param_set; ++ dma_glom_enable_t glom_enab; ++ di_rxunframed_t rxunframed; ++ dma_active_rxbuf_t dma_activerxbuf; ++ uint endnum; ++} di_fcn_t; ++ ++/* ++ * Exported data structure (read-only) ++ */ ++/* export structure */ ++struct hnddma_pub { ++ const di_fcn_t *di_fn; /* DMA function pointers */ ++ uint txavail; /* # free tx descriptors */ ++ uint dmactrlflags; /* dma control flags */ ++ ++ /* rx error counters */ ++ uint rxgiants; /* rx giant frames */ ++ uint rxnobuf; /* rx out of dma descriptors */ ++ /* tx error counters */ ++ uint txnobuf; /* tx out of dma descriptors */ ++ uint txnodesc; /* tx out of dma descriptors running count */ ++}; ++ ++ ++extern hnddma_t * dma_attach(osl_t *osh, const char *name, si_t *sih, ++ volatile void *dmaregstx, volatile void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, ++ uint rxoffset, uint *msg_level); ++#ifdef BCMDMA32 ++ ++#define dma_detach(di) ((di)->di_fn->detach(di)) ++#define dma_txreset(di) ((di)->di_fn->txreset(di)) ++#define dma_rxreset(di) ((di)->di_fn->rxreset(di)) ++#define dma_rxidle(di) ((di)->di_fn->rxidle(di)) ++#define dma_txinit(di) ((di)->di_fn->txinit(di)) ++#define dma_txenabled(di) ((di)->di_fn->txenabled(di)) ++#define dma_rxinit(di) ((di)->di_fn->rxinit(di)) ++#define dma_txsuspend(di) ((di)->di_fn->txsuspend(di)) ++#define dma_txresume(di) ((di)->di_fn->txresume(di)) ++#define dma_txsuspended(di) ((di)->di_fn->txsuspended(di)) ++#define dma_txsuspendedidle(di) ((di)->di_fn->txsuspendedidle(di)) ++#ifdef WL_MULTIQUEUE ++#define dma_txflush(di) ((di)->di_fn->txflush(di)) ++#define dma_txflush_clear(di) ((di)->di_fn->txflush_clear(di)) ++#endif /* WL_MULTIQUEUE */ ++#define dma_txfast(di, p, commit) ((di)->di_fn->txfast(di, p, commit)) ++#define dma_fifoloopbackenable(di) ((di)->di_fn->fifoloopbackenable(di)) ++#define dma_txstopped(di) ((di)->di_fn->txstopped(di)) ++#define dma_rxstopped(di) ((di)->di_fn->rxstopped(di)) ++#define dma_rxenable(di) ((di)->di_fn->rxenable(di)) ++#define dma_rxenabled(di) ((di)->di_fn->rxenabled(di)) ++#define dma_rx(di) ((di)->di_fn->rx(di)) ++#define dma_rxfill(di) ((di)->di_fn->rxfill(di)) ++#define dma_txreclaim(di, range) ((di)->di_fn->txreclaim(di, range)) ++#define dma_rxreclaim(di) ((di)->di_fn->rxreclaim(di)) ++#define dma_getvar(di, name) ((di)->di_fn->d_getvar(di, name)) ++#define dma_getnexttxp(di, range) ((di)->di_fn->getnexttxp(di, range)) ++#define dma_getnextrxp(di, forceall) ((di)->di_fn->getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) ((di)->di_fn->peeknexttxp(di)) ++#define dma_peekntxp(di, l, t, r) ((di)->di_fn->peekntxp(di, l, t, r)) ++#define dma_peeknextrxp(di) ((di)->di_fn->peeknextrxp(di)) ++#define dma_rxparam_get(di, off, bufs) ((di)->di_fn->rxparam_get(di, off, bufs)) ++ ++#define dma_txblock(di) ((di)->di_fn->txblock(di)) ++#define dma_txunblock(di) ((di)->di_fn->txunblock(di)) ++#define dma_txactive(di) ((di)->di_fn->txactive(di)) ++#define dma_rxactive(di) ((di)->di_fn->rxactive(di)) ++#define dma_txrotate(di) ((di)->di_fn->txrotate(di)) ++#define dma_counterreset(di) ((di)->di_fn->counterreset(di)) ++#define dma_ctrlflags(di, mask, flags) ((di)->di_fn->ctrlflags((di), (mask), (flags))) ++#define dma_txpending(di) ((di)->di_fn->txpending(di)) ++#define dma_txcommitted(di) ((di)->di_fn->txcommitted(di)) ++#define dma_pktpool_set(di, pool) ((di)->di_fn->pktpool_set((di), (pool))) ++#if defined(BCMDBG) ++#define dma_dump(di, buf, dumpring) ((di)->di_fn->dump(di, buf, dumpring)) ++#define dma_dumptx(di, buf, dumpring) ((di)->di_fn->dumptx(di, buf, dumpring)) ++#define dma_dumprx(di, buf, dumpring) ((di)->di_fn->dumprx(di, buf, dumpring)) ++#endif ++#define dma_rxtxerror(di, istx) ((di)->di_fn->rxtxerror(di, istx)) ++#define dma_burstlen_set(di, rxlen, txlen) ((di)->di_fn->burstlen_set(di, rxlen, txlen)) ++#define dma_avoidance_cnt(di) ((di)->di_fn->avoidancecnt(di)) ++#define dma_param_set(di, paramid, paramval) ((di)->di_fn->param_set(di, paramid, paramval)) ++#define dma_activerxbuf(di) ((di)->di_fn->dma_activerxbuf(di)) ++ ++#else /* BCMDMA32 */ ++extern const di_fcn_t dma64proc; ++ ++#define dma_detach(di) (dma64proc.detach(di)) ++#define dma_txreset(di) (dma64proc.txreset(di)) ++#define dma_rxreset(di) (dma64proc.rxreset(di)) ++#define dma_rxidle(di) (dma64proc.rxidle(di)) ++#define dma_txinit(di) (dma64proc.txinit(di)) ++#define dma_txenabled(di) (dma64proc.txenabled(di)) ++#define dma_rxinit(di) (dma64proc.rxinit(di)) ++#define dma_txsuspend(di) (dma64proc.txsuspend(di)) ++#define dma_txresume(di) (dma64proc.txresume(di)) ++#define dma_txsuspended(di) (dma64proc.txsuspended(di)) ++#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di)) ++#ifdef WL_MULTIQUEUE ++#define dma_txflush(di) (dma64proc.txflush(di)) ++#define dma_txflush_clear(di) (dma64proc.txflush_clear(di)) ++#endif /* WL_MULTIQUEUE */ ++#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit)) ++#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit)) ++#define dma_getpos(di, dir) (dma64proc.getpos(di, dir)) ++#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di)) ++#define dma_txstopped(di) (dma64proc.txstopped(di)) ++#define dma_rxstopped(di) (dma64proc.rxstopped(di)) ++#define dma_rxenable(di) (dma64proc.rxenable(di)) ++#define dma_rxenabled(di) (dma64proc.rxenabled(di)) ++#define dma_rx(di) (dma64proc.rx(di)) ++#define dma_rxfill(di) (dma64proc.rxfill(di)) ++#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range)) ++#define dma_rxreclaim(di) (dma64proc.rxreclaim(di)) ++#define dma_getvar(di, name) (dma64proc.d_getvar(di, name)) ++#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range)) ++#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di)) ++#define dma_peekntxp(di, l, t, r) (dma64proc.peekntxp(di, l, t, r)) ++#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di)) ++#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs)) ++ ++#define dma_txblock(di) (dma64proc.txblock(di)) ++#define dma_txunblock(di) (dma64proc.txunblock(di)) ++#define dma_txactive(di) (dma64proc.txactive(di)) ++#define dma_rxactive(di) (dma64proc.rxactive(di)) ++#define dma_txrotate(di) (dma64proc.txrotate(di)) ++#define dma_counterreset(di) (dma64proc.counterreset(di)) ++#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags))) ++#define dma_txpending(di) (dma64proc.txpending(di)) ++#define dma_txcommitted(di) (dma64proc.txcommitted(di)) ++#define dma_pktpool_set(di, pool) (dma64proc.pktpool_set((di), (pool))) ++#define dma_rxunframed(di, p, l, commit)(dma64proc.rxunframed(di, p, l, commit)) ++#if defined(BCMDBG) ++#define dma_dump(di, buf, dumpring) (dma64proc.dump(di, buf, dumpring)) ++#define dma_dumptx(di, buf, dumpring) (dma64proc.dumptx(di, buf, dumpring)) ++#define dma_dumprx(di, buf, dumpring) (dma64proc.dumprx(di, buf, dumpring)) ++#endif ++#define dma_rxtxerror(di, istx) (dma64proc.rxtxerror(di, istx)) ++#define dma_burstlen_set(di, rxlen, txlen) (dma64proc.burstlen_set(di, rxlen, txlen)) ++#define dma_avoidance_cnt(di) (dma64proc.avoidancecnt(di)) ++#define dma_param_set(di, paramid, paramval) (dma64proc.param_set(di, paramid, paramval)) ++ ++#define dma_glom_enable(di, val) (dma64proc.glom_enab(di, val)) ++#define dma_activerxbuf(di) (dma64proc.dma_activerxbuf(di)) ++ ++#endif /* BCMDMA32 */ ++ ++/* return addresswidth allowed ++ * This needs to be done after SB attach but before dma attach. ++ * SB attach provides ability to probe backplane and dma core capabilities ++ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach ++ */ ++extern uint dma_addrwidth(si_t *sih, void *dmaregs); ++ ++/* pio helpers */ ++extern void dma_txpioloopback(osl_t *osh, dma32regs_t *); ++ ++#endif /* _hnddma_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndfwd.h b/drivers/bcmdrivers/gmac/src/include/hndfwd.h +new file mode 100755 +index 0000000..1502804 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch new file mode 100644 index 00000000..a731d86b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch @@ -0,0 +1,142 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndfwd.h +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND GMAC Forwarder ++ * When multiple ports from a switch to a dual core host processor are available ++ * each Wl MAC instance (wl0 and wl1) may be tied to each core. A forwarding ++ * driver would recieve/transmit packets from/to switch on behalf of the Wl ++ * driver per core, essentially translating each core of the host processor to ++ * be a WL MAC that is becomes just another "W"-LAN port on the switch. ++ * ++ * hndfwd.h provides the API for the Fwder network device driver and wl driver ++ * to register their respective transmit handlers as a per cpu object. ++ * ++ * HND Fwder in SMP assumes "dual" core: ++ * Core1: wl0=11ac ++ * Core0: wl1=11n + eth0 ++ * HND Fwder in Uniprocessor mode would use 2 units. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _hndfwd_h_ ++#define _hndfwd_h_ ++ ++#if defined(GMAC3) ++ ++/* ++ * Multiple GMAC to Host SMP Model: The ethernet driver operates as a ++ * FWD: Forwarder to MAC Interface such as wl0, wl1 ++ * NTK: Ethernet Network Interface binding to network stack (via CTF) ++ */ ++#define DEV_FWDER_NAME "fwd" ++#define DEV_NTKIF(etc) ((etc)->gmac_fwd == FALSE) ++#define DEV_FWDER(etc) ((etc)->gmac_fwd == TRUE) ++ ++#if defined(CONFIG_SMP) ++#define _FWDER_LOCK(fwder) spin_lock_bh(&(fwder)->lock) ++#define _FWDER_UNLOCK(fwder) spin_unlock_bh(&(fwder)->lock) ++#else /* !CONFIG_SMP */ ++#define _FWDER_LOCK(fwder) local_bh_disable() ++#define _FWDER_UNLOCK(fwder) local_bh_enable() ++#endif /* !CONFIG_SMP */ ++ ++#define FWDER_FAILURE 1 ++#define FWDER_SUCCESS 0 ++ ++#define FWDER_DEBUG ++#define FWDER_MAX_UNITS 2 ++ ++/* hard start xmit handler of a network device driver */ ++typedef int (* fwder_start_t)(struct sk_buff * buff, struct net_device * dev, ++ int cnt); ++ ++typedef enum fwder_dir { ++ FWD_UPSTREAM, /* WL##(RX) -> GMAC(TX) Start Xmit Handler */ ++ FWD_DNSTREAM, /* GMAC(RX) -> Wl##(TX) Start Xmit Handler */ ++ FWD_MAX_DIRS ++} fwder_dir_t; ++ ++typedef struct fwder { ++ struct net_device * dev; ++ fwder_start_t forward; ++ int unit; ++ unsigned int error; ++#if defined(CONFIG_SMP) ++ spinlock_t lock; ++#endif /* CONFIG_SMP */ ++} fwder_t; ++ ++#if defined(CONFIG_SMP) ++DECLARE_PER_CPU(struct fwder, fwd_upstream); /* Per Core GMAC Transmit */ ++DECLARE_PER_CPU(struct fwder, fwd_dnstream); /* Per Core Wl## Transmit */ ++#else /* !CONFIG_SMP */ ++extern struct fwder fwd_upstream[FWDER_MAX_UNITS]; ++extern struct fwder fwd_dnstream[FWDER_MAX_UNITS]; ++#endif /* !CONFIG_SMP */ ++ ++extern int fwder_init(void); /* Invoked in eth0 module_init */ ++ ++/* Register a transmit handler and return the reverse dir handler */ ++extern struct fwder * fwder_attach(fwder_start_t forward, ++ const struct net_device * dev, const int unit, const enum fwder_dir dir); ++ ++/* Deregister a transmit handler */ ++extern struct fwder * fwder_dettach(struct fwder * fwder_p); ++ ++extern void fwder_dump(const struct fwder * fwder_p); ++extern void fwder_dump_all(void); ++ ++static inline int ++fwder_transmit(struct sk_buff * skb, struct net_device * dev, ++ struct fwder * fwder_p, int cnt) ++{ ++ int ret; ++ ++ ASSERT(fwder_p != (struct fwder*)NULL); ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ if (dev == (struct net_device *)NULL) { ++ skb->dev = (struct net_device *)fwder_p->dev; ++ } ++ ++ ret = fwder_p->forward(skb, skb->dev, cnt); ++ ++#if defined(FWDER_DEBUG) ++ if (ret == FWDER_FAILURE) ++ fwder_p->error++; ++#endif ++ ++ _FWDER_UNLOCK(fwder_p); /* --LOCK */ ++ ++ return ret; ++} ++ ++#else /* !GMAC3 */ ++ ++#define DEV_FWDER_NAME "eth" ++#define DEV_NTKIF(etc) 1 ++#define DEV_FWDER(etc) 0 ++ ++#endif /* !GMAC3 */ ++ ++#endif /* _hndfwd_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndsoc.h b/drivers/bcmdrivers/gmac/src/include/hndsoc.h +new file mode 100755 +index 0000000..ae3d3c3 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch new file mode 100644 index 00000000..7e1e5224 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch @@ -0,0 +1,275 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndsoc.h +@@ -0,0 +1,269 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom HND chip & on-chip-interconnect-related definitions. ++ * ++ * $Id: hndsoc.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _HNDSOC_H ++#define _HNDSOC_H ++ ++/* Include the soci specific files */ ++#include ++#include ++ ++/* ++ * SOC Interconnect Address Map. ++ * All regions may not exist on all chips. ++ */ ++#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */ ++#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI_MEM_SZ (64 * 1024 * 1024) ++#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */ ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++#define SI_ENUM_BASE (sii->pub.si_enum_base) ++#else ++#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ ++#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ ++#define SI_MAXCORES 20 /* Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ ++ ++#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ ++#define SI_FASTRAM_SWAPPED 0x19800000 ++ ++#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ ++#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ ++#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ ++#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ ++#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ ++ ++#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */ ++#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */ ++#define SI_NS_NORFLASH_SZ 0x02000000 /* Size of NorthStar NOR flash region */ ++#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */ ++ ++#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ ++#define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ ++#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ ++#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ ++#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ ++#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ ++ ++#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ ++#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), low 32 bits ++ */ ++#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define SI_NS_CUR 0x1800B000 /* NorthStar CUR base */ ++ ++#if defined(CONFIG_MACH_NS) ++#define SI_NS_CHIPCB_SRAB 0x18007000 /* NorthStar Chip Common B SRAB base */ ++#else ++#define SI_NS_CHIPCB_SRAB 0x18036000 /* NorthStar+ Chip Common B SRAB base */ ++#endif ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++ ++#define ACPHY_CORE_ID 0x83b /* Dot11 ACPHY */ ++#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */ ++#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */ ++#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */ ++#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */ ++#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */ ++#define EROM_CORE_ID 0x366 /* EROM core ID */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all ++ * unused address ranges ++ */ ++ ++#define CC_4706_CORE_ID 0x500 /* chipcommon core */ ++#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++#define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ ++#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID ++#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */ ++#define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ ++#define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ ++#define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ ++#define ALTA_CORE_ID 0x534 /* I2S core */ ++#define DDR23_PHY_CORE_ID 0x5dd ++ ++#define SI_PCI1_MEM 0x40000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI1_CFG 0x44000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */ ++#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */ ++#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */ ++ ++/* There are TWO constants on all HND chips: SI_ENUM_BASE above, ++ * and chipcommon being the first core: ++ */ ++#define SI_CC_IDX 0 ++ ++/* SOC Interconnect types (aka chip types) */ ++#define SOCI_SB 0 ++#define SOCI_AI 1 ++#define SOCI_UBUS 2 ++#define SOCI_NS 3 ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++/* Common core status flags */ ++#define SISF_BIST_DONE 0x8000 ++#define SISF_BIST_ERROR 0x4000 ++#define SISF_GATED_CLK 0x2000 ++#define SISF_DMA64 0x1000 ++#define SISF_CORE_BITS 0x0fff ++ ++/* Norstar core status flags */ ++#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */ ++#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */ ++#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */ ++#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */ ++#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ ++#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ ++ ++/* A register that is common to all cores to ++ * communicate w/PMU regarding clock control. ++ */ ++#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ ++ ++/* clk_ctl_st register */ ++#define CCS_FORCEALP 0x00000001 /* force ALP request */ ++#define CCS_FORCEHT 0x00000002 /* force HT request */ ++#define CCS_FORCEILP 0x00000004 /* force ILP request */ ++#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ ++#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ ++#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ ++#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */ ++#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */ ++#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ ++#define CCS_ERSRC_REQ_SHIFT 8 ++#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ ++#define CCS_HTAVAIL 0x00020000 /* HT is available */ ++#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */ ++#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */ ++#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ ++#define CCS_ERSRC_STS_SHIFT 24 ++ ++#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ ++ ++/* Not really related to SOC Interconnect, but a couple of software ++ * conventions for the use the flash space: ++ */ ++ ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++/* A boot/binary may have an embedded block that describes its size */ ++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ ++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ ++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ ++#define BISZ_TXTST_IDX 1 /* 1: text start */ ++#define BISZ_TXTEND_IDX 2 /* 2: text end */ ++#define BISZ_DATAST_IDX 3 /* 3: data start */ ++#define BISZ_DATAEND_IDX 4 /* 4: data end */ ++#define BISZ_BSSST_IDX 5 /* 5: bss start */ ++#define BISZ_BSSEND_IDX 6 /* 6: bss end */ ++#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ ++ ++#endif /* _HNDSOC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndtcam.h b/drivers/bcmdrivers/gmac/src/include/hndtcam.h +new file mode 100755 +index 0000000..da7acf8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch new file mode 100644 index 00000000..085aa791 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch @@ -0,0 +1,101 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndtcam.h +@@ -0,0 +1,95 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SOCRAM TCAM software interface. ++ * ++ * $Id: hndtcam.h 317281 2012-02-27 11:23:27Z $ ++ */ ++#ifndef _hndtcam_h_ ++#define _hndtcam_h_ ++ ++/* ++ * 0 - 1 ++ * 1 - 2 Consecutive locations are patched ++ * 2 - 4 Consecutive locations are patched ++ * 3 - 8 Consecutive locations are patched ++ * 4 - 16 Consecutive locations are patched ++ * Define default to patch 2 locations ++ */ ++ ++#ifdef PATCHCOUNT ++#define SRPC_PATCHCOUNT PATCHCOUNT ++#else ++#define PATCHCOUNT 0 ++#define SRPC_PATCHCOUNT PATCHCOUNT ++#endif ++ ++#if defined(__ARM_ARCH_7R__) ++#ifndef PATCHCOUNT ++#define PATCHCOUNT 1 ++#endif ++#define ARMCR4_TCAMPATCHCOUNT PATCHCOUNT ++#define ARMCR4_TCAMADDR_MASK (~((1 << (ARMCR4_TCAMPATCHCOUNT + 2))-1)) ++#define ARMCR4_PATCHNLOC (1 << ARMCR4_TCAMPATCHCOUNT) ++#endif /* defined(__ARM_ARCH_7R__) */ ++ ++/* N Consecutive location to patch */ ++#define SRPC_PATCHNLOC (1 << (SRPC_PATCHCOUNT)) ++ ++#define PATCHHDR(_p) __attribute__ ((__section__ (".patchhdr."#_p))) _p ++#define PATCHENTRY(_p) __attribute__ ((__section__ (".patchentry."#_p))) _p ++ ++#if defined(__ARM_ARCH_7R__) ++typedef struct { ++ uint32 data[ARMCR4_PATCHNLOC]; ++} patch_entry_t; ++#else ++typedef struct { ++ uint32 data[SRPC_PATCHNLOC]; ++} patch_entry_t; ++#endif ++ ++typedef struct { ++ void *addr; /* patch address */ ++ uint32 len; /* bytes to patch in entry */ ++ patch_entry_t *entry; /* patch entry data */ ++} patch_hdr_t; ++ ++/* patch values and address structure */ ++typedef struct patchaddrvalue { ++ uint32 addr; ++ uint32 value; ++} patchaddrvalue_t; ++ ++extern void *socram_regs; ++extern uint32 socram_rev; ++ ++extern void *arm_regs; ++ ++extern void hnd_patch_init(void *srp); ++extern void hnd_tcam_write(void *srp, uint16 idx, uint32 data); ++extern void hnd_tcam_read(void *srp, uint16 idx, uint32 *content); ++void * hnd_tcam_init(void *srp, int no_addrs); ++extern void hnd_tcam_disablepatch(void *srp); ++extern void hnd_tcam_enablepatch(void *srp); ++#ifdef CONFIG_XIP ++extern void hnd_tcam_bootloader_load(void *srp, char *pvars); ++#else ++extern void hnd_tcam_load(void *srp, const patchaddrvalue_t *patchtbl); ++#endif /* CONFIG_XIP */ ++extern void BCMATTACHFN(hnd_tcam_load_default)(void); ++extern void hnd_tcam_reclaim(void); ++ ++#endif /* _hndtcam_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/linux_osl.h b/drivers/bcmdrivers/gmac/src/include/linux_osl.h +new file mode 100755 +index 0000000..e49878b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch new file mode 100644 index 00000000..21565d1c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch @@ -0,0 +1,985 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/linux_osl.h +@@ -0,0 +1,979 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux OS Independent Layer ++ * ++ * $Id: linux_osl.h 329351 2012-04-25 01:48:39Z $ ++ */ ++ ++#ifndef _linux_osl_h_ ++#define _linux_osl_h_ ++ ++#include ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ ++/* Reuse some of existing code of CTFPOOL */ ++#ifndef CTFPOOL ++#define CTFPOOL ++#endif ++ ++/* #define SKB_RECYCLING_DEBUG */ ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ ++/* Linux Kernel: File Operations: start */ ++extern void * osl_os_open_image(char * filename); ++extern int osl_os_get_image_block(char * buf, int len, void * image); ++extern void osl_os_close_image(void * image); ++extern int osl_os_image_size(void *image); ++/* Linux Kernel: File Operations: end */ ++ ++#ifdef BCMDRIVER ++ ++/* OSL initialization */ ++extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); ++extern void osl_detach(osl_t *osh); ++ ++/* Global ASSERT type */ ++extern uint32 g_assert_type; ++ ++/* ASSERT */ ++ #ifdef __GNUC__ ++ #define GCC_VERSION \ ++ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) ++ #if GCC_VERSION > 30100 ++ #define ASSERT(exp) do {} while (0) ++ #else ++ /* ASSERT could cause segmentation fault on GCC3.1, use empty instead */ ++ #define ASSERT(exp) ++ #endif /* GCC_VERSION > 30100 */ ++ #endif /* __GNUC__ */ ++ ++/* microsecond delay */ ++#define OSL_DELAY(usec) osl_delay(usec) ++extern void osl_delay(uint usec); ++ ++#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_read_attr((osh), (offset), (buf), (size)) ++#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_write_attr((osh), (offset), (buf), (size)) ++extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); ++extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); ++ ++/* PCI configuration space access macros */ ++#define OSL_PCI_READ_CONFIG(osh, offset, size) \ ++ osl_pci_read_config((osh), (offset), (size)) ++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ ++ osl_pci_write_config((osh), (offset), (size), (val)) ++extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size); ++extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); ++ ++/* PCI device bus # and slot # */ ++#define OSL_PCI_BUS(osh) osl_pci_bus(osh) ++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) ++extern uint osl_pci_bus(osl_t *osh); ++extern uint osl_pci_slot(osl_t *osh); ++extern struct pci_dev *osl_pci_device(osl_t *osh); ++ ++/* Pkttag flag should be part of public information */ ++typedef struct { ++ bool pkttag; ++ bool mmbus; /* Bus supports memory-mapped register accesses */ ++ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ ++ void *tx_ctx; /* Context to the callback function */ ++#ifdef OSLREGOPS ++ osl_rreg_fn_t rreg_fn; /* Read Register function */ ++ osl_wreg_fn_t wreg_fn; /* Write Register function */ ++ void *reg_ctx; /* Context to the reg callback functions */ ++#else ++ void *unused[3]; ++#endif ++} osl_pubinfo_t; ++ ++#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ ++ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ ++ } while (0) ++ ++#ifdef OSLREGOPS ++#define REGOPSSET(osh, rreg, wreg, ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->rreg_fn = rreg; \ ++ ((osl_pubinfo_t*)osh)->wreg_fn = wreg; \ ++ ((osl_pubinfo_t*)osh)->reg_ctx = ctx; \ ++ } while (0) ++#endif /* OSLREGOPS */ ++ ++/* host/bus architecture-specific byte swap */ ++// #define BUS_SWAP32(v) (v) /* JIRA:LINUXDEV-16 */ ++#ifdef IL_BIGENDIAN ++#define BUS_SWAP32(v) bcmswap32(v) ++#else ++#define BUS_SWAP32(v) (v) ++#endif /* IL_BIGENDIAN */ ++ ++ #define MALLOC(osh, size) osl_malloc((osh), (size)) ++ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) ++ #define MALLOCED(osh) osl_malloced((osh)) ++ extern void *osl_malloc(osl_t *osh, uint size); ++ extern void osl_mfree(osl_t *osh, void *addr, uint size); ++ extern uint osl_malloced(osl_t *osh); ++ ++#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC) ++#define NATIVE_MFREE(osh, addr, size) kfree(addr) ++#ifdef USBAP ++#include ++#define VMALLOC(osh, size) vmalloc(size) ++#define VFREE(osh, addr, size) vfree(addr) ++#endif /* USBAP */ ++ ++#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) ++extern uint osl_malloc_failed(osl_t *osh); ++ ++/* allocate/free shared (dma-able) consistent memory */ ++#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align() ++#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \ ++ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap)) ++#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ ++ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) ++extern uint osl_dma_consistent_align(void); ++extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap); ++extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); ++ ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ ++ ++/* map/unmap shared (dma-able) memory */ ++#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ ++ osl_dma_unmap((osh), (pa), (size), (direction)) ++extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah); ++extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); ++ ++/* API for DMA addressing capability */ ++#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) ++ ++/* register access macros */ ++ ++ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op ++ #define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op ++ ++#define OSL_ERROR(bcmerror) osl_error(bcmerror) ++extern int osl_error(int bcmerror); ++ ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ * Macros expand to calls to functions defined in linux_osl.c . ++ */ ++#ifndef BINOSL ++#include /* use current 2.4.x calling conventions */ ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++ ++#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) ++#define printf(fmt, args...) printk(fmt , ## args) ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++/* bcopy's: Linux kernel doesn't provide these (anymore) */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++ ++/* register access macros */ ++#if defined(OSLREGOPS) ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((osh), (volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((osh), (volatile uint16*)(r)) : \ ++ osl_readl((osh), (volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): osl_writeb((osh), (volatile uint8*)(r), (uint8)(v)); break; \ ++ case sizeof(uint16): osl_writew((osh), (volatile uint16*)(r), (uint16)(v)); break; \ ++ case sizeof(uint32): osl_writel((osh), (volatile uint32*)(r), (uint32)(v)); break; \ ++ } \ ++} while (0) ++ ++extern uint8 osl_readb(osl_t *osh, volatile uint8 *r); ++extern uint16 osl_readw(osl_t *osh, volatile uint16 *r); ++extern uint32 osl_readl(osl_t *osh, volatile uint32 *r); ++extern void osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v); ++extern void osl_writew(osl_t *osh, volatile uint16 *r, uint16 v); ++extern void osl_writel(osl_t *osh, volatile uint32 *r, uint32 v); ++#else /* OSLREGOPS */ ++ ++#ifndef IL_BIGENDIAN ++#ifndef __mips__ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++#else /* __mips__ */ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ __asm__ __volatile__("sync"); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v; \ ++ }), \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v = OSL_READ_REG(osh, r); \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v; \ ++ })) \ ++) ++#endif /* __mips__ */ ++ ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++#else /* IL_BIGENDIAN */ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)((uintptr)(r)^3)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)((uintptr)(r)^2)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), \ ++ (volatile uint8*)((uintptr)(r)^3)); break; \ ++ case sizeof(uint16): writew((uint16)(v), \ ++ (volatile uint16*)((uintptr)(r)^2)); break; \ ++ case sizeof(uint32): writel((uint32)(v), \ ++ (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++#endif /* IL_BIGENDIAN */ ++#endif /* OSLREGOPS */ ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++ ++/* bcopy, bcmp, and bzero functions */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++/* uncached/cached virtual address */ ++#ifdef __mips__ ++#include ++#define OSL_UNCACHED(va) ((void *)KSEG1ADDR((va))) ++#define OSL_CACHED(va) ((void *)KSEG0ADDR((va))) ++#else ++#define OSL_UNCACHED(va) ((void *)va) ++#define OSL_CACHED(va) ((void *)va) ++ ++/* ARM NorthStar */ ++#define OSL_CACHE_FLUSH(va, len) ++ ++#endif /* mips */ ++ ++#ifdef __mips__ ++#define OSL_PREF_RANGE_LD(va, sz) prefetch_range_PREF_LOAD_RETAINED(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) prefetch_range_PREF_STORE_RETAINED(va, sz) ++#else /* __mips__ */ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++#endif /* __mips__ */ ++ ++/* get processor cycle count */ ++#if defined(mips) ++#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) ++#elif defined(__i386__) ++#define OSL_GETCYCLES(x) rdtscl((x)) ++#else ++#define OSL_GETCYCLES(x) ((x) = 0) ++#endif /* defined(mips) */ ++ ++/* dereference an address that may cause a bus exception */ ++#ifdef mips ++#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) ++#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into"\ ++ " a module") ++#else ++#define BUSPROBE(val, addr) get_dbe((val), (addr)) ++#include ++#endif /* defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) */ ++#else ++#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) ++#endif /* mips */ ++ ++/* map/unmap physical to virtual I/O */ ++#if !defined(CONFIG_MMC_MSM7X00A) ++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) ++#else ++#define REG_MAP(pa, size) (void *)(0) ++#endif /* !defined(CONFIG_MMC_MSM7X00A */ ++#define REG_UNMAP(va) iounmap((va)) ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) memset((r), '\0', (len)) ++ ++/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for ++ * performance reasons), we need the Linux headers. ++ */ ++#include /* use current 2.4.x calling conventions */ ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#ifdef DHD_USE_STATIC_BUF ++#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) ++#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) ++#endif /* DHD_USE_STATIC_BUF */ ++#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) ++#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) ++#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) ++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) ++#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) ++#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) ++#define PKTSETLEN(osh, skb, len) __pskb_trim((struct sk_buff*)(skb), (len)) ++#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) ++#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++#define PKTSHRINK(osh, m) (m) ++ ++#ifdef CTFPOOL ++#define CTFPOOL_REFILL_THRESH 3 ++typedef struct ctfpool { ++ void *head; ++ spinlock_t lock; ++ uint max_obj; ++ uint curr_obj; ++ uint obj_size; ++ uint refills; ++ uint fast_allocs; ++ uint fast_frees; ++ uint slow_allocs; ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ int unit; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++} ctfpool_t; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && defined CONFIG_BCM_CTF2 ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags) ++#else ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define FASTBUF (0xFFF00000) ++#else ++#define FASTBUF (1 << 4) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#define CTFBUF (1 << 5) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->ctfpool_tag) == FASTBUF) ++#else ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->ctfpool_tag) ++#else ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif /* 2.6.36 */ ++ ++#else ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) ++#endif /* 2.6.22 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) ++#else ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) ++#else ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif ++ ++extern void *osl_ctfpool_add(osl_t *osh); ++extern void osl_ctfpool_replenish(osl_t *osh, uint thresh); ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++extern int32 osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size); ++#else ++extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size); ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++extern void osl_ctfpool_cleanup(osl_t *osh); ++extern void osl_ctfpool_stats(osl_t *osh, void *b); ++#else ++#define FASTBUF (1 << 16) ++#define CTFBUF (1 << 17) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#endif /* CTFPOOL */ ++ ++#ifdef CTFMAP ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->sp) ++#else /* 2.6.14 */ ++#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->list) ++#endif /* 2.6.14 */ ++ ++#define PKTCTFMAP(osh, p) \ ++do { \ ++ if (PKTISCTF(osh, p)) { \ ++ int32 sz; \ ++ sz = (uint32)(((struct sk_buff *)p)->end) - \ ++ (uint32)CTFMAPPTR(osh, p); \ ++ /* map the remaining unmapped area */ \ ++ if (sz > 0) { \ ++ _DMA_MAP(osh, (void *)CTFMAPPTR(osh, p), \ ++ sz, DMA_RX, p, NULL); \ ++ } \ ++ /* clear ctf buf flag */ \ ++ PKTCLRCTF(osh, p); \ ++ CTFMAPPTR(osh, p) = NULL; \ ++ } \ ++} while (0) ++#endif /* CTFMAP */ ++ ++#ifdef HNDCTF ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++#define SKIPCT (1 << 2) ++#define CHAINED (1 << 3) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED) ++#else ++#define SKIPCT (1 << 18) ++#define CHAINED (1 << 19) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED) ++#endif /* 2.6.36 */ ++#else /* 2.6.22 */ ++#define SKIPCT (1 << 2) ++#define CHAINED (1 << 3) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED) ++#endif /* 2.6.22 */ ++typedef struct ctf_mark { ++ uint32 value; ++} ctf_mark_t; ++#define CTF_MARK(m) (m.value) ++#else /* HNDCTF */ ++#define PKTSETSKIPCT(osh, skb) ++#define PKTCLRSKIPCT(osh, skb) ++#define PKTSKIPCT(osh, skb) ++#define PKTCLRCHAINED(osh, skb) ++#define PKTSETCHAINED(osh, skb) ++#define CTF_MARK(m) 0 ++#endif /* HNDCTF */ ++ ++#ifdef BCMFA ++#ifdef BCMFA_HW_HASH ++#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx) ++#else ++#define PKTSETFAHIDX(skb, idx) ++#endif /* BCMFA_SW_HASH */ ++#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx) ++#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp) ++#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev) ++ ++#define AUX_TCP_FIN_RST (1 << 0) ++#define AUX_FREED (1 << 1) ++#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST) ++#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST)) ++#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST) ++#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED) ++#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED)) ++#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED) ++#define PKTISFABRIDGED(skb) PKTISFAAUX(skb) ++#else ++#define PKTISFAAUX(skb) (FALSE) ++#define PKTISFABRIDGED(skb) (FALSE) ++#define PKTISFAFREED(skb) (FALSE) ++ ++#define PKTCLRFAAUX(skb) ++#define PKTSETFAFREED(skb) ++#define PKTCLRFAFREED(skb) ++#endif /* BCMFA */ ++ ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern void *osl_pktget_static(osl_t *osh, uint len); ++extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); ++ ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) ++ ++#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) ++#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) ++#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) ++#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) ++#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) ++#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ ++ ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) ++/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ ++#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) ++ ++#ifdef CONFIG_NF_CONNTRACK_MARK ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define PKTMARK(p) (((struct sk_buff *)(p))->mark) ++#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m) ++#else /* !2.6.0 */ ++#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) ++#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) ++#endif /* 2.6.0 */ ++#else /* CONFIG_NF_CONNTRACK_MARK */ ++#define PKTMARK(p) 0 ++#define PKTSETMARK(p, m) ++#endif /* CONFIG_NF_CONNTRACK_MARK */ ++ ++#else /* BINOSL */ ++ ++/* Where to get the declarations for mem, str, printf, bcopy's? Two basic approaches. ++ * ++ * First, use the Linux header files and the C standard library replacmenent versions ++ * built-in to the kernel. Use this approach when compiling non hybrid code or compling ++ * the OS port files. The second approach is to use our own defines/prototypes and ++ * functions we have provided in the Linux OSL, i.e. linux_osl.c. Use this approach when ++ * compiling the files that make up the hybrid binary. We are ensuring we ++ * don't directly link to the kernel replacement routines from the hybrid binary. ++ * ++ * NOTE: The issue we are trying to avoid is any questioning of whether the ++ * hybrid binary is derived from Linux. The wireless common code (wlc) is designed ++ * to be OS independent through the use of the OSL API and thus the hybrid binary doesn't ++ * derive from the Linux kernel at all. But since we defined our OSL API to include ++ * a small collection of standard C library routines and these routines are provided in ++ * the kernel we want to avoid even the appearance of deriving at all even though clearly ++ * usage of a C standard library API doesn't represent a derivation from Linux. Lastly ++ * note at the time of this checkin 4 references to memcpy/memset could not be eliminated ++ * from the binary because they are created internally by GCC as part of things like ++ * structure assignment. I don't think the compiler should be doing this but there is ++ * no options to disable it on Intel architectures (there is for MIPS so somebody must ++ * agree with me). I may be able to even remove these references eventually with ++ * a GNU binutil such as objcopy via a symbol rename (i.e. memcpy to osl_memcpy). ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++ #define printf(fmt, args...) printk(fmt , ## args) ++ #include /* for vsn/printf's */ ++ #include /* for mem*, str* */ ++ /* bcopy's: Linux kernel doesn't provide these (anymore) */ ++ #define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++ #define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++ #define bzero(b, len) memset((b), '\0', (len)) ++ ++ /* These are provided only because when compiling linux_osl.c there ++ * must be an explicit prototype (separate from the definition) because ++ * we are compiling with GCC option -Wstrict-prototypes. Conversely ++ * these could be placed directly in linux_osl.c. ++ */ ++ extern int osl_printf(const char *format, ...); ++ extern int osl_sprintf(char *buf, const char *format, ...); ++ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); ++ extern int osl_vsprintf(char *buf, const char *format, va_list ap); ++ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); ++ extern int osl_strcmp(const char *s1, const char *s2); ++ extern int osl_strncmp(const char *s1, const char *s2, uint n); ++ extern int osl_strlen(const char *s); ++ extern char* osl_strcpy(char *d, const char *s); ++ extern char* osl_strncpy(char *d, const char *s, uint n); ++ extern char* osl_strchr(const char *s, int c); ++ extern char* osl_strrchr(const char *s, int c); ++ extern void *osl_memset(void *d, int c, size_t n); ++ extern void *osl_memcpy(void *d, const void *s, size_t n); ++ extern void *osl_memmove(void *d, const void *s, size_t n); ++ extern int osl_memcmp(const void *s1, const void *s2, size_t n); ++#else ++ ++ /* In the below defines we undefine the macro first in case it is ++ * defined. This shouldn't happen because we are not using Linux ++ * header files but because our Linux 2.4 make includes modversions.h ++ * through a GCC -include compile option, they get defined to point ++ * at the appropriate versioned symbol name. Note this doesn't ++ * happen with our Linux 2.6 makes. ++ */ ++ ++ /* *printf functions */ ++ #include /* va_list needed for v*printf */ ++ #include /* size_t needed for *nprintf */ ++ #undef printf ++ #undef sprintf ++ #undef snprintf ++ #undef vsprintf ++ #undef vsnprintf ++ #define printf(fmt, args...) osl_printf((fmt) , ## args) ++ #define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt) , ## args) ++ #define snprintf(buf, n, fmt, args...) osl_snprintf((buf), (n), (fmt) , ## args) ++ #define vsprintf(buf, fmt, ap) osl_vsprintf((buf), (fmt), (ap)) ++ #define vsnprintf(buf, n, fmt, ap) osl_vsnprintf((buf), (n), (fmt), (ap)) ++ extern int osl_printf(const char *format, ...); ++ extern int osl_sprintf(char *buf, const char *format, ...); ++ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); ++ extern int osl_vsprintf(char *buf, const char *format, va_list ap); ++ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); ++ ++ /* str* functions */ ++ #undef strcmp ++ #undef strncmp ++ #undef strlen ++ #undef strcpy ++ #undef strncpy ++ #undef strchr ++ #undef strrchr ++ #define strcmp(s1, s2) osl_strcmp((s1), (s2)) ++ #define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n)) ++ #define strlen(s) osl_strlen((s)) ++ #define strcpy(d, s) osl_strcpy((d), (s)) ++ #define strncpy(d, s, n) osl_strncpy((d), (s), (n)) ++ #define strchr(s, c) osl_strchr((s), (c)) ++ #define strrchr(s, c) osl_strrchr((s), (c)) ++ extern int osl_strcmp(const char *s1, const char *s2); ++ extern int osl_strncmp(const char *s1, const char *s2, uint n); ++ extern int osl_strlen(const char *s); ++ extern char* osl_strcpy(char *d, const char *s); ++ extern char* osl_strncpy(char *d, const char *s, uint n); ++ extern char* osl_strchr(const char *s, int c); ++ extern char* osl_strrchr(const char *s, int c); ++ ++ /* mem* functions */ ++ #undef memset ++ #undef memcpy ++ #undef memcmp ++ #define memset(d, c, n) osl_memset((d), (c), (n)) ++ #define memcpy(d, s, n) osl_memcpy((d), (s), (n)) ++ #define memmove(d, s, n) osl_memmove((d), (s), (n)) ++ #define memcmp(s1, s2, n) osl_memcmp((s1), (s2), (n)) ++ extern void *osl_memset(void *d, int c, size_t n); ++ extern void *osl_memcpy(void *d, const void *s, size_t n); ++ extern void *osl_memmove(void *d, const void *s, size_t n); ++ extern int osl_memcmp(const void *s1, const void *s2, size_t n); ++ ++ /* bcopy, bcmp, and bzero functions */ ++ #undef bcopy ++ #undef bcmp ++ #undef bzero ++ #define bcopy(src, dst, len) osl_memcpy((dst), (src), (len)) ++ #define bcmp(b1, b2, len) osl_memcmp((b1), (b2), (len)) ++ #define bzero(b, len) osl_memset((b), '\0', (len)) ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++/* register access macros */ ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \ ++ osl_readl((volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ } \ ++} while (0) ++ ++/* else added by johnvb to make sdio and jtag work with BINOSL, at least compile ... UNTESTED */ ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++extern uint8 osl_readb(volatile uint8 *r); ++extern uint16 osl_readw(volatile uint16 *r); ++extern uint32 osl_readl(volatile uint32 *r); ++extern void osl_writeb(uint8 v, volatile uint8 *r); ++extern void osl_writew(uint16 v, volatile uint16 *r); ++extern void osl_writel(uint32 v, volatile uint32 *r); ++ ++/* system up time in ms */ ++#define OSL_SYSUPTIME() osl_sysuptime() ++extern uint32 osl_sysuptime(void); ++ ++/* uncached/cached virtual address */ ++#define OSL_UNCACHED(va) osl_uncached((va)) ++extern void *osl_uncached(void *va); ++#define OSL_CACHED(va) osl_cached((va)) ++extern void *osl_cached(void *va); ++ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++ ++/* get processor cycle count */ ++#define OSL_GETCYCLES(x) ((x) = osl_getcycles()) ++extern uint osl_getcycles(void); ++ ++/* dereference an address that may target abort */ ++#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr)) ++extern int osl_busprobe(uint32 *val, uint32 addr); ++ ++/* map/unmap physical to virtual */ ++#define REG_MAP(pa, size) osl_reg_map((pa), (size)) ++#define REG_UNMAP(va) osl_reg_unmap((va)) ++extern void *osl_reg_map(uint32 pa, uint size); ++extern void osl_reg_unmap(void *va); ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) bzero((r), (len)) ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#define PKTDATA(osh, skb) osl_pktdata((osh), (skb)) ++#define PKTLEN(osh, skb) osl_pktlen((osh), (skb)) ++#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb)) ++#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb)) ++#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb)) ++#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x)) ++#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len)) ++#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes)) ++#define PKTTAG(skb) osl_pkttag((skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt)) ++#define PKTLINK(skb) osl_pktlink((skb)) ++#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x)) ++#define PKTPRIO(skb) osl_pktprio((skb)) ++#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x)) ++#define PKTSHARED(skb) osl_pktshared((skb)) ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++ ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern uchar *osl_pktdata(osl_t *osh, void *skb); ++extern uint osl_pktlen(osl_t *osh, void *skb); ++extern uint osl_pktheadroom(osl_t *osh, void *skb); ++extern uint osl_pkttailroom(osl_t *osh, void *skb); ++extern void *osl_pktnext(osl_t *osh, void *skb); ++extern void osl_pktsetnext(void *skb, void *x); ++extern void osl_pktsetlen(osl_t *osh, void *skb, uint len); ++extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes); ++extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes); ++extern void *osl_pkttag(void *skb); ++extern void *osl_pktlink(void *skb); ++extern void osl_pktsetlink(void *skb, void *x); ++extern uint osl_pktprio(void *skb); ++extern void osl_pktsetprio(void *skb, uint x); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++extern bool osl_pktshared(void *skb); ++ ++ ++#endif /* BINOSL */ ++ ++#define PKTALLOCED(osh) osl_pktalloced(osh) ++extern uint osl_pktalloced(osl_t *osh); ++ ++#ifdef CTFMAP ++#include ++#define CTFMAPSZ 320 ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++({ \ ++ typeof(size) sz = (size); \ ++ if (PKTISCTF((osh), (p))) { \ ++ sz = CTFMAPSZ; \ ++ CTFMAPPTR((osh), (p)) = (void *)(((uint8 *)(va)) + CTFMAPSZ); \ ++ } \ ++ osl_dma_map((osh), (va), sz, (direction), (p), (dmah)); \ ++}) ++#define _DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++#else /* CTFMAP */ ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++#endif /* CTFMAP */ ++ ++#ifdef PKTC ++/* Use 8 bytes of skb tstamp field to store below info */ ++struct chain_node { ++ struct sk_buff *link; ++ unsigned int flags:3, pkts:9, bytes:20; ++}; ++ ++#define CHAIN_NODE(skb) ((struct chain_node*)(((struct sk_buff*)skb)->pktc_cb)) ++ ++#define PKTCSETATTR(s, f, p, b) ({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \ ++ CHAIN_NODE(s)->bytes = (b);}) ++#define PKTCCLRATTR(s) ({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \ ++ CHAIN_NODE(s)->bytes = 0;}) ++#define PKTCGETATTR(s) (CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \ ++ CHAIN_NODE(s)->bytes) ++#define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts) ++#define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes) ++#define PKTCGETFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETFLAGS(skb, f) (CHAIN_NODE(skb)->flags = (f)) ++#define PKTCCLRFLAGS(skb) (CHAIN_NODE(skb)->flags = 0) ++#define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c)) ++#define PKTCINCRCNT(skb) (CHAIN_NODE(skb)->pkts++) ++#define PKTCADDCNT(skb, c) (CHAIN_NODE(skb)->pkts += (c)) ++#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l)) ++#define PKTCADDLEN(skb, l) (CHAIN_NODE(skb)->bytes += (l)) ++#define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb)) ++#define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb)) ++#define PKTCLINK(skb) (CHAIN_NODE(skb)->link) ++#define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x)) ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for (; (skb) != NULL; (skb) = (nskb)) \ ++ if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \ ++ PKTSETCLINK((skb), NULL), 1) ++#define PKTCFREE(osh, skb, send) \ ++do { \ ++ void *nskb; \ ++ ASSERT((skb) != NULL); \ ++ FOREACH_CHAINED_PKT((skb), nskb) { \ ++ PKTCLRCHAINED((osh), (skb)); \ ++ PKTCCLRFLAGS((skb)); \ ++ PKTFREE((osh), (skb), (send)); \ ++ } \ ++} while (0) ++#define PKTCENQTAIL(h, t, p) \ ++do { \ ++ if ((t) == NULL) { \ ++ (h) = (t) = (p); \ ++ } else { \ ++ PKTSETCLINK((t), (p)); \ ++ (t) = (p); \ ++ } \ ++} while (0) ++#endif /* PKTC */ ++ ++#else /* ! BCMDRIVER */ ++ ++ ++/* ASSERT */ ++ #define ASSERT(exp) do {} while (0) ++ ++/* MALLOC and MFREE */ ++#define MALLOC(o, l) malloc(l) ++#define MFREE(o, p, l) free(p) ++#include ++ ++/* str* and mem* functions */ ++#include ++ ++/* *printf functions */ ++#include ++ ++/* bcopy, bcmp, and bzero */ ++extern void bcopy(const void *src, void *dst, size_t len); ++extern int bcmp(const void *b1, const void *b2, size_t len); ++extern void bzero(void *b, size_t len); ++#endif /* ! BCMDRIVER */ ++ ++#endif /* _linux_osl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/linuxver.h b/drivers/bcmdrivers/gmac/src/include/linuxver.h +new file mode 100755 +index 0000000..6150c05 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch new file mode 100644 index 00000000..b31d6c27 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_linuxver.h.patch @@ -0,0 +1,668 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/linuxver.h +@@ -0,0 +1,662 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux-specific abstractions to gain some independence from linux kernel versions. ++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. ++ * ++ * $Id: linuxver.h 312774 2012-02-03 22:20:14Z $ ++ */ ++ ++#ifndef _linuxver_h_ ++#define _linuxver_h_ ++ ++#include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#include ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) ++#include ++#else ++#include ++#endif ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) ++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ ++#ifdef __UNDEF_NO_VERSION__ ++#undef __NO_VERSION__ ++#else ++#define __NO_VERSION__ ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) ++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") ++#define module_param_string(_name_, _string_, _size_, _perm_) \ ++ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) ++#endif ++ ++/* linux/malloc.h is deprecated, use linux/slab.h instead. */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#include ++#else ++#include ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) ++#undef IP_TOS ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */ ++#include ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) ++#include ++#else ++#include ++#ifndef work_struct ++#define work_struct tq_struct ++#endif ++#ifndef INIT_WORK ++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) ++#endif ++#ifndef schedule_work ++#define schedule_work(_work) schedule_task((_work)) ++#endif ++#ifndef flush_scheduled_work ++#define flush_scheduled_work() flush_scheduled_tasks() ++#endif ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func) ++#else ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work) ++typedef void (*work_func_t)(void *work); ++#endif /* >= 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* Some distributions have their own 2.6.x compatibility layers */ ++#ifndef IRQ_NONE ++typedef void irqreturn_t; ++#define IRQ_NONE ++#define IRQ_HANDLED ++#define IRQ_RETVAL(x) ++#endif ++#else ++typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) ++#define IRQF_SHARED SA_SHIRQ ++#endif /* < 2.6.18 */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) ++#ifdef CONFIG_NET_RADIO ++#define CONFIG_WIRELESS_EXT ++#endif ++#endif /* < 2.6.17 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) ++#define MOD_INC_USE_COUNT ++#define MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#include ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ ++ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) ++#include ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++#include ++#include ++#endif ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)) ++/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which ++ * does this, but it's not in 2.4 so we do our own for now. ++ */ ++static inline void ++cs_error(client_handle_t handle, int func, int ret) ++{ ++ error_info_t err = { func, ret }; ++ CardServices(ReportError, handle, &err); ++} ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16)) ++ ++typedef struct pcmcia_device dev_link_t; ++ ++#endif ++ ++#endif /* CONFIG_PCMCIA */ ++ ++#ifndef __exit ++#define __exit ++#endif ++#ifndef __devexit ++#define __devexit ++#endif ++#ifndef __devinit ++#define __devinit __init ++#endif ++#ifndef __devinitdata ++#define __devinitdata ++#endif ++#ifndef __devexit_p ++#define __devexit_p(x) x ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) ++ ++#define pci_get_drvdata(dev) (dev)->sysdata ++#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) ++ ++/* ++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration ++ */ ++ ++struct pci_device_id { ++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ ++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ ++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ ++ unsigned long driver_data; /* Data private to the driver */ ++}; ++ ++struct pci_driver { ++ struct list_head node; ++ char *name; ++ const struct pci_device_id *id_table; /* NULL if wants all devices */ ++ int (*probe)(struct pci_dev *dev, ++ const struct pci_device_id *id); /* New device inserted */ ++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug ++ * capable driver) ++ */ ++ void (*suspend)(struct pci_dev *dev); /* Device suspended */ ++ void (*resume)(struct pci_dev *dev); /* Device woken up */ ++}; ++ ++#define MODULE_DEVICE_TABLE(type, name) ++#define PCI_ANY_ID (~0) ++ ++/* compatpci.c */ ++#define pci_module_init pci_register_driver ++extern int pci_register_driver(struct pci_driver *drv); ++extern void pci_unregister_driver(struct pci_driver *drv); ++ ++#endif /* PCI registration */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) ++#define pci_module_init pci_register_driver ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) ++#ifdef MODULE ++#define module_init(x) int init_module(void) { return x(); } ++#define module_exit(x) void cleanup_module(void) { x(); } ++#else ++#define module_init(x) __initcall(x); ++#define module_exit(x) __exitcall(x); ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) ++#define WL_USE_NETDEV_OPS ++#else ++#undef WL_USE_NETDEV_OPS ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL) ++#define WL_CONFIG_RFKILL ++#else ++#undef WL_CONFIG_RFKILL ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) ++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) ++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) ++#define pci_enable_device(dev) do { } while (0) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) ++#define net_device device ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) ++ ++/* ++ * DMA mapping ++ * ++ * See linux/Documentation/DMA-mapping.txt ++ */ ++ ++#ifndef PCI_DMA_TODEVICE ++#define PCI_DMA_TODEVICE 1 ++#define PCI_DMA_FROMDEVICE 2 ++#endif ++ ++typedef u32 dma_addr_t; ++ ++/* Pure 2^n version of get_order */ ++static inline int get_order(unsigned long size) ++{ ++ int order; ++ ++ size = (size-1) >> (PAGE_SHIFT-1); ++ order = -1; ++ do { ++ size >>= 1; ++ order++; ++ } while (size); ++ return order; ++} ++ ++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ++ dma_addr_t *dma_handle) ++{ ++ void *ret; ++ int gfp = GFP_ATOMIC | GFP_DMA; ++ ++ ret = (void *)__get_free_pages(gfp, get_order(size)); ++ ++ if (ret != NULL) { ++ memset(ret, 0, size); ++ *dma_handle = virt_to_bus(ret); ++ } ++ return ret; ++} ++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, ++ void *vaddr, dma_addr_t dma_handle) ++{ ++ free_pages((unsigned long)vaddr, get_order(size)); ++} ++#ifdef ILSIM ++extern uint pci_map_single(void *dev, void *va, uint size, int direction); ++extern void pci_unmap_single(void *dev, uint pa, uint size, int direction); ++#else ++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) ++#define pci_unmap_single(cookie, address, size, dir) ++#endif ++ ++#endif /* DMA mapping */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) ++ ++#define dev_kfree_skb_any(a) dev_kfree_skb(a) ++#define netif_down(dev) do { (dev)->start = 0; } while (0) ++ ++/* pcmcia-cs provides its own netdevice compatibility layer */ ++#ifndef _COMPAT_NETDEVICE_H ++ ++/* ++ * SoftNet ++ * ++ * For pre-softnet kernels we need to tell the upper layer not to ++ * re-enter start_xmit() while we are in there. However softnet ++ * guarantees not to enter while we are in there so there is no need ++ * to do the netif_stop_queue() dance unless the transmit queue really ++ * gets stuck. This should also improve performance according to tests ++ * done by Aman Singla. ++ */ ++ ++#define dev_kfree_skb_irq(a) dev_kfree_skb(a) ++#define netif_wake_queue(dev) \ ++ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) ++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) ++ ++static inline void netif_start_queue(struct net_device *dev) ++{ ++ dev->tbusy = 0; ++ dev->interrupt = 0; ++ dev->start = 1; ++} ++ ++#define netif_queue_stopped(dev) (dev)->tbusy ++#define netif_running(dev) (dev)->start ++ ++#endif /* _COMPAT_NETDEVICE_H */ ++ ++#define netif_device_attach(dev) netif_start_queue(dev) ++#define netif_device_detach(dev) netif_stop_queue(dev) ++ ++/* 2.4.x renamed bottom halves to tasklets */ ++#define tasklet_struct tq_struct ++static inline void tasklet_schedule(struct tasklet_struct *tasklet) ++{ ++ queue_task(tasklet, &tq_immediate); ++ mark_bh(IMMEDIATE_BH); ++} ++ ++static inline void tasklet_init(struct tasklet_struct *tasklet, ++ void (*func)(unsigned long), ++ unsigned long data) ++{ ++ tasklet->next = NULL; ++ tasklet->sync = 0; ++ tasklet->routine = (void (*)(void *))func; ++ tasklet->data = (void *)data; ++} ++#define tasklet_kill(tasklet) { do {} while (0); } ++ ++/* 2.4.x introduced del_timer_sync() */ ++#define del_timer_sync(timer) del_timer(timer) ++ ++#else ++ ++#define netif_down(dev) ++ ++#endif /* SoftNet */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) ++ ++/* ++ * Emit code to initialise a tq_struct's routine and data pointers ++ */ ++#define PREPARE_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ (_tq)->routine = _routine; \ ++ (_tq)->data = _data; \ ++ } while (0) ++ ++/* ++ * Emit code to initialise all of a tq_struct ++ */ ++#define INIT_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ INIT_LIST_HEAD(&(_tq)->list); \ ++ (_tq)->sync = 0; \ ++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ ++ } while (0) ++ ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */ ++ ++/* Power management related macro & routines */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9) ++#define PCI_SAVE_STATE(a, b) pci_save_state(a) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a) ++#else ++#define PCI_SAVE_STATE(a, b) pci_save_state(a, b) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) ++static inline int ++pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_read_config_dword(dev, i * 4, &buffer[i]); ++ } ++ return 0; ++} ++ ++static inline int ++pci_restore_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_write_config_dword(dev, i * 4, buffer[i]); ++ } ++ /* ++ * otherwise, write the context information we know from bootup. ++ * This works around a problem where warm-booting from Windows ++ * combined with a D3(hot)->D0 transition causes PCI config ++ * header data to be forgotten. ++ */ ++ else { ++ for (i = 0; i < 6; i ++) ++ pci_write_config_dword(dev, ++ PCI_BASE_ADDRESS_0 + (i * 4), ++ pci_resource_start(dev, i)); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ } ++ return 0; ++} ++#endif /* PCI power management */ ++ ++/* Old cp0 access macros deprecated in 2.4.19 */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) ++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) ++#endif ++ ++/* Module refcount handled internally in 2.6.x */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#else ++#define OLD_MOD_INC_USE_COUNT do {} while (0) ++#define OLD_MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#endif ++#ifndef MOD_INC_USE_COUNT ++#define MOD_INC_USE_COUNT do {} while (0) ++#endif ++#ifndef MOD_DEC_USE_COUNT ++#define MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++ ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) do {} while (0) ++#endif ++ ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(dev) kfree(dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* struct packet_type redefined in 2.6.x */ ++#define af_packet_priv data ++#endif ++ ++/* suspend args */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) ++#define DRV_SUSPEND_STATE_TYPE pm_message_t ++#else ++#define DRV_SUSPEND_STATE_TYPE uint32 ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define CHECKSUM_HW CHECKSUM_PARTIAL ++#endif ++ ++typedef struct { ++ void *parent; /* some external entity that the thread supposed to work for */ ++ struct task_struct *p_task; ++ long thr_pid; ++ int prio; /* priority */ ++ struct semaphore sema; ++ int terminated; ++ struct completion completed; ++} tsk_ctl_t; ++ ++ ++/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */ ++/* note this macro assumes there may be only one context waiting on thread's completion */ ++#ifdef DHD_DEBUG ++#define DBG_THR(x) printk x ++#else ++#define DBG_THR(x) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) ++#else ++#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) ++#endif ++ ++ ++#define PROC_START(thread_func, owner, tsk_ctl, flags) \ ++{ \ ++ sema_init(&((tsk_ctl)->sema), 0); \ ++ init_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->parent = owner; \ ++ (tsk_ctl)->terminated = FALSE; \ ++ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ ++ if ((tsk_ctl)->thr_pid > 0) \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++} ++ ++#define PROC_STOP(tsk_ctl) \ ++{ \ ++ (tsk_ctl)->terminated = TRUE; \ ++ smp_wmb(); \ ++ up(&((tsk_ctl)->sema)); \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++ (tsk_ctl)->thr_pid = -1; \ ++} ++ ++/* ----------------------- */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) ++#define KILL_PROC(nr, sig) \ ++{ \ ++struct task_struct *tsk; \ ++struct pid *pid; \ ++pid = find_get_pid((pid_t)nr); \ ++tsk = pid_task(pid, PIDTYPE_PID); \ ++if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ ++ KERNEL_VERSION(2, 6, 30)) ++#define KILL_PROC(pid, sig) \ ++{ \ ++ struct task_struct *tsk; \ ++ tsk = find_task_by_vpid(pid); \ ++ if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#define KILL_PROC(pid, sig) \ ++{ \ ++ kill_proc(pid, sig, 1); \ ++} ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#include ++#include ++#else ++#include ++ ++#define __wait_event_interruptible_timeout(wq, condition, ret) \ ++do { \ ++ wait_queue_t __wait; \ ++ init_waitqueue_entry(&__wait, current); \ ++ \ ++ add_wait_queue(&wq, &__wait); \ ++ for (;;) { \ ++ set_current_state(TASK_INTERRUPTIBLE); \ ++ if (condition) \ ++ break; \ ++ if (!signal_pending(current)) { \ ++ ret = schedule_timeout(ret); \ ++ if (!ret) \ ++ break; \ ++ continue; \ ++ } \ ++ ret = -ERESTARTSYS; \ ++ break; \ ++ } \ ++ current->state = TASK_RUNNING; \ ++ remove_wait_queue(&wq, &__wait); \ ++} while (0) ++ ++#define wait_event_interruptible_timeout(wq, condition, timeout) \ ++({ \ ++ long __ret = timeout; \ ++ if (!(condition)) \ ++ __wait_event_interruptible_timeout(wq, condition, __ret); \ ++ __ret; \ ++}) ++ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ ++ ++/* ++For < 2.6.24, wl creates its own netdev but doesn't ++align the priv area like the genuine alloc_netdev(). ++Since netdev_priv() always gives us the aligned address, it will ++not match our unaligned address for < 2.6.24 ++*/ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#define DEV_PRIV(dev) (dev->priv) ++#else ++#define DEV_PRIV(dev) netdev_priv(dev) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++#define WL_ISR(i, d, p) wl_isr((i), (d)) ++#else ++#define WL_ISR(i, d, p) wl_isr((i), (d), (p)) ++#endif /* < 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define netdev_priv(dev) dev->priv ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++ ++#endif /* _linuxver_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/osl.h b/drivers/bcmdrivers/gmac/src/include/osl.h +new file mode 100755 +index 0000000..6b961d9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch new file mode 100644 index 00000000..3b2fe58c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_osl.h.patch @@ -0,0 +1,151 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/osl.h +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OS Abstraction Layer ++ * ++ * $Id: osl.h 321101 2012-03-14 02:53:01Z $ ++ */ ++ ++#ifndef _osl_h_ ++#define _osl_h_ ++ ++/* osl handle type forward declaration */ ++typedef struct osl_info osl_t; ++typedef struct osl_dmainfo osldma_t; ++ ++#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ ++ ++/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ ++typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); ++ ++/* Drivers use REGOPSSET() to register register read/write funcitons */ ++typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size); ++typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size); ++ ++#ifdef __mips__ ++#define PREF_LOAD 0 ++#define PREF_STORE 1 ++#define PREF_LOAD_STREAMED 4 ++#define PREF_STORE_STREAMED 5 ++#define PREF_LOAD_RETAINED 6 ++#define PREF_STORE_RETAINED 7 ++#define PREF_WBACK_INV 25 ++#define PREF_PREPARE4STORE 30 ++ ++ ++#define MAKE_PREFETCH_FN(hint) \ ++static inline void prefetch_##hint(const void *addr) \ ++{ \ ++ __asm__ __volatile__(\ ++ " .set mips4 \n" \ ++ " pref %0, (%1) \n" \ ++ " .set mips0 \n" \ ++ : \ ++ : "i" (hint), "r" (addr)); \ ++} ++ ++#define MAKE_PREFETCH_RANGE_FN(hint) \ ++static inline void prefetch_range_##hint(const void *addr, int len) \ ++{ \ ++ int size = len; \ ++ while (size > 0) { \ ++ prefetch_##hint(addr); \ ++ size -= 32; \ ++ } \ ++} ++ ++MAKE_PREFETCH_FN(PREF_LOAD) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD) ++MAKE_PREFETCH_FN(PREF_STORE) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE) ++MAKE_PREFETCH_FN(PREF_LOAD_STREAMED) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD_STREAMED) ++MAKE_PREFETCH_FN(PREF_STORE_STREAMED) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE_STREAMED) ++MAKE_PREFETCH_FN(PREF_LOAD_RETAINED) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD_RETAINED) ++MAKE_PREFETCH_FN(PREF_STORE_RETAINED) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE_RETAINED) ++#endif /* __mips__ */ ++ ++#if defined(linux) ++#include ++#else ++#error "Unsupported OSL requested" ++#endif ++ ++#ifndef PKTDBG_TRACE ++#define PKTDBG_TRACE(osh, pkt, bit) ++#endif ++ ++#ifndef PKTCTFMAP ++#define PKTCTFMAP(osh, p) ++#endif /* PKTCTFMAP */ ++ ++/* -------------------------------------------------------------------------- ++** Register manipulation macros. ++*/ ++ ++#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) ++ ++#ifndef AND_REG ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#endif /* !AND_REG */ ++ ++#ifndef OR_REG ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++#endif /* !OR_REG */ ++ ++#if !defined(OSL_SYSUPTIME) ++#define OSL_SYSUPTIME() (0) ++#define OSL_SYSUPTIME_SUPPORT FALSE ++#else ++#define OSL_SYSUPTIME_SUPPORT TRUE ++#endif /* OSL_SYSUPTIME */ ++ ++#if !defined(linux) || !defined(PKTC) ++#define PKTCGETATTR(s) (0) ++#define PKTCSETATTR(skb, f, p, b) ++#define PKTCCLRATTR(skb) ++#define PKTCCNT(skb) (1) ++#define PKTCLEN(skb) PKTLEN(NULL, skb) ++#define PKTCGETFLAGS(skb) (0) ++#define PKTCSETFLAGS(skb, f) ++#define PKTCCLRFLAGS(skb) ++#define PKTCFLAGS(skb) (0) ++#define PKTCSETCNT(skb, c) ++#define PKTCINCRCNT(skb) ++#define PKTCADDCNT(skb, c) ++#define PKTCSETLEN(skb, l) ++#define PKTCADDLEN(skb, l) ++#define PKTCSETFLAG(skb, fb) ++#define PKTCCLRFLAG(skb, fb) ++#define PKTCLINK(skb) NULL ++#define PKTSETCLINK(skb, x) ++#undef PKTISCHAINED ++#define PKTISCHAINED(skb) FALSE ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) ++#define PKTCFREE PKTFREE ++#endif ++ ++ ++#endif /* _osl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/packed_section_end.h b/drivers/bcmdrivers/gmac/src/include/packed_section_end.h +new file mode 100755 +index 0000000..44c83f8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch new file mode 100644 index 00000000..c5b9ea16 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch @@ -0,0 +1,77 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/packed_section_end.h +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is NOT defined at this ++ * point, then there is a missing include of packed_section_start.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #undef BWL_PACKED_SECTION ++#else ++ #error "BWL_PACKED_SECTION is NOT defined!" ++#endif ++ ++ ++#if defined(_MSC_VER) ++ /* Disable compiler warning about pragma pack changing alignment. */ ++ #pragma warning(disable:4103) ++ ++ /* The Microsoft compiler uses pragmas for structure packing. Other ++ * compilers use structure attribute modifiers. Refer to ++ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined in ++ * typedefs.h ++ */ ++ #if defined(BWL_DEFAULT_PACKING) ++ /* require default structure packing */ ++ #pragma pack(pop) ++ #undef BWL_DEFAULT_PACKING ++ #else /* BWL_PACKED_SECTION */ ++ #pragma pack() ++ #endif /* BWL_PACKED_SECTION */ ++#endif /* _MSC_VER */ ++ ++ ++/* Compiler-specific directives for structure packing are declared in ++ * packed_section_start.h. This marks the end of the structure packing section, ++ * so, undef them here. ++ */ ++#undef BWL_PRE_PACKED_STRUCT ++#undef BWL_POST_PACKED_STRUCT +diff --git a/drivers/bcmdrivers/gmac/src/include/packed_section_start.h b/drivers/bcmdrivers/gmac/src/include/packed_section_start.h +new file mode 100755 +index 0000000..1899125 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch new file mode 100644 index 00000000..70c4c44f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch @@ -0,0 +1,82 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/packed_section_start.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is already defined at this ++ * point, then there is a missing include of packed_section_end.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #error "BWL_PACKED_SECTION is already defined!" ++#else ++ #define BWL_PACKED_SECTION ++#endif ++ ++ ++#if defined(_MSC_VER) ++ /* Disable compiler warning about pragma pack changing alignment. */ ++ #pragma warning(disable:4103) ++ ++ /* The Microsoft compiler uses pragmas for structure packing. Other ++ * compilers use structure attribute modifiers. Refer to ++ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined below. ++ */ ++ #if defined(BWL_DEFAULT_PACKING) ++ /* Default structure packing */ ++ #pragma pack(push, 8) ++ #else /* BWL_PACKED_SECTION */ ++ #pragma pack(1) ++ #endif /* BWL_PACKED_SECTION */ ++#endif /* _MSC_VER */ ++ ++ ++/* Declare compiler-specific directives for structure packing. */ ++#if defined(_MSC_VER) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT ++#elif defined(__GNUC__) || defined(__lint) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed)) ++#elif defined(__CC_ARM) ++ #define BWL_PRE_PACKED_STRUCT __packed ++ #define BWL_POST_PACKED_STRUCT ++#else ++ #error "Unknown compiler!" ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/include/pcicfg.h b/drivers/bcmdrivers/gmac/src/include/pcicfg.h +new file mode 100755 +index 0000000..fa01982 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch new file mode 100644 index 00000000..7fd8f492 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch @@ -0,0 +1,575 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/pcicfg.h +@@ -0,0 +1,569 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * pcicfg.h: PCI configuration constants and structures. ++ * ++ * $Id: pcicfg.h 316716 2012-02-23 04:39:13Z $ ++ */ ++ ++#ifndef _h_pcicfg_ ++#define _h_pcicfg_ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* The following inside ifndef's so we don't collide with NTDDK.H */ ++#ifndef PCI_MAX_BUS ++#define PCI_MAX_BUS 0x100 ++#endif ++#ifndef PCI_MAX_DEVICES ++#define PCI_MAX_DEVICES 0x20 ++#endif ++#ifndef PCI_MAX_FUNCTION ++#define PCI_MAX_FUNCTION 0x8 ++#endif ++ ++#ifndef PCI_INVALID_VENDORID ++#define PCI_INVALID_VENDORID 0xffff ++#endif ++#ifndef PCI_INVALID_DEVICEID ++#define PCI_INVALID_DEVICEID 0xffff ++#endif ++ ++ ++/* Convert between bus-slot-function-register and config addresses */ ++ ++#define PCICFG_BUS_SHIFT 16 /* Bus shift */ ++#define PCICFG_SLOT_SHIFT 11 /* Slot shift */ ++#define PCICFG_FUN_SHIFT 8 /* Function shift */ ++#define PCICFG_OFF_SHIFT 0 /* Register shift */ ++ ++#define PCICFG_BUS_MASK 0xff /* Bus mask */ ++#define PCICFG_SLOT_MASK 0x1f /* Slot mask */ ++#define PCICFG_FUN_MASK 7 /* Function mask */ ++#define PCICFG_OFF_MASK 0xff /* Bus mask */ ++ ++#define PCI_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \ ++ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \ ++ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \ ++ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT)) ++ ++#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK) ++#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK) ++#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK) ++#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK) ++ ++/* PCIE Config space accessing MACROS */ ++ ++#define PCIECFG_BUS_SHIFT 24 /* Bus shift */ ++#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */ ++#define PCIECFG_FUN_SHIFT 16 /* Function shift */ ++#define PCIECFG_OFF_SHIFT 0 /* Register shift */ ++ ++#define PCIECFG_BUS_MASK 0xff /* Bus mask */ ++#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */ ++#define PCIECFG_FUN_MASK 7 /* Function mask */ ++#define PCIECFG_OFF_MASK 0xfff /* Register mask */ ++ ++#define PCIE_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \ ++ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \ ++ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \ ++ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT)) ++ ++#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK) ++#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK) ++#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK) ++#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK) ++ ++/* The actual config space */ ++ ++#define PCI_BAR_MAX 6 ++ ++#define PCI_ROM_BAR 8 ++ ++#define PCR_RSVDA_MAX 2 ++ ++/* Bits in PCI bars' flags */ ++ ++#define PCIBAR_FLAGS 0xf ++#define PCIBAR_IO 0x1 ++#define PCIBAR_MEM1M 0x2 ++#define PCIBAR_MEM64 0x4 ++#define PCIBAR_PREFETCH 0x8 ++#define PCIBAR_MEM32_MASK 0xFFFFFF80 ++ ++/* pci config status reg has a bit to indicate that capability ptr is present */ ++ ++#define PCI_CAPPTR_PRESENT 0x0010 ++ ++typedef struct _pci_config_regs { ++ uint16 vendor; ++ uint16 device; ++ uint16 command; ++ uint16 status; ++ uint8 rev_id; ++ uint8 prog_if; ++ uint8 sub_class; ++ uint8 base_class; ++ uint8 cache_line_size; ++ uint8 latency_timer; ++ uint8 header_type; ++ uint8 bist; ++ uint32 base[PCI_BAR_MAX]; ++ uint32 cardbus_cis; ++ uint16 subsys_vendor; ++ uint16 subsys_id; ++ uint32 baserom; ++ uint32 rsvd_a[PCR_RSVDA_MAX]; ++ uint8 int_line; ++ uint8 int_pin; ++ uint8 min_gnt; ++ uint8 max_lat; ++ uint8 dev_dep[192]; ++} pci_config_regs; ++ ++#define SZPCR (sizeof (pci_config_regs)) ++#define MINSZPCR 64 /* offsetof (dev_dep[0] */ ++ ++#endif /* !LINUX_POSTMOGRIFY_REMOVAL */ ++/* A structure for the config registers is nice, but in most ++ * systems the config space is not memory mapped, so we need ++ * field offsetts. :-( ++ */ ++#define PCI_CFG_VID 0 ++#define PCI_CFG_DID 2 ++#define PCI_CFG_CMD 4 ++#define PCI_CFG_STAT 6 ++#define PCI_CFG_REV 8 ++#define PCI_CFG_PROGIF 9 ++#define PCI_CFG_SUBCL 0xa ++#define PCI_CFG_BASECL 0xb ++#define PCI_CFG_CLSZ 0xc ++#define PCI_CFG_LATTIM 0xd ++#define PCI_CFG_HDR 0xe ++#define PCI_CFG_BIST 0xf ++#define PCI_CFG_BAR0 0x10 ++#define PCI_CFG_BAR1 0x14 ++#define PCI_CFG_BAR2 0x18 ++#define PCI_CFG_BAR3 0x1c ++#define PCI_CFG_BAR4 0x20 ++#define PCI_CFG_BAR5 0x24 ++#define PCI_CFG_CIS 0x28 ++#define PCI_CFG_SVID 0x2c ++#define PCI_CFG_SSID 0x2e ++#define PCI_CFG_ROMBAR 0x30 ++#define PCI_CFG_CAPPTR 0x34 ++#define PCI_CFG_INT 0x3c ++#define PCI_CFG_PIN 0x3d ++#define PCI_CFG_MINGNT 0x3e ++#define PCI_CFG_MAXLAT 0x3f ++#define PCI_CFG_DEVCTRL 0xd8 ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++#ifdef __NetBSD__ ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_MEMORY ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_INPUT ++#undef PCI_CLASS_DOCK ++#endif /* __NetBSD__ */ ++ ++#ifdef EFI ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_OLD ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_SERIAL ++#undef PCI_CLASS_SATELLITE ++#endif /* EFI */ ++ ++/* Classes and subclasses */ ++ ++typedef enum { ++ PCI_CLASS_OLD = 0, ++ PCI_CLASS_DASDI, ++ PCI_CLASS_NET, ++ PCI_CLASS_DISPLAY, ++ PCI_CLASS_MMEDIA, ++ PCI_CLASS_MEMORY, ++ PCI_CLASS_BRIDGE, ++ PCI_CLASS_COMM, ++ PCI_CLASS_BASE, ++ PCI_CLASS_INPUT, ++ PCI_CLASS_DOCK, ++ PCI_CLASS_CPU, ++ PCI_CLASS_SERIAL, ++ PCI_CLASS_INTELLIGENT = 0xe, ++ PCI_CLASS_SATELLITE, ++ PCI_CLASS_CRYPT, ++ PCI_CLASS_DSP, ++ PCI_CLASS_XOR = 0xfe ++} pci_classes; ++ ++typedef enum { ++ PCI_DASDI_SCSI, ++ PCI_DASDI_IDE, ++ PCI_DASDI_FLOPPY, ++ PCI_DASDI_IPI, ++ PCI_DASDI_RAID, ++ PCI_DASDI_OTHER = 0x80 ++} pci_dasdi_subclasses; ++ ++typedef enum { ++ PCI_NET_ETHER, ++ PCI_NET_TOKEN, ++ PCI_NET_FDDI, ++ PCI_NET_ATM, ++ PCI_NET_OTHER = 0x80 ++} pci_net_subclasses; ++ ++typedef enum { ++ PCI_DISPLAY_VGA, ++ PCI_DISPLAY_XGA, ++ PCI_DISPLAY_3D, ++ PCI_DISPLAY_OTHER = 0x80 ++} pci_display_subclasses; ++ ++typedef enum { ++ PCI_MMEDIA_VIDEO, ++ PCI_MMEDIA_AUDIO, ++ PCI_MMEDIA_PHONE, ++ PCI_MEDIA_OTHER = 0x80 ++} pci_mmedia_subclasses; ++ ++typedef enum { ++ PCI_MEMORY_RAM, ++ PCI_MEMORY_FLASH, ++ PCI_MEMORY_OTHER = 0x80 ++} pci_memory_subclasses; ++ ++typedef enum { ++ PCI_BRIDGE_HOST, ++ PCI_BRIDGE_ISA, ++ PCI_BRIDGE_EISA, ++ PCI_BRIDGE_MC, ++ PCI_BRIDGE_PCI, ++ PCI_BRIDGE_PCMCIA, ++ PCI_BRIDGE_NUBUS, ++ PCI_BRIDGE_CARDBUS, ++ PCI_BRIDGE_RACEWAY, ++ PCI_BRIDGE_OTHER = 0x80 ++} pci_bridge_subclasses; ++ ++typedef enum { ++ PCI_COMM_UART, ++ PCI_COMM_PARALLEL, ++ PCI_COMM_MULTIUART, ++ PCI_COMM_MODEM, ++ PCI_COMM_OTHER = 0x80 ++} pci_comm_subclasses; ++ ++typedef enum { ++ PCI_BASE_PIC, ++ PCI_BASE_DMA, ++ PCI_BASE_TIMER, ++ PCI_BASE_RTC, ++ PCI_BASE_PCI_HOTPLUG, ++ PCI_BASE_OTHER = 0x80 ++} pci_base_subclasses; ++ ++typedef enum { ++ PCI_INPUT_KBD, ++ PCI_INPUT_PEN, ++ PCI_INPUT_MOUSE, ++ PCI_INPUT_SCANNER, ++ PCI_INPUT_GAMEPORT, ++ PCI_INPUT_OTHER = 0x80 ++} pci_input_subclasses; ++ ++typedef enum { ++ PCI_DOCK_GENERIC, ++ PCI_DOCK_OTHER = 0x80 ++} pci_dock_subclasses; ++ ++typedef enum { ++ PCI_CPU_386, ++ PCI_CPU_486, ++ PCI_CPU_PENTIUM, ++ PCI_CPU_ALPHA = 0x10, ++ PCI_CPU_POWERPC = 0x20, ++ PCI_CPU_MIPS = 0x30, ++ PCI_CPU_COPROC = 0x40, ++ PCI_CPU_OTHER = 0x80 ++} pci_cpu_subclasses; ++ ++typedef enum { ++ PCI_SERIAL_IEEE1394, ++ PCI_SERIAL_ACCESS, ++ PCI_SERIAL_SSA, ++ PCI_SERIAL_USB, ++ PCI_SERIAL_FIBER, ++ PCI_SERIAL_SMBUS, ++ PCI_SERIAL_OTHER = 0x80 ++} pci_serial_subclasses; ++ ++typedef enum { ++ PCI_INTELLIGENT_I2O ++} pci_intelligent_subclasses; ++ ++typedef enum { ++ PCI_SATELLITE_TV, ++ PCI_SATELLITE_AUDIO, ++ PCI_SATELLITE_VOICE, ++ PCI_SATELLITE_DATA, ++ PCI_SATELLITE_OTHER = 0x80 ++} pci_satellite_subclasses; ++ ++typedef enum { ++ PCI_CRYPT_NETWORK, ++ PCI_CRYPT_ENTERTAINMENT, ++ PCI_CRYPT_OTHER = 0x80 ++} pci_crypt_subclasses; ++ ++typedef enum { ++ PCI_DSP_DPIO, ++ PCI_DSP_OTHER = 0x80 ++} pci_dsp_subclasses; ++ ++typedef enum { ++ PCI_XOR_QDMA, ++ PCI_XOR_OTHER = 0x80 ++} pci_xor_subclasses; ++ ++/* Header types */ ++#define PCI_HEADER_MULTI 0x80 ++#define PCI_HEADER_MASK 0x7f ++typedef enum { ++ PCI_HEADER_NORMAL, ++ PCI_HEADER_BRIDGE, ++ PCI_HEADER_CARDBUS ++} pci_header_types; ++ ++ ++/* Overlay for a PCI-to-PCI bridge */ ++ ++#define PPB_RSVDA_MAX 2 ++#define PPB_RSVDD_MAX 8 ++ ++typedef struct _ppb_config_regs { ++ uint16 vendor; ++ uint16 device; ++ uint16 command; ++ uint16 status; ++ uint8 rev_id; ++ uint8 prog_if; ++ uint8 sub_class; ++ uint8 base_class; ++ uint8 cache_line_size; ++ uint8 latency_timer; ++ uint8 header_type; ++ uint8 bist; ++ uint32 rsvd_a[PPB_RSVDA_MAX]; ++ uint8 prim_bus; ++ uint8 sec_bus; ++ uint8 sub_bus; ++ uint8 sec_lat; ++ uint8 io_base; ++ uint8 io_lim; ++ uint16 sec_status; ++ uint16 mem_base; ++ uint16 mem_lim; ++ uint16 pf_mem_base; ++ uint16 pf_mem_lim; ++ uint32 pf_mem_base_hi; ++ uint32 pf_mem_lim_hi; ++ uint16 io_base_hi; ++ uint16 io_lim_hi; ++ uint16 subsys_vendor; ++ uint16 subsys_id; ++ uint32 rsvd_b; ++ uint8 rsvd_c; ++ uint8 int_pin; ++ uint16 bridge_ctrl; ++ uint8 chip_ctrl; ++ uint8 diag_ctrl; ++ uint16 arb_ctrl; ++ uint32 rsvd_d[PPB_RSVDD_MAX]; ++ uint8 dev_dep[192]; ++} ppb_config_regs; ++ ++ ++/* PCI CAPABILITY DEFINES */ ++#define PCI_CAP_POWERMGMTCAP_ID 0x01 ++#define PCI_CAP_MSICAP_ID 0x05 ++#define PCI_CAP_VENDSPEC_ID 0x09 ++#define PCI_CAP_PCIECAP_ID 0x10 ++ ++/* Data structure to define the Message Signalled Interrupt facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_msi { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 msgctrl; ++ uint32 msgaddr; ++} pciconfig_cap_msi; ++ ++/* Data structure to define the Power managment facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_pwrmgmt { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 pme_cap; ++ uint16 pme_sts_ctrl; ++ uint8 pme_bridge_ext; ++ uint8 data; ++} pciconfig_cap_pwrmgmt; ++ ++#define PME_CAP_PM_STATES (0x1f << 27) /* Bits 31:27 states that can generate PME */ ++#define PME_CSR_OFFSET 0x4 /* 4-bytes offset */ ++#define PME_CSR_PME_EN (1 << 8) /* Bit 8 Enable generating of PME */ ++#define PME_CSR_PME_STAT (1 << 15) /* Bit 15 PME got asserted */ ++ ++/* Data structure to define the PCIE capability */ ++typedef struct _pciconfig_cap_pcie { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 pcie_cap; ++ uint32 dev_cap; ++ uint16 dev_ctrl; ++ uint16 dev_status; ++ uint32 link_cap; ++ uint16 link_ctrl; ++ uint16 link_status; ++ uint32 slot_cap; ++ uint16 slot_ctrl; ++ uint16 slot_status; ++ uint16 root_ctrl; ++ uint16 root_cap; ++ uint32 root_status; ++} pciconfig_cap_pcie; ++ ++/* PCIE Enhanced CAPABILITY DEFINES */ ++#define PCIE_EXTCFG_OFFSET 0x100 ++#define PCIE_ADVERRREP_CAPID 0x0001 ++#define PCIE_VC_CAPID 0x0002 ++#define PCIE_DEVSNUM_CAPID 0x0003 ++#define PCIE_PWRBUDGET_CAPID 0x0004 ++ ++/* PCIE Extended configuration */ ++#define PCIE_ADV_CORR_ERR_MASK 0x114 ++#define CORR_ERR_RE (1 << 0) /* Receiver */ ++#define CORR_ERR_BT (1 << 6) /* Bad TLP */ ++#define CORR_ERR_BD (1 << 7) /* Bad DLLP */ ++#define CORR_ERR_RR (1 << 8) /* REPLAY_NUM rollover */ ++#define CORR_ERR_RT (1 << 12) /* Reply timer timeout */ ++#define ALL_CORR_ERRORS (CORR_ERR_RE | CORR_ERR_BT | CORR_ERR_BD | \ ++ CORR_ERR_RR | CORR_ERR_RT) ++ ++/* PCIE Root Control Register bits (Host mode only) */ ++#define PCIE_RC_CORR_SERR_EN 0x0001 ++#define PCIE_RC_NONFATAL_SERR_EN 0x0002 ++#define PCIE_RC_FATAL_SERR_EN 0x0004 ++#define PCIE_RC_PME_INT_EN 0x0008 ++#define PCIE_RC_CRS_EN 0x0010 ++ ++/* PCIE Root Capability Register bits (Host mode only) */ ++#define PCIE_RC_CRS_VISIBILITY 0x0001 ++ ++/* Header to define the PCIE specific capabilities in the extended config space */ ++typedef struct _pcie_enhanced_caphdr { ++ uint16 capID; ++ uint16 cap_ver : 4; ++ uint16 next_ptr : 12; ++} pcie_enhanced_caphdr; ++ ++ ++/* Everything below is BRCM HND proprietary */ ++ ++ ++/* Brcm PCI configuration registers */ ++#define cap_list rsvd_a[0] ++#define bar0_window dev_dep[0x80 - 0x40] ++#define bar1_window dev_dep[0x84 - 0x40] ++#define sprom_control dev_dep[0x88 - 0x40] ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ ++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ ++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ ++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ ++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ ++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ ++#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */ ++#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */ ++#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */ ++#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ ++ ++#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++/* ++ * PCIE GEN2 changed some of the above locations for ++ * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase ++ * BAR0 maps 32K of register space ++*/ ++#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */ ++ ++#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */ ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* On AI chips we have a second window to map DMP regs are mapped: */ ++#define PCI_16KB0_WIN2_OFFSET (4 * 1024) /* bar0 + 4K is "Window 2" */ ++ ++/* PCI_INT_STATUS */ ++#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */ ++ ++/* PCI_INT_MASK */ ++#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */ ++#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */ ++#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* PCI_SPROM_CONTROL */ ++#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ ++#define SPROM_LOCKED 0x08 /* SPROM Locked */ ++#define SPROM_BLANK 0x04 /* indicating a blank SPROM */ ++#define SPROM_WRITEEN 0x10 /* SPROM write enable */ ++#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ ++#define SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */ ++#define SPROM_OTPIN_USE 0x80 /* device OTP In use */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Bits in PCI command and status regs */ ++#define PCI_CMD_IO 0x00000001 /* I/O enable */ ++#define PCI_CMD_MEMORY 0x00000002 /* Memory enable */ ++#define PCI_CMD_MASTER 0x00000004 /* Master enable */ ++#define PCI_CMD_SPECIAL 0x00000008 /* Special cycles enable */ ++#define PCI_CMD_INVALIDATE 0x00000010 /* Invalidate? */ ++#define PCI_CMD_VGA_PAL 0x00000040 /* VGA Palate */ ++#define PCI_STAT_TA 0x08000000 /* target abort status */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define PCI_CONFIG_SPACE_SIZE 256 ++#endif /* _h_pcicfg_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/802.11.h b/drivers/bcmdrivers/gmac/src/include/proto/802.11.h +new file mode 100755 +index 0000000..db026bf diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch new file mode 100644 index 00000000..c4cab740 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch @@ -0,0 +1,2362 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/802.11.h +@@ -0,0 +1,2356 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to 802.11 ++ * ++ * $Id: 802.11.h 308961 2012-01-18 03:01:00Z $ ++ */ ++ ++#ifndef _802_11_H_ ++#define _802_11_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++#ifndef _NET_ETHERNET_H_ ++#include ++#endif ++ ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ ++ ++/* Generic 802.11 frame constants */ ++#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ ++#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ ++#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ ++#define DOT11_FCS_LEN 4 /* d11 FCS length */ ++#define DOT11_ICV_LEN 4 /* d11 ICV length */ ++#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ ++#define DOT11_QOS_LEN 2 /* d11 QoS length */ ++#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ ++ ++#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ ++#define DOT11_IV_LEN 4 /* d11 IV length */ ++#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ ++#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ ++#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ ++#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ ++ ++/* Includes MIC */ ++#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ ++/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ ++#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ ++ DOT11_QOS_LEN + \ ++ DOT11_IV_AES_CCM_LEN + \ ++ DOT11_MAX_MPDU_BODY_LEN + \ ++ DOT11_ICV_LEN + \ ++ DOT11_FCS_LEN) /* d11 max MPDU length */ ++ ++#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ ++ ++/* dot11RTSThreshold */ ++#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ ++#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ ++ ++/* dot11FragmentationThreshold */ ++#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ ++#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength ++ * of the attached PHY ++ */ ++#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ ++ ++/* dot11BeaconPeriod */ ++#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ ++ ++/* dot11DTIMPeriod */ ++#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ ++#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ ++ ++/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ ++#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ ++#define DOT11_OUI_LEN 3 /* d11 OUI length */ ++BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { ++ uint8 dsap; /* always 0xAA */ ++ uint8 ssap; /* always 0xAA */ ++ uint8 ctl; /* always 0x03 */ ++ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 ++ * Bridge-Tunnel: 0x00 0x00 0xF8 ++ */ ++ uint16 type; /* ethertype */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* RFC1042 header used by 802.11 per 802.1H */ ++#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ ++ ++/* Generic 802.11 MAC header */ ++/* ++ * N.B.: This struct reflects the full 4 address 802.11 MAC header. ++ * The fields are defined such that the shorter 1, 2, and 3 ++ * address headers just use the first k fields. ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr a1; /* address 1 */ ++ struct ether_addr a2; /* address 2 */ ++ struct ether_addr a3; /* address 3 */ ++ uint16 seq; /* sequence control */ ++ struct ether_addr a4; /* address 4 */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* Control frames */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* AID */ ++ struct ether_addr bssid; /* receiver address, STA in AP */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr bssid; /* transmitter address, STA in AP */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ ++ ++/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling ++* category+OUI+vendor specific content ( this can be variable) ++*/ ++BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1040]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; ++ ++/* generic vender specific action frame with variable length */ ++BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t; ++#define DOT11_ACTION_VS_HDR_LEN 6 ++ ++#define BCM_ACTION_OUI_BYTE0 0x00 ++#define BCM_ACTION_OUI_BYTE1 0x90 ++#define BCM_ACTION_OUI_BYTE2 0x4c ++ ++/* BA/BAR Control parameters */ ++#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ ++#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ ++#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ ++ ++#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ ++#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ ++ ++#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ ++#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ ++ ++#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ ++#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ ++ ++/* control frame header (BA/BAR) */ ++BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ ++ ++/* BAR frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_bar { ++ uint16 bar_control; /* BAR Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BAR_LEN 4 /* BAR frame payload length */ ++ ++#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ ++#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ ++/* BA frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_ba { ++ uint16 ba_control; /* BA Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */ ++ ++/* Management frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr da; /* receiver address */ ++ struct ether_addr sa; /* transmitter address */ ++ struct ether_addr bssid; /* BSS ID */ ++ uint16 seq; /* sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ ++ ++/* Management frame payloads */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { ++ uint32 timestamp[2]; ++ uint16 beacon_interval; ++ uint16 capability; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_auth { ++ uint16 alg; /* algorithm */ ++ uint16 seq; /* sequence control */ ++ uint16 status; /* status code */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++ struct ether_addr ap; /* Current AP address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { ++ uint16 capability; /* capability information */ ++ uint16 status; /* status code */ ++ uint16 aid; /* association ID */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_measure { ++ uint8 category; ++ uint8 action; ++ uint8 token; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { ++ uint8 category; ++ uint8 action; ++ uint8 ch_width; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { ++ uint8 category; ++ uint8 action; ++ uint8 control; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query { ++ uint8 category; ++ uint8 action; ++ uint16 id; ++} BWL_POST_PACKED_STRUCT; ++ ++#define SM_PWRSAVE_ENABLE 1 ++#define SM_PWRSAVE_MODE 2 ++ ++/* ************* 802.11h related definitions. ************* */ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { ++ uint8 id; ++ uint8 len; ++ uint8 power; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cnst dot11_power_cnst_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cap { ++ uint8 min; ++ uint8 max; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cap dot11_power_cap_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { ++ uint8 id; ++ uint8 len; ++ uint8 tx_pwr; ++ uint8 margin; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_tpc_rep dot11_tpc_rep_t; ++#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { ++ uint8 id; ++ uint8 len; ++ uint8 first_channel; ++ uint8 num_channels; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_supp_channels dot11_supp_channels_t; ++ ++/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband ++ * offset for 40MHz operation. The possible 3 values are: ++ * 1 = above control channel ++ * 3 = below control channel ++ * 0 = no extension channel ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_extch { ++ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ ++ uint8 len; /* IE length */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extch dot11_extch_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; ++ ++#define BRCM_EXTCH_IE_LEN 5 ++#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ ++#define DOT11_EXTCH_IE_LEN 1 ++#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ ++#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ ++#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ ++#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { ++ uint8 category; ++ uint8 action; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_FRMHDR_LEN 2 ++ ++/* CSA IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { ++ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_channel_switch dot11_chan_switch_ie_t; ++ ++#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ ++/* CSA mode - 802.11h-2003 $7.3.2.20 */ ++#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ ++#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { ++ uint8 category; ++ uint8 action; ++ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ ++ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_csa_body { ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 reg; /* regulatory class */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* 11n Extended Channel Switch IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { ++ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ext_csa dot11_ext_csa_ie_t; ++#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { ++ uint8 id; ++ uint8 len; ++ uint8 info; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_coex dot11_obss_coex_t; ++#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */ ++ ++#define DOT11_OBSS_COEX_INFO_REQ 0x01 ++#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 ++#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { ++ uint8 id; ++ uint8 len; ++ uint8 regclass; ++ uint8 chanlist[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; ++#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { ++ uint8 id; ++ uint8 len; ++ uint8 cap[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap_ie dot11_extcap_ie_t; ++ ++#define DOT11_EXTCAP_LEN_MAX 7 ++#define DOT11_EXTCAP_LEN_COEX 1 ++#define DOT11_EXTCAP_LEN_BT 3 ++#define DOT11_EXTCAP_LEN_IW 4 ++#define DOT11_EXTCAP_LEN_SI 6 ++ ++#define DOT11_EXTCAP_LEN_TDLS 5 ++BWL_PRE_PACKED_STRUCT struct dot11_extcap { ++ uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap dot11_extcap_t; ++ ++/* TDLS Capabilities */ ++#define TDLS_CAP_TDLS 37 /* TDLS support */ ++#define TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */ ++#define TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */ ++#define TDLS_CAP_CH_SW 30 /* TDLS Channel switch */ ++#define TDLS_CAP_PROH 38 /* TDLS prohibited */ ++#define TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */ ++ ++#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */ ++ ++/* 802.11h/802.11k Measurement Request/Report IEs */ ++/* Measurement Type field */ ++#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ ++#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ ++#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */ ++#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */ ++#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */ ++#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */ ++#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */ ++#define DOT11_MEASURE_TYPE_STATS 7 /* d11 measurement STA Statistics type */ ++#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ ++#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */ ++#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */ ++ ++/* Measurement Request Modes */ ++#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */ ++#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ ++#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ ++#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ ++#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */ ++/* Measurement Report Modes */ ++#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ ++#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ ++#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ ++/* Basic Measurement Map bits */ ++#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ ++#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ ++#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ ++#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ ++#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_req { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_req dot11_meas_req_t; ++#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ ++/* length of Measure Request IE data not including variable len */ ++#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ BWL_PRE_PACKED_STRUCT union ++ { ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++ } BWL_POST_PACKED_STRUCT basic; ++ uint8 data[1]; ++ } BWL_POST_PACKED_STRUCT rep; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep dot11_meas_rep_t; ++ ++/* length of Measure Report IE data not including variable len */ ++#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; ++#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_quiet { ++ uint8 id; ++ uint8 len; ++ uint8 count; /* TBTTs until beacon interval in quiet starts */ ++ uint8 period; /* Beacon intervals between periodic quiet periods ? */ ++ uint16 duration; /* Length of quiet period, in TU's */ ++ uint16 offset; /* TU's offset from TBTT in Count field */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_quiet dot11_quiet_t; ++ ++BWL_PRE_PACKED_STRUCT struct chan_map_tuple { ++ uint8 channel; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct chan_map_tuple chan_map_tuple_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { ++ uint8 id; ++ uint8 len; ++ uint8 eaddr[ETHER_ADDR_LEN]; ++ uint8 interval; ++ chan_map_tuple_t map[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; ++ ++/* WME Elements */ ++#define WME_OUI "\x00\x50\xf2" /* WME OUI */ ++#define WME_OUI_LEN 3 ++#define WME_OUI_TYPE 2 /* WME type */ ++#define WME_TYPE 2 /* WME type, deprecated */ ++#define WME_SUBTYPE_IE 0 /* Information Element */ ++#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ ++#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ ++#define WME_VER 1 /* WME version */ ++ ++/* WME Access Category Indices (ACIs) */ ++#define AC_BE 0 /* Best Effort */ ++#define AC_BK 1 /* Background */ ++#define AC_VI 2 /* Video */ ++#define AC_VO 3 /* Voice */ ++#define AC_COUNT 4 /* number of ACs */ ++ ++typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ ++ ++#define AC_BITMAP_NONE 0x0 /* No ACs */ ++#define AC_BITMAP_ALL 0xf /* All ACs */ ++#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) ++#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) ++#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) ++ ++/* WME Information Element (IE) */ ++BWL_PRE_PACKED_STRUCT struct wme_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_ie wme_ie_t; ++#define WME_IE_LEN 7 /* WME IE length */ ++ ++BWL_PRE_PACKED_STRUCT struct edcf_acparam { ++ uint8 ACI; ++ uint8 ECW; ++ uint16 TXOP; /* stored in network order (ls octet first) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct edcf_acparam edcf_acparam_t; ++ ++/* WME Parameter Element (PE) */ ++BWL_PRE_PACKED_STRUCT struct wme_param_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_param_ie wme_param_ie_t; ++#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ ++ ++/* QoS Info field for IE as sent from AP */ ++#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ ++#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ ++#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ ++#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ ++ ++/* QoS Info field for IE as sent from STA */ ++#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ ++#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ ++#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ ++#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ ++#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ ++#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ ++#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ ++#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ ++#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ ++#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ ++#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ ++#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ ++ ++/* ACI */ ++#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ ++#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ ++#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ ++#define EDCF_ACM_MASK 0x10 /* ACM mask */ ++#define EDCF_ACI_MASK 0x60 /* ACI mask */ ++#define EDCF_ACI_SHIFT 5 /* ACI shift */ ++#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ ++ ++/* ECW */ ++#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ ++#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ ++#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ ++#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ ++ ++/* TXOP */ ++#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ ++#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++ ++/* Default BE ACI value for non-WME connection STA */ ++#define NON_EDCF_AC_BE_ACI_STA 0x02 ++ ++/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ ++#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ ++#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ ++#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ ++ ++/* Default EDCF parameters that AP uses; WMM draft Table 14 */ ++#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ ++#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ ++#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ ++ ++/* EDCA Parameter IE */ ++BWL_PRE_PACKED_STRUCT struct edca_param_ie { ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct edca_param_ie edca_param_ie_t; ++#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */ ++ ++/* QoS Capability IE */ ++BWL_PRE_PACKED_STRUCT struct qos_cap_ie { ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct qos_cap_ie qos_cap_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { ++ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ ++ uint8 length; ++ uint16 station_count; /* total number of STAs associated */ ++ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ ++ uint16 aac; /* available admission capacity */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; ++#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ ++ ++/* nom_msdu_size */ ++#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ ++#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ ++ ++/* surplus_bandwidth */ ++/* Represented as 3 bits of integer, binary point, 13 bits fraction */ ++#define INTEGER_SHIFT 13 /* integer shift */ ++#define FRACTION_MASK 0x1FFF /* fraction mask */ ++ ++/* Management Notification Frame */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_notification { ++ uint8 category; /* DOT11_ACTION_NOTIFICATION */ ++ uint8 action; ++ uint8 token; ++ uint8 status; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ ++ ++/* Timeout Interval IE */ ++BWL_PRE_PACKED_STRUCT struct ti_ie { ++ uint8 ti_type; ++ uint32 ti_val; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ti_ie ti_ie_t; ++#define TI_TYPE_REASSOC_DEADLINE 1 ++#define TI_TYPE_KEY_LIFETIME 2 ++ ++/* WME Action Codes */ ++#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ ++#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ ++#define WME_DELTS_REQUEST 2 /* WME DELTS request */ ++ ++/* WME Setup Response Status Codes */ ++#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ ++#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ ++#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ ++ ++/* Macro to take a pointer to a beacon or probe response ++ * body and return the char* pointer to the SSID info element ++ */ ++#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) ++ ++/* Authentication frame payload constants */ ++#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ ++#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */ ++#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */ ++ ++/* Frame control macros */ ++#define FC_PVER_MASK 0x3 /* PVER mask */ ++#define FC_PVER_SHIFT 0 /* PVER shift */ ++#define FC_TYPE_MASK 0xC /* type mask */ ++#define FC_TYPE_SHIFT 2 /* type shift */ ++#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ ++#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ ++#define FC_TODS 0x100 /* to DS */ ++#define FC_TODS_SHIFT 8 /* to DS shift */ ++#define FC_FROMDS 0x200 /* from DS */ ++#define FC_FROMDS_SHIFT 9 /* from DS shift */ ++#define FC_MOREFRAG 0x400 /* more frag. */ ++#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ ++#define FC_RETRY 0x800 /* retry */ ++#define FC_RETRY_SHIFT 11 /* retry shift */ ++#define FC_PM 0x1000 /* PM */ ++#define FC_PM_SHIFT 12 /* PM shift */ ++#define FC_MOREDATA 0x2000 /* more data */ ++#define FC_MOREDATA_SHIFT 13 /* more data shift */ ++#define FC_WEP 0x4000 /* WEP */ ++#define FC_WEP_SHIFT 14 /* WEP shift */ ++#define FC_ORDER 0x8000 /* order */ ++#define FC_ORDER_SHIFT 15 /* order shift */ ++ ++/* sequence control macros */ ++#define SEQNUM_SHIFT 4 /* seq. number shift */ ++#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ ++#define FRAGNUM_MASK 0xF /* frag. number mask */ ++ ++/* Frame Control type/subtype defs */ ++ ++/* FC Types */ ++#define FC_TYPE_MNG 0 /* management type */ ++#define FC_TYPE_CTL 1 /* control type */ ++#define FC_TYPE_DATA 2 /* data type */ ++ ++/* Management Subtypes */ ++#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ ++#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ ++#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ ++#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ ++#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ ++#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ ++#define FC_SUBTYPE_BEACON 8 /* beacon */ ++#define FC_SUBTYPE_ATIM 9 /* ATIM */ ++#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ ++#define FC_SUBTYPE_AUTH 11 /* authentication */ ++#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ ++#define FC_SUBTYPE_ACTION 13 /* action */ ++#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ ++ ++/* Control Subtypes */ ++#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ ++#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ ++#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ ++#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ ++#define FC_SUBTYPE_RTS 11 /* RTS */ ++#define FC_SUBTYPE_CTS 12 /* CTS */ ++#define FC_SUBTYPE_ACK 13 /* ACK */ ++#define FC_SUBTYPE_CF_END 14 /* CF-END */ ++#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ ++ ++/* Data Subtypes */ ++#define FC_SUBTYPE_DATA 0 /* Data */ ++#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ ++#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ ++#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_NULL 4 /* Null */ ++#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ ++#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ ++#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ ++#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ ++#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ ++#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ ++ ++/* Data Subtype Groups */ ++#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) ++#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) ++#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) ++#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) ++ ++/* Type/Subtype Combos */ ++#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ ++ ++#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ ++ ++#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ ++#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ ++ ++#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ ++#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ ++#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ ++#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ ++#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ ++#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ ++#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ ++#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ ++#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ ++#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ ++#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ ++#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ ++ ++#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ ++#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ ++#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ ++#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ ++#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ ++#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ ++#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ ++#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ ++#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ ++ ++#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ ++#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ ++#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ ++#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ ++#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ ++ ++/* QoS Control Field */ ++ ++/* 802.1D Priority */ ++#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ ++#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ ++#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ ++ ++/* Traffic Identifier */ ++#define QOS_TID_SHIFT 0 /* QoS TID shift */ ++#define QOS_TID_MASK 0x000f /* QoS TID mask */ ++#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ ++ ++/* End of Service Period (U-APSD) */ ++#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ ++#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ ++#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ ++ ++/* Ack Policy */ ++#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ ++#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ ++#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ ++#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ ++#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ ++#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ ++#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ ++ ++/* A-MSDU flag */ ++#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ ++#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ ++ ++/* Management Frames */ ++ ++/* Management Frame Constants */ ++ ++/* Fixed fields */ ++#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ ++#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ ++#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ ++#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ ++#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ ++#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ ++#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ ++#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ ++#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ ++#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ ++ ++/* DUR/ID field in assoc resp is 0xc000 | AID */ ++#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ ++ ++/* Reason Codes */ ++#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ ++#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ ++#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */ ++#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station ++ * is leaving (or has left) IBSS or ESS ++ */ ++#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ ++#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle ++ * all currently associated stations ++ */ ++#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from ++ * nonauthenticated station ++ */ ++#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from ++ * nonassociated station ++ */ ++#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is ++ * leaving (or has left) BSS ++ */ ++#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not ++ * authenticated with responding station ++ */ ++#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ ++#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ ++/* 12 is unused */ ++ ++/* 32-39 are QSTA specific reasons added in 11e */ ++#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ ++#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ ++#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ ++#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ ++#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ ++#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ ++#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ ++#define DOT11_RC_TIMEOUT 39 /* timeout */ ++ ++#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ ++ ++#define DOT11_RC_TDLS_PEER_UNREACH 25 ++#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 ++ ++/* Status Codes */ ++#define DOT11_SC_SUCCESS 0 /* Successful */ ++#define DOT11_SC_FAILURE 1 /* Unspecified failure */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */ ++ /* schedule provided */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */ ++#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */ ++#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */ ++#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */ ++#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested ++ * capabilities in the Capability ++ * Information field ++ */ ++#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability ++ * to confirm that association exists ++ */ ++#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason ++ * outside the scope of this standard ++ */ ++#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support ++ * the specified authentication ++ * algorithm ++ */ ++#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame ++ * with authentication transaction ++ * sequence number out of expected ++ * sequence ++ */ ++#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of ++ * challenge failure ++ */ ++#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout ++ * waiting for next frame in sequence ++ */ ++#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is ++ * unable to handle additional ++ * associated stations ++ */ ++#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting ++ * station not supporting all of the ++ * data rates in the BSSBasicRateSet ++ * parameter ++ */ ++#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting ++ * station not supporting the Short ++ * Preamble option ++ */ ++#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting ++ * station not supporting the PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting ++ * station not supporting the Channel ++ * Agility option ++ */ ++#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum ++ * Management capability is required. ++ */ ++#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info ++ * in the Power Cap element is ++ * unacceptable. ++ */ ++#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info ++ * in the Supported Channel element is ++ * unacceptable ++ */ ++#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting ++ * station not supporting the Short Slot ++ * Time option ++ */ ++#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting ++ * station not supporting the ER-PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting ++ * station not supporting the DSS-OFDM ++ * option ++ */ ++#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP ++ * being unable to reach the R0 Key Holder ++ */ ++#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later ++ */ ++#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management ++ * frame policy violation ++ */ ++ ++#define DOT11_SC_DECLINED 37 /* request declined */ ++#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ ++#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */ ++#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */ ++#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */ ++#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */ ++#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */ ++#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */ ++#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */ ++ ++#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */ ++#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */ ++#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */ ++ ++/* Info Elts, length of INFORMATION portion of Info Elts */ ++#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ ++#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ ++ ++/* TIM Info element has 3 bytes fixed info in INFORMATION field, ++ * followed by 1 to 251 bytes of Partial Virtual Bitmap ++ */ ++#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ ++#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ ++#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ ++#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ ++#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ ++ ++/* TLV defines */ ++#define TLV_TAG_OFF 0 /* tag offset */ ++#define TLV_LEN_OFF 1 /* length offset */ ++#define TLV_HDR_LEN 2 /* header length */ ++#define TLV_BODY_OFF 2 /* body offset */ ++ ++/* Management Frame Information Element IDs */ ++#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ ++#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ ++#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ ++#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ ++#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ ++#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ ++#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ ++#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ ++#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ ++#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ ++#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ ++#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ ++#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */ ++#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ ++#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ ++#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ ++#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ ++#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ ++#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ ++#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ ++#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ ++#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ ++#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ ++#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ ++#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ ++#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ ++#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */ ++#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */ ++#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ ++#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ ++#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ ++#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */ ++#define DOT11_MNG_NBR_REP_ID 52 /* 11k Neighbor report id */ ++#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */ ++#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */ ++#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */ ++#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */ ++#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */ ++#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ ++#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */ ++#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */ ++#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */ ++#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */ ++#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */ ++#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */ ++#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */ ++#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */ ++#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */ ++#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */ ++#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */ ++#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */ ++#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */ ++#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */ ++#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */ ++#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */ ++#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */ ++#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */ ++#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */ ++#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */ ++#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */ ++ ++#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ ++#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ ++/* should start using this one instead of above two */ ++#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ ++ ++/* Rate element Basic flag and rate mask */ ++#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ ++#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ ++ ++/* ERP info element bit values */ ++#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ ++#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present ++ *in the BSS ++ */ ++#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ++ *ERP-OFDM frames ++ */ ++#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, ++ * 1 == not allowed ++ */ ++/* TS Delay element offset & size */ ++#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ ++#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ ++ ++/* Capability Information Field */ ++#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ ++#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ ++#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ ++#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ ++#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ ++#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ ++#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ ++#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ ++#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ ++#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ ++#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */ ++#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ ++ ++/* Extended capabilities IE bitfields */ ++/* 20/40 BSS Coexistence Management support bit position */ ++#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0 ++/* scheduled PSMP support bit position */ ++#define DOT11_EXT_CAP_SPSMP 6 ++/* BSS Transition Management support bit position */ ++#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 ++/* Interworking support bit position */ ++#define DOT11_EXT_CAP_IW 31 ++/* service Interval granularity bit position and mask */ ++#define DOT11_EXT_CAP_SI 41 ++#define DOT11_EXT_CAP_SI_MASK 0x0E ++ ++/* ++ * Action Frame Constants ++ */ ++#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */ ++#define DOT11_ACTION_CAT_OFF 0 /* category offset */ ++#define DOT11_ACTION_ACT_OFF 1 /* action offset */ ++ ++/* Action Category field (sec 7.3.1.11) */ ++#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */ ++#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */ ++#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */ ++#define DOT11_ACTION_CAT_QOS 1 /* category QoS */ ++#define DOT11_ACTION_CAT_DLS 2 /* category DLS */ ++#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */ ++#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */ ++#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */ ++#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */ ++#define DOT11_ACTION_CAT_HT 7 /* category for HT */ ++#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */ ++#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */ ++#define DOT11_ACTION_CAT_BSSMGMT 10 /* category for BSS transition management */ ++#define DOT11_ACTION_NOTIFICATION 17 ++#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */ ++#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */ ++ ++/* Spectrum Management Action IDs (sec 7.4.1) */ ++#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */ ++#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */ ++#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */ ++#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */ ++#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */ ++ ++/* HT action ids */ ++#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ ++#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ ++ ++/* Public action ids */ ++#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */ ++#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++ ++/* Block Ack action types */ ++#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ ++#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ ++#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ ++ ++/* ADDBA action parameters */ ++#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ ++#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ ++#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ ++#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ ++#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ ++#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ ++#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ ++ ++#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ ++#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ ++ ++/* Fast Transition action types */ ++#define DOT11_FT_ACTION_FT_RESERVED 0 ++#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */ ++#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */ ++ ++/* DLS action types */ ++#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */ ++#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */ ++#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */ ++ ++/* Wireless Network Management (WNM) action types */ ++#define DOT11_WNM_ACTION_EVENT_REQ 0 ++#define DOT11_WNM_ACTION_EVENT_REP 1 ++#define DOT11_WNM_ACTION_DIAG_REQ 2 ++#define DOT11_WNM_ACTION_DIAG_REP 3 ++#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 ++#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 ++#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 ++#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 ++#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 ++#define DOT11_WNM_ACTION_FMS_REQ 9 ++#define DOT11_WNM_ACTION_FMS_RESP 10 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 ++#define DOT11_WNM_ACTION_TFS_REQ 13 ++#define DOT11_WNM_ACTION_TFS_RESP 14 ++#define DOT11_WNM_ACTION_TFS_NOTIFY 15 ++#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 ++#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 ++#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 ++#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 ++#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 ++#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 ++#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 ++#define DOT11_WNM_ACTION_DMS_REQ 23 ++#define DOT11_WNM_ACTION_DMS_RESP 24 ++#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 ++#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 ++#define DOT11_WNM_ACTION_NOTFCTN_RES 27 ++ ++#define DOT11_MNG_COUNTRY_ID_LEN 3 ++ ++/* DLS Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_req { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint16 cap; /* capability */ ++ uint16 timeout; /* timeout value */ ++ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_req dot11_dls_req_t; ++#define DOT11_DLS_REQ_LEN 18 /* Fixed length */ ++ ++/* DLS response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ uint16 status; /* status code field */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint8 data[1]; /* optional: capability, rate ... */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_resp dot11_dls_resp_t; ++#define DOT11_DLS_RESP_LEN 16 /* Fixed length */ ++ ++ ++/* BSS Management Transition Query frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_query (6) */ ++ uint8 token; /* dialog token */ ++ uint8 reason; /* transition query reason */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; ++#define DOT11_BSS_TRANS_QUERY_LEN 4 /* Fixed length */ ++ ++/* BSS Management Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_req (7) */ ++ uint8 token; /* dialog token */ ++ uint8 reqmode; /* transition request mode */ ++ uint16 disassoc_tmr; /* disassociation timer */ ++ uint8 validity_intrvl; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; ++#define DOT11_BSS_TRANS_REQ_LEN 7 /* Fixed length */ ++ ++#define DOT11_BSS_TERM_DUR_LEN 12 /* Fixed length if present */ ++ ++ ++/* BSS Mgmt Transition Request Mode Field - 802.11v */ ++#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 ++#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 ++#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 ++#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 ++#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 ++ ++ ++/* BSS Management transition response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_res (8) */ ++ uint8 token; /* dialog token */ ++ uint8 status; /* transition status */ ++ uint8 term_delay; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; ++#define DOT11_BSS_TRANS_RES_LEN 5 /* Fixed length */ ++ ++/* BSS Mgmt Transition Response Status Field */ ++#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 ++#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 ++ ++ ++/* Neighbor Report BSSID Information Field */ ++#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 ++#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 ++#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 ++ ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 ++ ++/* Neighbor Report Subelements */ ++#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 ++ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_req { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint8 token; /* identifier */ ++ uint16 addba_param_set; /* parameter set */ ++ uint16 timeout; /* timeout in seconds */ ++ uint16 start_seqnum; /* starting sequence number */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_req dot11_addba_req_t; ++#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba resp */ ++ uint8 token; /* identifier */ ++ uint16 status; /* status of add request */ ++ uint16 addba_param_set; /* negotiated parameter set */ ++ uint16 timeout; /* negotiated timeout in seconds */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_resp dot11_addba_resp_t; ++#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ ++ ++/* DELBA action parameters */ ++#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ ++#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ ++#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ ++#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_delba { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint16 delba_param_set; /* paarmeter set */ ++ uint16 reason; /* reason for dellba */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_delba dot11_delba_t; ++#define DOT11_DELBA_LEN 6 /* length of delba frame */ ++ ++/* SA Query action field value */ ++#define SA_QUERY_REQUEST 0 ++#define SA_QUERY_RESPONSE 1 ++ ++/* ************* 802.11r related definitions. ************* */ ++ ++/* Over-the-DS Fast Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_req { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft req */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_req dot11_ft_req_t; ++#define DOT11_FT_REQ_FIXED_LEN 14 ++ ++/* Over-the-DS Fast Transition Response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_res { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft resp */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint16 status; /* status code */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_res dot11_ft_res_t; ++#define DOT11_FT_RES_FIXED_LEN 16 ++ ++ ++/* ************* 802.11k related definitions. ************* */ ++ ++/* Radio measurements enabled capability ie */ ++ ++#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */ ++BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { ++ uint8 cap[DOT11_RRM_CAP_LEN]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; ++ ++/* Bitmap definitions for cap ie */ ++#define DOT11_RRM_CAP_LINK 0 ++#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1 ++#define DOT11_RRM_CAP_PARALLEL 2 ++#define DOT11_RRM_CAP_REPEATED 3 ++#define DOT11_RRM_CAP_BCN_PASSIVE 4 ++#define DOT11_RRM_CAP_BCN_ACTIVE 5 ++#define DOT11_RRM_CAP_BCN_TABLE 6 ++#define DOT11_RRM_CAP_BCN_REP_COND 7 ++#define DOT11_RRM_CAP_AP_CHANREP 16 ++ ++ ++/* Operating Class (formerly "Regulatory Class") definitions */ ++#define DOT11_OP_CLASS_NONE 255 ++ ++ ++/* Radio Measurements action ids */ ++#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */ ++#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */ ++#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */ ++#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */ ++#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */ ++#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */ ++ ++/* Generic radio measurement action frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_action { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_action dot11_rm_action_t; ++#define DOT11_RM_ACTION_LEN 3 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint16 reps; /* no. of repetitions */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq dot11_rmreq_t; ++#define DOT11_RMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_ie { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_ie dot11_rm_ie_t; ++#define DOT11_RM_IE_LEN 5 ++ ++/* Definitions for "mode" bits in rm req */ ++#define DOT11_RMREQ_MODE_PARALLEL 1 ++#define DOT11_RMREQ_MODE_ENABLE 2 ++#define DOT11_RMREQ_MODE_REQUEST 4 ++#define DOT11_RMREQ_MODE_REPORT 8 ++#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */ ++ ++/* Definitions for "mode" bits in rm rep */ ++#define DOT11_RMREP_MODE_LATE 1 ++#define DOT11_RMREP_MODE_INCAPABLE 2 ++#define DOT11_RMREP_MODE_REFUSED 4 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 reg; ++ uint8 channel; ++ uint16 interval; ++ uint16 duration; ++ uint8 bcn_mode; ++ struct ether_addr bssid; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t; ++#define DOT11_RMREQ_BCN_LEN 18 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn { ++ uint8 reg; ++ uint8 channel; ++ uint32 starttime[2]; ++ uint16 duration; ++ uint8 frame_info; ++ uint8 rcpi; ++ uint8 rsni; ++ struct ether_addr bssid; ++ uint8 antenna_id; ++ uint32 parent_tsf; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; ++#define DOT11_RMREP_BCN_LEN 26 ++ ++/* Beacon request measurement mode */ ++#define DOT11_RMREQ_BCN_PASSIVE 0 ++#define DOT11_RMREQ_BCN_ACTIVE 1 ++#define DOT11_RMREQ_BCN_TABLE 2 ++ ++/* Sub-element IDs for Beacon Request */ ++#define DOT11_RMREQ_BCN_SSID_ID 0 ++#define DOT11_RMREQ_BCN_REPINFO_ID 1 ++#define DOT11_RMREQ_BCN_REPDET_ID 2 ++#define DOT11_RMREQ_BCN_REQUEST_ID 10 ++#define DOT11_RMREQ_BCN_APCHREP_ID 51 ++ ++/* Reporting Detail element definition */ ++#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ ++#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */ ++#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */ ++ ++/* Sub-element IDs for Beacon Report */ ++#define DOT11_RMREP_BCN_FRM_BODY 1 ++ ++/* Neighbor measurement report */ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { ++ struct ether_addr bssid; ++ uint32 bssid_info; ++ uint8 reg; ++ uint8 channel; ++ uint8 phytype; ++ uchar sub_elements[1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; ++#define DOT11_RMREP_NBR_LEN 13 ++ ++/* MLME Enumerations */ ++#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ ++#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ ++#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ ++#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ ++#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ ++ ++/* Link Measurement */ ++BWL_PRE_PACKED_STRUCT struct dot11_lmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 txpwr; /* Transmit Power Used */ ++ uint8 maxtxpwr; /* Max Transmit Power */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmreq dot11_lmreq_t; ++#define DOT11_LMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_lmrep { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ dot11_tpc_rep_t tpc; /* TPC element */ ++ uint8 rxant; /* Receive Antenna ID */ ++ uint8 txant; /* Transmit Antenna ID */ ++ uint8 rcpi; /* RCPI */ ++ uint8 rsni; /* RSNI */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmrep dot11_lmrep_t; ++#define DOT11_LMREP_LEN 11 ++ ++/* 802.11 BRCM "Compromise" Pre N constants */ ++#define PREN_PREAMBLE 24 /* green field preamble time */ ++#define PREN_MM_EXT 12 /* extra mixed mode preamble time */ ++#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ ++ ++/* 802.11N PHY constants */ ++#define RIFS_11N_TIME 2 /* NPHY RIFS time */ ++ ++/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3 ++ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2 ++ */ ++/* HT-SIG1 */ ++#define HT_SIG1_MCS_MASK 0x00007F ++#define HT_SIG1_CBW 0x000080 ++#define HT_SIG1_HT_LENGTH 0xFFFF00 ++ ++/* HT-SIG2 */ ++#define HT_SIG2_SMOOTHING 0x000001 ++#define HT_SIG2_NOT_SOUNDING 0x000002 ++#define HT_SIG2_RESERVED 0x000004 ++#define HT_SIG2_AGGREGATION 0x000008 ++#define HT_SIG2_STBC_MASK 0x000030 ++#define HT_SIG2_STBC_SHIFT 4 ++#define HT_SIG2_FEC_CODING 0x000040 ++#define HT_SIG2_SHORT_GI 0x000080 ++#define HT_SIG2_ESS_MASK 0x000300 ++#define HT_SIG2_ESS_SHIFT 8 ++#define HT_SIG2_CRC 0x03FC00 ++#define HT_SIG2_TAIL 0x1C0000 ++ ++/* 802.11 A PHY constants */ ++#define APHY_SLOT_TIME 9 /* APHY slot time */ ++#define APHY_SIFS_TIME 16 /* APHY SIFS time */ ++#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ ++#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ ++#define APHY_SIGNAL_TIME 4 /* APHY signal time */ ++#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ ++#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ ++#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ ++#define APHY_CWMIN 15 /* APHY cwmin */ ++ ++/* 802.11 B PHY constants */ ++#define BPHY_SLOT_TIME 20 /* BPHY slot time */ ++#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ ++#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ ++#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ ++#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ ++#define BPHY_CWMIN 31 /* BPHY cwmin */ ++ ++/* 802.11 G constants */ ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ ++ ++#define PHY_CWMAX 1023 /* PHY cwmax */ ++ ++#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ ++ ++/* 802.11 AC (VHT) constants */ ++ ++typedef int vht_group_id_t; ++ ++/* for VHT-A1 */ ++/* SIG-A1 reserved bits */ ++#define VHT_SIGA1_CONST_MASK 0x800004 ++ ++#define VHT_SIGA1_20MHZ_VAL 0x000000 ++#define VHT_SIGA1_40MHZ_VAL 0x000001 ++#define VHT_SIGA1_80MHZ_VAL 0x000002 ++#define VHT_SIGA1_160MHZ_VAL 0x000003 ++ ++#define VHT_SIGA1_STBC 0x000008 ++ ++#define VHT_SIGA1_GID_MAX_GID 0x3f ++#define VHT_SIGA1_GID_SHIFT 4 ++#define VHT_SIGA1_GID_TO_AP 0x00 ++#define VHT_SIGA1_GID_NOT_TO_AP 0x3f ++ ++#define VHT_SIGA1_NSTS_SHIFT 10 ++#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 ++ ++#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 ++ ++/* for VHT-A2 */ ++#define VHT_SIGA2_GI_NONE 0x000000 ++#define VHT_SIGA2_GI_SHORT 0x000001 ++#define VHT_SIGA2_GI_W_MOD10 0x000002 ++#define VHT_SIGA2_CODING_LDPC 0x000004 ++#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 ++#define VHT_SIGA2_MCS_SHIFT 4 ++ ++#define VHT_SIGA2_B9_RESERVED 0x000200 ++#define VHT_SIGA2_TAIL_MASK 0xfc0000 ++#define VHT_SIGA2_TAIL_VALUE 0x000000 ++ ++#define VHT_SIGA2_SVC_BITS 16 ++#define VHT_SIGA2_TAIL_BITS 6 ++ ++ ++/* dot11Counters Table - 802.11 spec., Annex D */ ++typedef struct d11cnt { ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++} d11cnt_t; ++ ++/* OUI for BRCM proprietary IE */ ++#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* The following BRCM_PROP_OUI types are currently in use (defined in ++ * relevant subsections). Each of them will be in a separate proprietary(221) IE ++ * #define SES_VNDR_IE_TYPE 1 (defined in src/ses/shared/ses.h) ++ * #define DPT_IE_TYPE 2 ++ * #define HT_CAP_IE_TYPE 51 ++ * #define HT_ADD_IE_TYPE 52 ++ * #define BRCM_EXTCH_IE_TYPE 53 ++ */ ++ ++/* Following is the generic structure for brcm_prop_ie (uses BRCM_PROP_OUI). ++ * DPT uses this format with type set to DPT_IE_TYPE ++ */ ++BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type of this IE */ ++ uint16 cap; /* DPT capabilities */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_prop_ie_s brcm_prop_ie_t; ++ ++#define BRCM_PROP_IE_LEN 6 /* len of fixed part of brcm_prop ie */ ++ ++#define DPT_IE_TYPE 2 ++#define WET_TUNNEL_IE_TYPE 3 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* BRCM OUI: Used in the proprietary(221) IE in all broadcom devices */ ++#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ ++ ++/* BRCM info element */ ++BWL_PRE_PACKED_STRUCT struct brcm_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ ++ uint8 ver; /* type/ver of this IE */ ++ uint8 assoc; /* # of assoc STAs */ ++ uint8 flags; /* misc flags */ ++ uint8 flags1; /* misc flags */ ++ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_ie brcm_ie_t; ++#define BRCM_IE_LEN 11 /* BRCM IE length */ ++#define BRCM_IE_VER 2 /* BRCM IE version */ ++#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ ++ ++/* brcm_ie flags */ ++#define BRF_LZWDS 0x4 /* lazy wds enabled */ ++#define BRF_BLOCKACK 0x8 /* BlockACK capable */ ++ ++/* brcm_ie flags1 */ ++#define BRF1_AMSDU 0x1 /* A-MSDU capable */ ++#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */ ++#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */ ++#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */ ++#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */ ++#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */ ++ ++/* Vendor IE structure */ ++BWL_PRE_PACKED_STRUCT struct vndr_ie { ++ uchar id; ++ uchar len; ++ uchar oui [3]; ++ uchar data [1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vndr_ie vndr_ie_t; ++ ++#define VNDR_IE_HDR_LEN 2 /* id + len field */ ++#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ ++#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ ++ ++/* ************* HT definitions. ************* */ ++#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ ++#define MAX_MCS_NUM (128) /* max mcs number = 128 */ ++ ++BWL_PRE_PACKED_STRUCT struct ht_cap_ie { ++ uint16 cap; ++ uint8 params; ++ uint8 supp_mcs[MCSSET_LEN]; ++ uint16 ext_htcap; ++ uint32 txbf_cap; ++ uint8 as_cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_cap_ie ht_cap_ie_t; ++ ++/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the capability IE is primarily used to convey this nodes abilities */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ ht_cap_ie_t cap_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; ++ ++#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ ++#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */ ++#define HT_CAP_IE_TYPE 51 ++ ++#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ ++#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */ ++#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ ++#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ ++#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ ++#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ ++#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ ++#define HT_CAP_GF 0x0010 /* Greenfield preamble support */ ++#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ ++#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ ++#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */ ++#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ ++#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ ++#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */ ++#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ ++ ++#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ ++#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ ++#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ ++#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ ++ ++#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ ++#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ ++#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ ++ ++#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */ ++#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */ ++/* Max AMSDU len - per spec */ ++#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA) ++ ++#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */ ++#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */ ++ ++#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ ++#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ ++#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ ++ ++/* HT/AMPDU specific define */ ++#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */ ++#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */ ++#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */ ++#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */ ++#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */ ++#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ ++ ++#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ ++#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ ++ ++#define HT_CAP_EXT_PCO 0x0001 ++#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 ++#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 ++#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 ++#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 ++#define HT_CAP_EXT_HTC 0x0400 ++#define HT_CAP_EXT_RD_RESP 0x0800 ++ ++BWL_PRE_PACKED_STRUCT struct ht_add_ie { ++ uint8 ctl_ch; /* control channel number */ ++ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ ++ uint16 opmode; /* operation mode */ ++ uint16 misc_bits; /* misc bits */ ++ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_add_ie ht_add_ie_t; ++ ++/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the additional IE is primarily used to convey the current BSS configuration */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* indicates what follows */ ++ ht_add_ie_t add_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_add_ie ht_prop_add_ie_t; ++ ++#define HT_ADD_IE_LEN 22 ++#define HT_ADD_IE_TYPE 52 ++ ++/* byte1 defn's */ ++#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ ++#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */ ++ ++/* opmode defn's */ ++#define HT_OPMODE_MASK 0x0003 /* protection mode mask */ ++#define HT_OPMODE_SHIFT 0 /* protection mode shift */ ++#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* misc_bites defn's */ ++#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ ++#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ ++#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */ ++#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ ++#define HT_PCO_ACTIVE 0x0400 /* PCO active */ ++#define HT_PCO_PHASE 0x0800 /* PCO phase */ ++#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */ ++ ++/* Tx Burst Limits */ ++#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++ ++/* Macros for opmode */ ++#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ >> HT_OPMODE_SHIFT) ++#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_MIXED) /* mixed mode present */ ++#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_HT20IN40) /* 20MHz HT present */ ++#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_OPTIONAL) /* Optional protection present */ ++#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ ++ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */ ++#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ ++ == HT_OPMODE_NONGF) /* non-GF present */ ++#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ ++ == DOT11N_TXBURST) /* Tx Burst present */ ++#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ ++ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ ++ ++BWL_PRE_PACKED_STRUCT struct obss_params { ++ uint16 passive_dwell; ++ uint16 active_dwell; ++ uint16 bss_widthscan_interval; ++ uint16 passive_total; ++ uint16 active_total; ++ uint16 chanwidth_transition_dly; ++ uint16 activity_threshold; ++} BWL_POST_PACKED_STRUCT; ++typedef struct obss_params obss_params_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { ++ uint8 id; ++ uint8 len; ++ obss_params_t obss_params; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_ie dot11_obss_ie_t; ++#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */ ++ ++/* HT control field */ ++#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */ ++#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */ ++#define HT_CTRL_LA_MAI_SHIFT 2 ++#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */ ++#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */ ++#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */ ++#define HT_CTRL_LA_MFSI_SHIFT 6 ++#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */ ++#define HT_CTRL_LA_MFB_ASELC_SH 9 ++#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */ ++#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */ ++#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */ ++#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */ ++#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */ ++#define HT_CTRL_CSI_STEER_SHIFT 22 ++#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */ ++#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */ ++#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */ ++#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */ ++#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */ ++#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */ ++#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */ ++ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* ************* VHT definitions. ************* */ ++ ++BWL_PRE_PACKED_STRUCT struct vht_cap_ie { ++ uint32 vht_cap_info; ++ /* supported MCS set - 64 bit field */ ++ uint16 rx_mcs_map; ++ uint16 rx_max_rate; ++ uint16 tx_mcs_map; ++ uint16 tx_max_rate; ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_cap_ie vht_cap_ie_t; ++/* 4B cap_info + 8B supp_mcs */ ++#define VHT_CAP_IE_LEN 12 ++/* 32bit - cap info */ ++#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 ++#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c ++#define VHT_CAP_INFO_LDPC 0x00000010 ++#define VHT_CAP_INFO_SGI_80MHZ 0x00000020 ++#define VHT_CAP_INFO_SGI_160MHZ 0x00000040 ++#define VHT_CAP_INFO_TX_STBC 0x00000080 ++#define VHT_CAP_INFO_RX_STBC 0x00000700 ++ ++#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 ++#define VHT_CAP_INFO_RX_STBC_SHIFT 8 ++#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 ++#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 ++ ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 ++#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 ++#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000 ++#define VHT_CAP_INFO_TXOPPS 0x00200000 ++#define VHT_CAP_INFO_HTCVHT 0x00400000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 ++ ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 ++ ++/* 64-bit Supp MCS. */ ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_MCS_MAP_0_7 0 ++#define VHT_CAP_MCS_MAP_0_8 1 ++#define VHT_CAP_MCS_MAP_0_9 2 ++#define VHT_CAP_MCS_MAP_NONE 3 ++ ++#define VHT_CAP_MCS_MAP_NSS_MAX 8 ++ ++/* VHT Capabilities Supported Channel Width */ ++typedef enum vht_cap_chan_width { ++ VHT_CAP_CHAN_WIDTH_20_40 = 0x00, ++ VHT_CAP_CHAN_WIDTH_80 = 0x04, ++ VHT_CAP_CHAN_WIDTH_160 = 0x08 ++} vht_cap_chan_width_t; ++ ++/* VHT Capabilities Supported max MPDU LEN */ ++typedef enum vht_cap_max_mpdu_len { ++ VHT_CAP_MPDU_MAX_4K = 0x00, ++ VHT_CAP_MPDU_MAX_8K = 0x01, ++ VHT_CAP_MPDU_MAX_11K = 0x02 ++} vht_cap_max_mpdu_len_t; ++ ++/* VHT Operation Element */ ++BWL_PRE_PACKED_STRUCT struct vht_op_ie { ++ uint8 chan_width; ++ uint8 chan1; ++ uint8 chan2; ++ uint16 supp_mcs; /* same def as above in vht cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_op_ie vht_op_ie_t; ++/* 3B VHT Op info + 2B Basic MCS */ ++#define VHT_OP_IE_LEN 5 ++ ++typedef enum vht_op_chan_width { ++ VHT_OP_CHAN_WIDTH_20_40 = 0, ++ VHT_OP_CHAN_WIDTH_80 = 1, ++ VHT_OP_CHAN_WIDTH_160 = 2, ++ VHT_OP_CHAN_WIDTH_80_80 = 3 ++} vht_op_chan_width_t; ++ ++/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */ ++#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) ++#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ ++ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) ++#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ ++ ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) ++ ++/* ************* WPA definitions. ************* */ ++#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ ++#define WPA_OUI_LEN 3 /* WPA OUI length */ ++#define WPA_OUI_TYPE 1 ++#define WPA_VERSION 1 /* WPA version */ ++#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ ++#define WPA2_OUI_LEN 3 /* WPA2 OUI length */ ++#define WPA2_VERSION 1 /* WPA2 version */ ++#define WPA2_VERSION_LEN 2 /* WAP2 version length */ ++ ++/* ************* WPS definitions. ************* */ ++#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */ ++#define WPS_OUI_LEN 3 /* WPS OUI length */ ++#define WPS_OUI_TYPE 4 ++ ++/* ************* WFA definitions. ************* */ ++#if defined(MACOSX) ++#define MAC_OUI "\x00\x17\xF2" /* MACOSX OUI */ ++#define MAC_OUI_TYPE_P2P 5 ++#endif /* MACOSX */ ++ ++#if defined(MACOSX) && !defined(WLP2P_NEW_WFA_OUI) ++#define WFA_OUI WPS_OUI /* WFA OUI */ ++#else ++#ifdef P2P_IE_OVRD ++#define WFA_OUI MAC_OUI ++#else ++#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */ ++#endif /* P2P_IE_OVRD */ ++#endif /* MACOSX && !WLP2P_NEW_WFA_OUI */ ++#define WFA_OUI_LEN 3 /* WFA OUI length */ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P ++#else ++#define WFA_OUI_TYPE_P2P 9 ++#endif ++ ++#define WFA_OUI_TYPE_TPC 8 ++ ++/* RSN authenticated key managment suite */ ++#define RSN_AKM_NONE 0 /* None (IBSS) */ ++#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ ++#define RSN_AKM_PSK 2 /* Pre-shared Key */ ++#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */ ++#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */ ++#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */ ++#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ ++#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ ++ ++/* Key related defines */ ++#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ ++#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ ++#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ ++#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ ++#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */ ++ ++#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ ++#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ ++#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ ++#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ ++#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ ++#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ ++#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ ++#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ ++#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ ++#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ ++#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ ++#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ ++#define AES_KEY_SIZE 16 /* size of AES key */ ++#define AES_MIC_SIZE 8 /* size of AES MIC */ ++#define BIP_KEY_SIZE 16 /* size of BIP key */ ++ ++/* WCN */ ++#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ ++#define WCN_TYPE 4 /* WCN type */ ++ ++ ++/* 802.11r protocol definitions */ ++ ++/* Mobility Domain IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mdid; /* Mobility Domain Id */ ++ uint8 cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_mdid_ie dot11_mdid_ie_t; ++ ++#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ ++#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ ++ ++/* Fast Bss Transition IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mic_control; /* Mic Control */ ++ uint8 mic[16]; ++ uint8 anonce[32]; ++ uint8 snonce[32]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_ie dot11_ft_ie_t; ++ ++#define TIE_TYPE_RESERVED 0 ++#define TIE_TYPE_REASSOC_DEADLINE 1 ++#define TIE_TYPE_KEY_LIEFTIME 2 ++#define TIE_TYPE_ASSOC_COMEBACK 3 ++BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { ++ uint8 id; ++ uint8 len; ++ uint8 type; /* timeout interval type */ ++ uint32 value; /* timeout interval value */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_timeout_ie dot11_timeout_ie_t; ++ ++/* GTK ie */ ++BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { ++ uint8 id; ++ uint8 len; ++ uint16 key_info; ++ uint8 key_len; ++ uint8 rsc[8]; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_gtk_ie dot11_gtk_ie_t; ++ ++#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" ++#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" ++ ++ ++/* ************* WMM Parameter definitions. ************* */ ++#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ ++#define WMM_OUI_LEN 3 /* WMM OUI length */ ++#define WMM_OUI_TYPE 2 /* WMM OUT type */ ++#define WMM_VERSION 1 ++#define WMM_VERSION_LEN 1 ++ ++/* WMM OUI subtype */ ++#define WMM_OUI_SUBTYPE_PARAMETER 1 ++#define WMM_PARAMETER_IE_LEN 24 ++ ++/* Link Identifier Element */ ++BWL_PRE_PACKED_STRUCT struct link_id_ie { ++ uint8 id; ++ uint8 len; ++ struct ether_addr bssid; ++ struct ether_addr tdls_init_mac; ++ struct ether_addr tdls_resp_mac; ++} BWL_POST_PACKED_STRUCT; ++typedef struct link_id_ie link_id_ie_t; ++#define TDLS_LINK_ID_IE_LEN 18 ++ ++/* Link Wakeup Schedule Element */ ++BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { ++ uint8 id; ++ uint8 len; ++ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */ ++ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */ ++ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */ ++ uint32 max_wake_win; /* in ms, max duration of Awake Window */ ++ uint16 idle_cnt; /* number of consecutive Awake Windows */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wakeup_sch_ie wakeup_sch_ie_t; ++#define TDLS_WAKEUP_SCH_IE_LEN 18 ++ ++/* Channel Switch Timing Element */ ++BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { ++ uint8 id; ++ uint8 len; ++ uint16 switch_time; /* in ms, time to switch channels */ ++ uint16 switch_timeout; /* in ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; ++#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 ++ ++/* PTI Control Element */ ++BWL_PRE_PACKED_STRUCT struct pti_control_ie { ++ uint8 id; ++ uint8 len; ++ uint8 tid; ++ uint16 seq_control; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pti_control_ie pti_control_ie_t; ++#define TDLS_PTI_CONTROL_IE_LEN 3 ++ ++/* PU Buffer Status Element */ ++BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { ++ uint8 id; ++ uint8 len; ++ uint8 status; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; ++#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BK 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BE 2 ++#define TDLS_PU_BUFFER_STATUS_AC_VI 4 ++#define TDLS_PU_BUFFER_STATUS_AC_VO 8 ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h b/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h +new file mode 100755 +index 0000000..3749214 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch new file mode 100644 index 00000000..c6e4015b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch @@ -0,0 +1,50 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to 802.1D ++ * ++ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_1_D_ ++#define _802_1_D_ ++ ++/* 802.1D priority defines */ ++#define PRIO_8021D_NONE 2 /* None = - */ ++#define PRIO_8021D_BK 1 /* BK - Background */ ++#define PRIO_8021D_BE 0 /* BE - Best-effort */ ++#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ ++#define PRIO_8021D_CL 4 /* CL - Controlled Load */ ++#define PRIO_8021D_VI 5 /* Vi - Video */ ++#define PRIO_8021D_VO 6 /* Vo - Voice */ ++#define PRIO_8021D_NC 7 /* NC - Network Control */ ++#define MAXPRIO 7 /* 0-7 */ ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define ALLPRIO -1 /* All prioirty */ ++ ++/* Converts prio to precedence since the numerical value of ++ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. ++ */ ++#define PRIO2PREC(prio) \ ++ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) ++ ++#endif /* _802_1_D__ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/BOM b/drivers/bcmdrivers/gmac/src/include/proto/BOM +new file mode 100755 +index 0000000..98c6e5d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch new file mode 100644 index 00000000..f644b264 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_BOM.patch @@ -0,0 +1,10 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/BOM +@@ -0,0 +1,4 @@ ++# Created by mkbom ++# $Id: BOM,v 9.0 1998-07-30 23:19:02 $ ++ ++File 1.46 vip.h +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/Makefile b/drivers/bcmdrivers/gmac/src/include/proto/Makefile +new file mode 100755 +index 0000000..533b7c4 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch new file mode 100644 index 00000000..c52212b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/Makefile +@@ -0,0 +1,9 @@ ++# ++# include/proto/Makefile ++# ++# Copyright 2006, Broadcom, Inc. ++# ++# $Id: Makefile 241182 2011-02-17 21:50:03Z $ ++# ++ ++# build etags +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h +new file mode 100755 +index 0000000..f3aede9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch new file mode 100644 index 00000000..e5acb184 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch @@ -0,0 +1,112 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Ethernettype protocol definitions ++ * ++ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $ ++ */ ++ ++/* ++ * Broadcom Ethernet protocol defines ++ */ ++ ++#ifndef _BCMETH_H_ ++#define _BCMETH_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* ETHER_TYPE_BRCM is defined in ethernet.h */ ++ ++/* ++ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field ++ * in one of two formats: (only subtypes 32768-65535 are in use now) ++ * ++ * subtypes 0-32767: ++ * 8 bit subtype (0-127) ++ * 8 bit length in bytes (0-255) ++ * ++ * subtypes 32768-65535: ++ * 16 bit big-endian subtype ++ * 16 bit big-endian length in bytes (0-65535) ++ * ++ * length is the number of additional bytes beyond the 4 or 6 byte header ++ * ++ * Reserved values: ++ * 0 reserved ++ * 5-15 reserved for iLine protocol assignments ++ * 17-126 reserved, assignable ++ * 127 reserved ++ * 32768 reserved ++ * 32769-65534 reserved, assignable ++ * 65535 reserved ++ */ ++ ++/* ++ * While adding the subtypes and their specific processing code make sure ++ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition ++ */ ++ ++#define BCMILCP_SUBTYPE_RATE 1 ++#define BCMILCP_SUBTYPE_LINK 2 ++#define BCMILCP_SUBTYPE_CSA 3 ++#define BCMILCP_SUBTYPE_LARQ 4 ++#define BCMILCP_SUBTYPE_VENDOR 5 ++#define BCMILCP_SUBTYPE_FLH 17 ++ ++#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 ++#define BCMILCP_SUBTYPE_CERT 32770 ++#define BCMILCP_SUBTYPE_SES 32771 ++ ++ ++#define BCMILCP_BCM_SUBTYPE_RESERVED 0 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define BCMILCP_BCM_SUBTYPE_SES 2 ++/* ++ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded ++ * within BCMILCP_BCM_SUBTYPE_EVENT type messages ++ */ ++/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ ++#define BCMILCP_BCM_SUBTYPE_DPT 4 ++ ++#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 ++#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 ++ ++/* These fields are stored in network order */ ++typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr ++{ ++ uint16 subtype; /* Vendor specific..32769 */ ++ uint16 length; ++ uint8 version; /* Version is 0 */ ++ uint8 oui[3]; /* Broadcom OUI */ ++ /* user specific Data */ ++ uint16 usr_subtype; ++} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMETH_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h +new file mode 100755 +index 0000000..57776ae diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch new file mode 100644 index 00000000..74d02b31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch @@ -0,0 +1,319 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h +@@ -0,0 +1,313 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Event protocol definitions ++ * ++ * Dependencies: proto/bcmeth.h ++ * ++ * $Id: bcmevent.h 315348 2012-02-16 07:32:51Z $ ++ * ++ */ ++ ++/* ++ * Broadcom Ethernet Events protocol defines ++ * ++ */ ++ ++#ifndef _BCMEVENT_H_ ++#define _BCMEVENT_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */ ++#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ ++ ++/* flags */ ++#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ ++#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ ++#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ ++#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */ ++#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */ ++ ++/* these fields are stored in network order */ ++ ++/* version 1 */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t; ++ ++/* the current version */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++ uint8 ifidx; /* destination OS i/f index */ ++ uint8 bsscfgidx; /* source bsscfg index */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_t; ++ ++/* used by driver msgs */ ++typedef BWL_PRE_PACKED_STRUCT struct bcm_event { ++ struct ether_header eth; ++ bcmeth_hdr_t bcm_hdr; ++ wl_event_msg_t event; ++ /* data portion follows */ ++} BWL_POST_PACKED_STRUCT bcm_event_t; ++ ++#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) ++ ++/* Event messages */ ++#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ ++#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ ++#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ ++#define WLC_E_AUTH 3 /* 802.11 AUTH request */ ++#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ ++#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ ++#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ ++#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ ++#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ ++#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ ++#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ ++#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ ++#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ ++#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ ++#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ ++#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ ++#define WLC_E_LINK 16 /* generic link indication */ ++#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ ++#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ ++#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ ++#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ ++#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ ++#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ ++#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ ++#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ ++#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ ++#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ ++#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ ++#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ ++#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ ++#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ ++#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */ ++#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ ++#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ ++#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ ++#define WLC_E_RESET_COMPLETE 35 ++#define WLC_E_JOIN_START 36 ++#define WLC_E_ROAM_START 37 ++#define WLC_E_ASSOC_START 38 ++#define WLC_E_IBSS_ASSOC 39 ++#define WLC_E_RADIO 40 ++#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */ ++#define WLC_E_PROBREQ_MSG 44 /* probe request received */ ++#define WLC_E_SCAN_CONFIRM_IND 45 ++#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */ ++#define WLC_E_COUNTRY_CODE_CHANGED 47 ++#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */ ++#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */ ++#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */ ++#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */ ++#define WLC_E_TRACE 52 ++#define WLC_E_IF 54 /* I/F change (for dongle host notification) */ ++#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */ ++#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */ ++#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */ ++#define WLC_E_EXTLOG_MSG 58 ++#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */ ++#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ ++#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ ++#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ ++#define WLC_E_CHANNEL_ADOPTED 63 ++#define WLC_E_AP_STARTED 64 /* AP started */ ++#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ ++#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ ++#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */ ++#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */ ++#define WLC_E_ESCAN_RESULT 69 /* escan result event */ ++#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */ ++#define WLC_E_PROBRESP_MSG 71 /* probe response received */ ++#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */ ++#define WLC_E_DCS_REQUEST 73 ++ ++#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ ++ ++#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH ++ * wl_event_rx_frame_data_t header ++ */ ++#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */ ++#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */ ++#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */ ++#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */ ++#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */ ++#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */ ++#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */ ++#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */ ++#define WLC_E_GTK_PLUMBED 84 ++#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */ ++#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */ ++#define WLC_E_ASSOC_REQ_IE 87 ++#define WLC_E_ASSOC_RESP_IE 88 ++ ++#define WLC_E_LAST 89 /* highest val + 1 for range checking */ ++ ++/* Table of event name strings for UIs and debugging dumps */ ++typedef struct { ++ uint event; ++ const char *name; ++} bcmevent_name_t; ++ ++extern const bcmevent_name_t bcmevent_names[]; ++extern const int bcmevent_names_size; ++ ++/* Event status codes */ ++#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ ++#define WLC_E_STATUS_FAIL 1 /* operation failed */ ++#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ ++#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ ++#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ ++#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ ++#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ ++#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ ++#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ ++#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ ++#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ ++#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ ++#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ ++#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ ++#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */ ++#define WLC_E_STATUS_ERROR 16 /* request failed due to error */ ++ ++/* roam reason codes */ ++#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ ++#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ ++#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ ++#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ ++#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ ++#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */ ++#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */ ++ ++/* Roam codes used primarily by CCX */ ++#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ ++#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ ++#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ ++#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ ++ ++#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition request by AP */ ++ ++/* prune reason codes */ ++#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */ ++#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ ++#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ ++#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ ++#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ ++#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ ++#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ ++#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ ++#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ ++#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ ++#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ ++#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ ++#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ ++#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ ++#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ ++ ++/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ ++#define WLC_E_SUP_OTHER 0 /* Other reason */ ++#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */ ++#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */ ++#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */ ++#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */ ++#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */ ++#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */ ++#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */ ++#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */ ++#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */ ++#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */ ++#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */ ++#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */ ++#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */ ++#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */ ++#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */ ++ ++/* Event data for events that include frames received over the air */ ++/* WLC_E_PROBRESP_MSG ++ * WLC_E_P2P_PROBREQ_MSG ++ * WLC_E_ACTION_FRAME_RX ++ */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { ++ uint16 version; ++ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ ++ int32 rssi; ++ uint32 mactime; ++ uint32 rate; ++} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; ++ ++#define BCM_RX_FRAME_DATA_VERSION 1 ++ ++/* WLC_E_IF event data */ ++typedef struct wl_event_data_if { ++ uint8 ifidx; /* RTE virtual device index (for dongle) */ ++ uint8 opcode; /* see I/F opcode */ ++ uint8 reserved; ++ uint8 bssidx; /* bsscfg index */ ++ uint8 role; /* see I/F role */ ++} wl_event_data_if_t; ++ ++/* opcode in WLC_E_IF event */ ++#define WLC_E_IF_ADD 1 /* bsscfg add */ ++#define WLC_E_IF_DEL 2 /* bsscfg delete */ ++#define WLC_E_IF_CHANGE 3 /* bsscfg role change */ ++ ++/* I/F role code in WLC_E_IF event */ ++#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ ++#define WLC_E_IF_ROLE_AP 1 /* Access Point */ ++#define WLC_E_IF_ROLE_WDS 2 /* WDS link */ ++#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ ++#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ ++ ++/* Reason codes for LINK */ ++#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */ ++#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */ ++#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ ++#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ ++ ++/* reason codes for WLC_E_OVERLAY_REQ event */ ++#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */ ++#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMEVENT_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h +new file mode 100755 +index 0000000..4f01aee diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch new file mode 100644 index 00000000..91960fdb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch @@ -0,0 +1,211 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h +@@ -0,0 +1,205 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental constants relating to IP Protocol ++ * ++ * $Id: bcmip.h 324300 2012-03-28 20:29:37Z $ ++ */ ++ ++#ifndef _bcmip_h_ ++#define _bcmip_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* IPV4 and IPV6 common */ ++#define IP_VER_OFFSET 0x0 /* offset to version field */ ++#define IP_VER_MASK 0xf0 /* version mask */ ++#define IP_VER_SHIFT 4 /* version shift */ ++#define IP_VER_4 4 /* version number for IPV4 */ ++#define IP_VER_6 6 /* version number for IPV6 */ ++ ++#define IP_VER(ip_body) \ ++ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) ++ ++#define IP_PROT_ICMP 0x1 /* ICMP protocol */ ++#define IP_PROT_IGMP 0x2 /* IGMP protocol */ ++#define IP_PROT_TCP 0x6 /* TCP protocol */ ++#define IP_PROT_UDP 0x11 /* UDP protocol type */ ++#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */ ++ ++/* IPV4 field offsets */ ++#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ ++#define IPV4_TOS_OFFSET 1 /* type of service offset */ ++#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ ++#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ ++#define IPV4_PROT_OFFSET 9 /* protocol type offset */ ++#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ ++#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ ++#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ ++#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ ++#define IPV4_MIN_HEADER_LEN 20 /* Minimum size for an IP header (no options) */ ++ ++/* IPV4 field decodes */ ++#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ ++#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ ++ ++#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ ++#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) ++ ++#define IPV4_ADDR_LEN 4 /* IPV4 address length */ ++ ++#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ ++ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) ++ ++#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ ++ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) ++ ++#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ ++#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ ++ ++#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) ++ ++#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ ++#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ ++ ++#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ ++#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ ++#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ ++ ++#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) ++ ++#define IPV4_FRAG_RESV 0x8000 /* Reserved */ ++#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ ++#define IPV4_FRAG_MORE 0x2000 /* More fragments */ ++#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ ++ ++#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ ++ ++/* IPV4 packet formats */ ++BWL_PRE_PACKED_STRUCT struct ipv4_addr { ++ uint8 addr[IPV4_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv4_hdr { ++ uint8 version_ihl; /* Version and Internet Header Length */ ++ uint8 tos; /* Type Of Service */ ++ uint16 tot_len; /* Number of bytes in packet (max 65535) */ ++ uint16 id; ++ uint16 frag; /* 3 flag bits and fragment offset */ ++ uint8 ttl; /* Time To Live */ ++ uint8 prot; /* Protocol */ ++ uint16 hdr_chksum; /* IP header checksum */ ++ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ ++ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* IPV6 field offsets */ ++#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ ++#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ ++#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ ++#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ ++#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ ++ ++/* IPV6 field decodes */ ++#define IPV6_TRAFFIC_CLASS(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ ++ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) ++ ++#define IPV6_FLOW_LABEL(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ ++ (((uint8 *)(ipv6_body))[2] << 8) | \ ++ (((uint8 *)(ipv6_body))[3])) ++ ++#define IPV6_PAYLOAD_LEN(ipv6_body) \ ++ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ ++ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) ++ ++#define IPV6_NEXT_HDR(ipv6_body) \ ++ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) ++ ++#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) ++ ++#define IPV6_ADDR_LEN 16 /* IPV6 address length */ ++ ++/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ ++#define IP_TOS46(ip_body) \ ++ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ ++ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) ++ ++/* IPV6 extension headers (options) */ ++#define IPV6_EXTHDR_HOP 0 ++#define IPV6_EXTHDR_ROUTING 43 ++#define IPV6_EXTHDR_FRAGMENT 44 ++#define IPV6_EXTHDR_AUTH 51 ++#define IPV6_EXTHDR_NONE 59 ++#define IPV6_EXTHDR_DEST 60 ++ ++#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \ ++ ((prot) == IPV6_EXTHDR_ROUTING) || \ ++ ((prot) == IPV6_EXTHDR_FRAGMENT) || \ ++ ((prot) == IPV6_EXTHDR_AUTH) || \ ++ ((prot) == IPV6_EXTHDR_NONE) || \ ++ ((prot) == IPV6_EXTHDR_DEST)) ++ ++#define IPV6_MIN_HLEN 40 ++ ++#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3) ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr { ++ uint8 nexthdr; ++ uint8 hdrlen; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag { ++ uint8 nexthdr; ++ uint8 rsvd; ++ uint16 frag_off; ++ uint32 ident; ++} BWL_POST_PACKED_STRUCT; ++ ++static INLINE int32 ++ipv6_exthdr_len(uint8 *h, uint8 *proto) ++{ ++ uint16 len = 0, hlen; ++ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h; ++ ++ while (IPV6_EXTHDR(eh->nexthdr)) { ++ if (eh->nexthdr == IPV6_EXTHDR_NONE) ++ return -1; ++ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT) ++ hlen = 8; ++ else if (eh->nexthdr == IPV6_EXTHDR_AUTH) ++ hlen = (eh->hdrlen + 2) << 2; ++ else ++ hlen = IPV6_EXTHDR_LEN(eh); ++ ++ len += hlen; ++ eh = (struct ipv6_exthdr *)(h + len); ++ } ++ ++ *proto = eh->nexthdr; ++ return len; ++} ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bcmip_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h +new file mode 100755 +index 0000000..c72eb31 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch new file mode 100644 index 00000000..a75d41a8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch @@ -0,0 +1,107 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental constants relating to Neighbor Discovery Protocol ++ * ++ * $Id: bcmipv6.h 305568 2011-12-29 20:21:17Z $ ++ */ ++ ++#ifndef _bcmipv6_h_ ++#define _bcmipv6_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define ICMPV6_HEADER_TYPE 0x3A ++#define ICMPV6_PKT_TYPE_NS 135 ++#define ICMPV6_PKT_TYPE_NA 136 ++ ++#define ICMPV6_ND_OPT_TYPE_TARGET_MAC 2 ++#define ICMPV6_ND_OPT_TYPE_SRC_MAC 1 ++ ++#define IPV6_VERSION 6 ++#define IPV6_HOP_LIMIT 255 ++ ++#define IPV6_ADDR_NULL(a) ((a[0] | a[1] | a[2] | a[3] | a[4] | \ ++ a[5] | a[6] | a[7] | a[8] | a[9] | \ ++ a[10] | a[11] | a[12] | a[13] | \ ++ a[14] | a[15]) == 0) ++ ++/* IPV6 address */ ++BWL_PRE_PACKED_STRUCT struct ipv6_addr { ++ uint8 addr[16]; ++} BWL_POST_PACKED_STRUCT; ++ ++#ifndef IL_BIGENDIAN ++ ++/* ICMPV6 Header */ ++BWL_PRE_PACKED_STRUCT struct icmp6_hdr { ++ uint8 icmp6_type; ++ uint8 icmp6_code; ++ uint16 icmp6_cksum; ++ BWL_PRE_PACKED_STRUCT union { ++ uint32 reserved; ++ BWL_PRE_PACKED_STRUCT struct nd_advt { ++ uint32 reserved1:5, ++ override:1, ++ solicited:1, ++ router:1, ++ reserved2:24; ++ } BWL_POST_PACKED_STRUCT nd_advt; ++ } BWL_POST_PACKED_STRUCT opt; ++} BWL_POST_PACKED_STRUCT; ++ ++/* Ipv6 Header Format */ ++BWL_PRE_PACKED_STRUCT struct ipv6_hdr { ++ uint8 priority:4, ++ version:4; ++ uint8 flow_lbl[3]; ++ uint16 payload_len; ++ uint8 nexthdr; ++ uint8 hop_limit; ++ struct ipv6_addr saddr; ++ struct ipv6_addr daddr; ++} BWL_POST_PACKED_STRUCT; ++ ++/* Neighbor Advertisement/Solicitation Packet Structure */ ++BWL_PRE_PACKED_STRUCT struct nd_msg { ++ struct icmp6_hdr icmph; ++ struct ipv6_addr target; ++} BWL_POST_PACKED_STRUCT; ++ ++ ++/* Neighibor Solicitation/Advertisement Optional Structure */ ++BWL_PRE_PACKED_STRUCT struct nd_msg_opt { ++ uint8 type; ++ uint8 len; ++ uint8 mac_addr[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++#endif /* IL_BIGENDIAN */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* !defined(_bcmipv6_h_) */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h b/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h +new file mode 100755 +index 0000000..85d664c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch new file mode 100644 index 00000000..baa492ab --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch @@ -0,0 +1,208 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h +@@ -0,0 +1,202 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. ++ * ++ * $Id: ethernet.h 316696 2012-02-23 03:29:35Z $ ++ */ ++ ++#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ ++#define _NET_ETHERNET_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include "typedefs.h" ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* ++ * The number of bytes in an ethernet (MAC) address. ++ */ ++#define ETHER_ADDR_LEN 6 ++ ++/* ++ * The number of bytes in the type field. ++ */ ++#define ETHER_TYPE_LEN 2 ++ ++/* ++ * The number of bytes in the trailing CRC field. ++ */ ++#define ETHER_CRC_LEN 4 ++ ++/* ++ * The length of the combined header. ++ */ ++#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) ++ ++/* ++ * The minimum packet length. ++ */ ++#define ETHER_MIN_LEN 64 ++ ++/* ++ * The minimum packet user data length. ++ */ ++#define ETHER_MIN_DATA 46 ++ ++/* ++ * The maximum packet length. ++ */ ++#define ETHER_MAX_LEN 1518 ++ ++/* ++ * The maximum packet user data length. ++ */ ++#define ETHER_MAX_DATA 1500 ++ ++/* ether types */ ++#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ ++#define ETHER_TYPE_IP 0x0800 /* IP */ ++#define ETHER_TYPE_ARP 0x0806 /* ARP */ ++#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ ++#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ ++#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ ++#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ ++#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ ++#define ETHER_TYPE_WAI 0x88b4 /* WAI */ ++#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ ++ ++#define ETHER_TYPE_PPP_SES 0x8864 /* PPPoE Session */ ++ ++/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ ++#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ ++ ++/* ether header */ ++#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ ++#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ ++#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ ++ ++/* ++ * A macro to validate a length with ++ */ ++#define ETHER_IS_VALID_LEN(foo) \ ++ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) ++ ++#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ ++ ((uint8 *)ea)[0] = 0x01; \ ++ ((uint8 *)ea)[1] = 0x00; \ ++ ((uint8 *)ea)[2] = 0x5e; \ ++ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ ++ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ ++ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ ++} ++ ++#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ ++/* ++ * Structure of a 10Mb/s Ethernet header. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 ether_type; ++} BWL_POST_PACKED_STRUCT; ++ ++/* ++ * Structure of a 48-bit Ethernet address. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_addr { ++ uint8 octet[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ ++ ++/* ++ * Takes a pointer, set, test, clear, toggle locally admininistered ++ * address bit in the 48-bit Ethernet address. ++ */ ++#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) ++#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) ++#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) ++#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) ++ ++/* Takes a pointer, marks unicast address bit in the MAC address */ ++#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) ++ ++/* ++ * Takes a pointer, returns true if a 48-bit multicast address ++ * (including broadcast, since it is all ones) ++ */ ++#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) ++ ++/* Copy an ethernet address in reverse order */ ++#define ether_rcopy(s, d) \ ++do { \ ++ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \ ++ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \ ++ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \ ++} while (0) ++ ++/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ ++#define eacmp(a, b) ((((uint16 *)(a))[0] ^ ((uint16 *)(b))[0]) | \ ++ (((uint16 *)(a))[1] ^ ((uint16 *)(b))[1]) | \ ++ (((uint16 *)(a))[2] ^ ((uint16 *)(b))[2])) ++ ++#define ether_cmp(a, b) eacmp(a, b) ++ ++/* copy an ethernet address - assumes the pointers can be referenced as shorts */ ++#define eacopy(s, d) \ ++do { \ ++ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \ ++ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \ ++ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \ ++} while (0) ++ ++#define ether_copy(s, d) eacopy(s, d) ++ ++ ++static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; ++static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; ++ ++#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \ ++ ((const uint8 *)(ea))[1] & \ ++ ((const uint8 *)(ea))[2] & \ ++ ((const uint8 *)(ea))[3] & \ ++ ((const uint8 *)(ea))[4] & \ ++ ((const uint8 *)(ea))[5]) == 0xff) ++#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \ ++ ((const uint8 *)(ea))[1] | \ ++ ((const uint8 *)(ea))[2] | \ ++ ((const uint8 *)(ea))[3] | \ ++ ((const uint8 *)(ea))[4] | \ ++ ((const uint8 *)(ea))[5]) == 0) ++ ++#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \ ++ ((const uint16 *)(da))[1] | \ ++ ((const uint16 *)(da))[2]) == 0) ++ ++ ++#define ETHER_MOVE_HDR(d, s) \ ++do { \ ++ struct ether_header t; \ ++ t = *(struct ether_header *)(s); \ ++ *(struct ether_header *)(d) = t; \ ++} while (0) ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _NET_ETHERNET_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/vlan.h b/drivers/bcmdrivers/gmac/src/include/proto/vlan.h +new file mode 100755 +index 0000000..5393070 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch new file mode 100644 index 00000000..31e5a251 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch @@ -0,0 +1,73 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/vlan.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * 802.1Q VLAN protocol definitions ++ * ++ * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _vlan_h_ ++#define _vlan_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#ifndef VLAN_VID_MASK ++#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ ++#endif ++#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ ++#define VLAN_PRI_SHIFT 13 /* user priority */ ++ ++#define VLAN_PRI_MASK 7 /* 3 bits of priority */ ++ ++#define VLAN_TCI_OFFSET 14 /* offset of tag ctrl info field */ ++ ++#define VLAN_TAG_LEN 4 ++#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ ++ ++#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ ++ ++struct ethervlan_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 vlan_type; /* 0x8100 */ ++ uint16 vlan_tag; /* priority, cfi and vid */ ++ uint16 ether_type; ++}; ++ ++#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#define ETHERVLAN_MOVE_HDR(d, s) \ ++do { \ ++ struct ethervlan_header t; \ ++ t = *(struct ethervlan_header *)(s); \ ++ *(struct ethervlan_header *)(d) = t; \ ++} while (0) ++ ++#endif /* _vlan_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/wpa.h b/drivers/bcmdrivers/gmac/src/include/proto/wpa.h +new file mode 100755 +index 0000000..98b09a2 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch new file mode 100644 index 00000000..c979b7b4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch @@ -0,0 +1,175 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/wpa.h +@@ -0,0 +1,169 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to WPA ++ * ++ * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ ++ */ ++ ++#ifndef _proto_wpa_h_ ++#define _proto_wpa_h_ ++ ++#include ++#include ++ ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* Reason Codes */ ++ ++/* 13 through 23 taken from IEEE Std 802.11i-2004 */ ++#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ ++#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ ++#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ ++#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ ++#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from ++ * (re-)assoc. request/probe response ++ */ ++#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ ++#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ ++#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ ++#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ ++#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ ++#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ ++ ++#define WPA2_PMKID_LEN 16 ++ ++/* WPA IE fixed portion */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ uint8 oui[3]; /* IE OUI */ ++ uint8 oui_type; /* OUI type */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; ++#define WPA_IE_OUITYPE_LEN 4 ++#define WPA_IE_FIXED_LEN 8 ++#define WPA_IE_TAG_FIXED_LEN 6 ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; ++#define WPA_RSN_IE_FIXED_LEN 4 ++#define WPA_RSN_IE_TAG_FIXED_LEN 2 ++typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; ++ ++/* WPA suite/multicast suite */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 oui[3]; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; ++#define WPA_SUITE_LEN 4 ++ ++/* WPA unicast suite list/key management suite list */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_suite_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; ++#define WPA_IE_SUITE_COUNT_LEN 2 ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_pmkid_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; ++ ++/* WPA cipher suites */ ++#define WPA_CIPHER_NONE 0 /* None */ ++#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ ++#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ ++#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ ++#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ ++#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ ++#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */ ++#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */ ++ ++ ++#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ ++ (cipher) == WPA_CIPHER_WEP_40 || \ ++ (cipher) == WPA_CIPHER_WEP_104 || \ ++ (cipher) == WPA_CIPHER_TKIP || \ ++ (cipher) == WPA_CIPHER_AES_OCB || \ ++ (cipher) == WPA_CIPHER_AES_CCM || \ ++ (cipher) == WPA_CIPHER_TPK) ++ ++ ++/* WPA TKIP countermeasures parameters */ ++#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ ++#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ ++ ++/* RSN IE defines */ ++#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ ++ ++/* RSN Capabilities defined in 802.11i */ ++#define RSN_CAP_PREAUTH 0x0001 ++#define RSN_CAP_NOPAIRWISE 0x0002 ++#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C ++#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 ++#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 ++#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 ++#define RSN_CAP_1_REPLAY_CNTR 0 ++#define RSN_CAP_2_REPLAY_CNTRS 1 ++#define RSN_CAP_4_REPLAY_CNTRS 2 ++#define RSN_CAP_16_REPLAY_CNTRS 3 ++#ifdef MFP ++#define RSN_CAP_MFPR 0x0040 ++#define RSN_CAP_MFPC 0x0080 ++#endif ++ ++/* WPA capabilities defined in 802.11i */ ++#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS ++#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS ++#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT ++#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK ++ ++/* WPA capabilities defined in 802.11zD9.0 */ ++#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */ ++ ++/* WPA Specific defines */ ++#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ ++#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */ ++ ++#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH ++ ++#define WPA2_PMKID_COUNT_LEN 2 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _proto_wpa_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbchipc.h b/drivers/bcmdrivers/gmac/src/include/sbchipc.h +new file mode 100755 +index 0000000..a03df39 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch new file mode 100644 index 00000000..2d57bad9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch @@ -0,0 +1,2523 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbchipc.h +@@ -0,0 +1,2517 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SiliconBackplane Chipcommon core hardware definitions. ++ * ++ * The chipcommon core provides chip identification, SB control, ++ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, ++ * GPIO interface, extbus, and support for serial and parallel flashes. ++ * ++ * $Id: sbchipc.h 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++typedef struct eci_prerev35 { ++ uint32 eci_output; ++ uint32 eci_control; ++ uint32 eci_inputlo; ++ uint32 eci_inputmi; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolaritymi; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskmi; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventmi; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskmi; ++ uint32 eci_eventmaskhi; ++ uint32 PAD[3]; ++} eci_prerev35_t; ++ ++typedef struct eci_rev35 { ++ uint32 eci_outputlo; ++ uint32 eci_outputhi; ++ uint32 eci_controllo; ++ uint32 eci_controlhi; ++ uint32 eci_inputlo; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskhi; ++ uint32 eci_auxtx; ++ uint32 eci_auxrx; ++ uint32 eci_datatag; ++ uint32 eci_uartescvalue; ++ uint32 eci_autobaudctr; ++ uint32 eci_uartfifolevel; ++} eci_rev35_t; ++ ++typedef struct flash_config { ++ uint32 PAD[19]; ++ /* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */ ++ uint32 flashstrconfig; ++} flash_config_t; ++ ++typedef volatile struct { ++ uint32 chipid; /* 0x0 */ ++ uint32 capabilities; ++ uint32 corecontrol; /* corerev >= 1 */ ++ uint32 bist; ++ ++ /* OTP */ ++ uint32 otpstatus; /* 0x10, corerev >= 10 */ ++ uint32 otpcontrol; ++ uint32 otpprog; ++ uint32 otplayout; /* corerev >= 23 */ ++ ++ /* Interrupt control */ ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; ++ ++ /* Chip specific regs */ ++ uint32 chipcontrol; /* 0x28, rev >= 11 */ ++ uint32 chipstatus; /* 0x2c, rev >= 11 */ ++ ++ /* Jtag Master */ ++ uint32 jtagcmd; /* 0x30, rev >= 10 */ ++ uint32 jtagir; ++ uint32 jtagdr; ++ uint32 jtagctrl; ++ ++ /* serial flash interface registers */ ++ uint32 flashcontrol; /* 0x40 */ ++ uint32 flashaddress; ++ uint32 flashdata; ++ uint32 otplayoutextension; /* rev >= 35 */ ++ ++ /* Silicon backplane configuration broadcast control */ ++ uint32 broadcastaddress; /* 0x50 */ ++ uint32 broadcastdata; ++ ++ /* gpio - cleared only by power-on-reset */ ++ uint32 gpiopullup; /* 0x58, corerev >= 20 */ ++ uint32 gpiopulldown; /* 0x5c, corerev >= 20 */ ++ uint32 gpioin; /* 0x60 */ ++ uint32 gpioout; /* 0x64 */ ++ uint32 gpioouten; /* 0x68 */ ++ uint32 gpiocontrol; /* 0x6C */ ++ uint32 gpiointpolarity; /* 0x70 */ ++ uint32 gpiointmask; /* 0x74 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioevent; ++ uint32 gpioeventintmask; ++ ++ /* Watchdog timer */ ++ uint32 watchdog; /* 0x80 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioeventintpolarity; ++ ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ uint32 gpiotimerval; /* 0x88 */ ++ uint32 gpiotimeroutmask; ++ ++ /* clock control */ ++ uint32 clockcontrol_n; /* 0x90 */ ++ uint32 clockcontrol_sb; /* aka m0 */ ++ uint32 clockcontrol_pci; /* aka m1 */ ++ uint32 clockcontrol_m2; /* mii/uart/mipsref */ ++ uint32 clockcontrol_m3; /* cpu */ ++ uint32 clkdiv; /* corerev >= 3 */ ++ uint32 gpiodebugsel; /* corerev >= 28 */ ++ uint32 capabilities_ext; /* 0xac */ ++ ++ /* pll delay registers (corerev >= 4) */ ++ uint32 pll_on_delay; /* 0xb0 */ ++ uint32 fref_sel_delay; ++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ uint32 PAD; ++ ++ /* Instaclock registers (corerev >= 10) */ ++ uint32 system_clk_ctl; /* 0xc0 */ ++ uint32 clkstatestretch; ++ uint32 PAD[2]; ++ ++ /* Indirect backplane access (corerev >= 22) */ ++ uint32 bp_addrlow; /* 0xd0 */ ++ uint32 bp_addrhigh; ++ uint32 bp_data; ++ uint32 PAD; ++ uint32 bp_indaccess; ++ /* SPI registers, corerev >= 37 */ ++ uint32 gsioctrl; ++ uint32 gsioaddress; ++ uint32 gsiodata; ++ ++ /* More clock dividers (corerev >= 32) */ ++ uint32 clkdiv2; ++ /* FAB ID (corerev >= 40) */ ++ uint32 otpcontrol1; ++ uint32 fabid; /* 0xf8 */ ++ ++ /* In AI chips, pointer to erom */ ++ uint32 eromptr; /* 0xfc */ ++ ++ /* ExtBus control registers (corerev >= 3) */ ++ uint32 pcmcia_config; /* 0x100 */ ++ uint32 pcmcia_memwait; ++ uint32 pcmcia_attrwait; ++ uint32 pcmcia_iowait; ++ uint32 ide_config; ++ uint32 ide_memwait; ++ uint32 ide_attrwait; ++ uint32 ide_iowait; ++ uint32 prog_config; ++ uint32 prog_waitcount; ++ uint32 flash_config; ++ uint32 flash_waitcount; ++ uint32 SECI_config; /* 0x130 SECI configuration */ ++ uint32 SECI_status; ++ uint32 SECI_statusmask; ++ uint32 SECI_rxnibchanged; ++ ++ union { /* 0x140 */ ++ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ ++ struct eci_prerev35 lt35; ++ struct eci_rev35 ge35; ++ /* Other interfaces */ ++ struct flash_config flashconf; ++ uint32 PAD[20]; ++ } eci; ++ ++ /* SROM interface (corerev >= 32) */ ++ uint32 sromcontrol; /* 0x190 */ ++ uint32 sromaddress; ++ uint32 sromdata; ++ uint32 PAD[1]; /* 0x19C */ ++ /* NAND flash registers for BCM4706 (corerev = 31) */ ++ uint32 nflashctrl; /* 0x1a0 */ ++ uint32 nflashconf; ++ uint32 nflashcoladdr; ++ uint32 nflashrowaddr; ++ uint32 nflashdata; ++ uint32 nflashwaitcnt0; /* 0x1b4 */ ++ uint32 PAD[2]; ++ ++ uint32 seci_uart_data; /* 0x1C0 */ ++ uint32 seci_uart_bauddiv; ++ uint32 seci_uart_fcr; ++ uint32 seci_uart_lcr; ++ uint32 seci_uart_mcr; ++ uint32 seci_uart_lsr; ++ uint32 seci_uart_msr; ++ uint32 seci_uart_baudadj; ++ /* Clock control and hardware workarounds (corerev >= 20) */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; ++ uint32 PAD[70]; ++ ++ /* UARTs */ ++ uint8 uart0data; /* 0x300 */ ++ uint8 uart0imr; ++ uint8 uart0fcr; ++ uint8 uart0lcr; ++ uint8 uart0mcr; ++ uint8 uart0lsr; ++ uint8 uart0msr; ++ uint8 uart0scratch; ++ uint8 PAD[248]; /* corerev >= 1 */ ++ ++ uint8 uart1data; /* 0x400 */ ++ uint8 uart1imr; ++ uint8 uart1fcr; ++ uint8 uart1lcr; ++ uint8 uart1mcr; ++ uint8 uart1lsr; ++ uint8 uart1msr; ++ uint8 uart1scratch; ++ uint32 PAD[126]; ++ ++ /* PMU registers (corerev >= 20) */ ++ /* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP. ++ * The CPU must read them twice, compare, and retry if different. ++ */ ++ uint32 pmucontrol; /* 0x600 */ ++ uint32 pmucapabilities; ++ uint32 pmustatus; ++ uint32 res_state; ++ uint32 res_pending; ++ uint32 pmutimer; ++ uint32 min_res_mask; ++ uint32 max_res_mask; ++ uint32 res_table_sel; ++ uint32 res_dep_mask; ++ uint32 res_updn_timer; ++ uint32 res_timer; ++ uint32 clkstretch; ++ uint32 pmuwatchdog; ++ uint32 gpiosel; /* 0x638, rev >= 1 */ ++ uint32 gpioenable; /* 0x63c, rev >= 1 */ ++ uint32 res_req_timer_sel; ++ uint32 res_req_timer; ++ uint32 res_req_mask; ++ uint32 PAD; ++ uint32 chipcontrol_addr; /* 0x650 */ ++ uint32 chipcontrol_data; /* 0x654 */ ++ uint32 regcontrol_addr; ++ uint32 regcontrol_data; ++ uint32 pllcontrol_addr; ++ uint32 pllcontrol_data; ++ uint32 pmustrapopt; /* 0x668, corerev >= 28 */ ++ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ ++ uint32 PAD[100]; ++ uint16 sromotp[512]; /* 0x800 */ ++#ifdef NFLASH_SUPPORT ++ /* Nand flash MLC controller registers (corerev >= 38) */ ++ uint32 nand_revision; /* 0xC00 */ ++ uint32 nand_cmd_start; ++ uint32 nand_cmd_addr_x; ++ uint32 nand_cmd_addr; ++ uint32 nand_cmd_end_addr; ++ uint32 nand_cs_nand_select; ++ uint32 nand_cs_nand_xor; ++ uint32 PAD; ++ uint32 nand_spare_rd0; ++ uint32 nand_spare_rd4; ++ uint32 nand_spare_rd8; ++ uint32 nand_spare_rd12; ++ uint32 nand_spare_wr0; ++ uint32 nand_spare_wr4; ++ uint32 nand_spare_wr8; ++ uint32 nand_spare_wr12; ++ uint32 nand_acc_control; ++ uint32 PAD; ++ uint32 nand_config; ++ uint32 PAD; ++ uint32 nand_timing_1; ++ uint32 nand_timing_2; ++ uint32 nand_semaphore; ++ uint32 PAD; ++ uint32 nand_devid; ++ uint32 nand_devid_x; ++ uint32 nand_block_lock_status; ++ uint32 nand_intfc_status; ++ uint32 nand_ecc_corr_addr_x; ++ uint32 nand_ecc_corr_addr; ++ uint32 nand_ecc_unc_addr_x; ++ uint32 nand_ecc_unc_addr; ++ uint32 nand_read_error_count; ++ uint32 nand_corr_stat_threshold; ++ uint32 PAD[2]; ++ uint32 nand_read_addr_x; ++ uint32 nand_read_addr; ++ uint32 nand_page_program_addr_x; ++ uint32 nand_page_program_addr; ++ uint32 nand_copy_back_addr_x; ++ uint32 nand_copy_back_addr; ++ uint32 nand_block_erase_addr_x; ++ uint32 nand_block_erase_addr; ++ uint32 nand_inv_read_addr_x; ++ uint32 nand_inv_read_addr; ++ uint32 PAD[2]; ++ uint32 nand_blk_wr_protect; ++ uint32 PAD[3]; ++ uint32 nand_acc_control_cs1; ++ uint32 nand_config_cs1; ++ uint32 nand_timing_1_cs1; ++ uint32 nand_timing_2_cs1; ++ uint32 PAD[20]; ++ uint32 nand_spare_rd16; ++ uint32 nand_spare_rd20; ++ uint32 nand_spare_rd24; ++ uint32 nand_spare_rd28; ++ uint32 nand_cache_addr; ++ uint32 nand_cache_data; ++ uint32 nand_ctrl_config; ++ uint32 nand_ctrl_status; ++#endif /* NFLASH_SUPPORT */ ++ uint32 gci_corecaps0; /* GCI starting at 0xC00 */ ++ uint32 gci_corecaps1; ++ uint32 gci_corecaps2; ++ uint32 gci_corectrl; ++ uint32 gci_corestat; /* 0xC10 */ ++ uint32 PAD[11]; ++ uint32 gci_indirect_addr; /* 0xC40 */ ++ uint32 PAD[111]; ++ uint32 gci_chipctrl; /* 0xE00 */ ++} chipcregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#if defined(IL_BIGENDIAN) && defined(BCMHND74K) ++/* Selective swapped defines for those registers we need in ++ * big-endian code. ++ */ ++#define CC_CHIPID 4 ++#define CC_CAPABILITIES 0 ++#define CC_CHIPST 0x28 ++#define CC_EROMPTR 0xf8 ++ ++#else /* !IL_BIGENDIAN || !BCMHND74K */ ++ ++#define CC_CHIPID 0 ++#define CC_CAPABILITIES 4 ++#define CC_CHIPST 0x2c ++#define CC_EROMPTR 0xfc ++ ++#endif /* IL_BIGENDIAN && BCMHND74K */ ++ ++#define CC_OTPST 0x10 ++#define CC_JTAGCMD 0x30 ++#define CC_JTAGIR 0x34 ++#define CC_JTAGDR 0x38 ++#define CC_JTAGCTRL 0x3c ++#define CC_GPIOPU 0x58 ++#define CC_GPIOPD 0x5c ++#define CC_GPIOIN 0x60 ++#define CC_GPIOOUT 0x64 ++#define CC_GPIOOUTEN 0x68 ++#define CC_GPIOCTRL 0x6c ++#define CC_GPIOPOL 0x70 ++#define CC_GPIOINTM 0x74 ++#define CC_WATCHDOG 0x80 ++#define CC_CLKC_N 0x90 ++#define CC_CLKC_M0 0x94 ++#define CC_CLKC_M1 0x98 ++#define CC_CLKC_M2 0x9c ++#define CC_CLKC_M3 0xa0 ++#define CC_CLKDIV 0xa4 ++#define CC_SYS_CLK_CTL 0xc0 ++#define CC_CLK_CTL_ST SI_CLK_CTL_ST ++#define PMU_CTL 0x600 ++#define PMU_CAP 0x604 ++#define PMU_ST 0x608 ++#define PMU_RES_STATE 0x60c ++#define PMU_TIMER 0x614 ++#define PMU_MIN_RES_MASK 0x618 ++#define PMU_MAX_RES_MASK 0x61c ++#define CC_CHIPCTL_ADDR 0x650 ++#define CC_CHIPCTL_DATA 0x654 ++#define PMU_REG_CONTROL_ADDR 0x658 ++#define PMU_REG_CONTROL_DATA 0x65C ++#define PMU_PLL_CONTROL_ADDR 0x660 ++#define PMU_PLL_CONTROL_DATA 0x664 ++#define CC_SROM_CTRL 0x190 ++#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ ++#define CC_GCI_INDIRECT_ADDR_REG 0xC40 ++#define CC_GCI_CHIP_CTRL_REG 0xE00 ++#define CC_GCI_CC_OFFSET_2 2 ++#define CC_GCI_CC_OFFSET_5 5 ++ ++#ifdef NFLASH_SUPPORT ++/* NAND flash support */ ++#define CC_NAND_REVISION 0xC00 ++#define CC_NAND_CMD_START 0xC04 ++#define CC_NAND_CMD_ADDR 0xC0C ++#define CC_NAND_SPARE_RD_0 0xC20 ++#define CC_NAND_SPARE_RD_4 0xC24 ++#define CC_NAND_SPARE_RD_8 0xC28 ++#define CC_NAND_SPARE_RD_C 0xC2C ++#define CC_NAND_CONFIG 0xC48 ++#define CC_NAND_DEVID 0xC60 ++#define CC_NAND_DEVID_EXT 0xC64 ++#define CC_NAND_INTFC_STATUS 0xC6C ++#endif /* NFLASH_SUPPORT */ ++ ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 ++#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ ++#define CID_TYPE_SHIFT 28 ++ ++/* capabilities */ ++#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ ++#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ ++#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ ++#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ ++#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ ++#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */ ++#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ ++#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ ++ ++#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ ++#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ ++ ++/* capabilities extension */ ++#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ ++ ++/* PLL type */ ++#define PLL_NONE 0x00000000 ++#define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */ ++#define PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */ ++#define PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */ ++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ ++#define PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */ ++ ++/* ILP clock */ ++#define ILP_CLOCK 32000 ++ ++/* ALP clock on pre-PMU chips */ ++#define ALP_CLOCK 20000000 ++ ++#define NS_ALP_CLOCK 125000000 ++#define NS_SLOW_ALP_CLOCK 100000000 ++#define NS_CPU_CLOCK 1000000000 ++#define NS_SLOW_CPU_CLOCK 800000000 ++#define NS_SI_CLOCK 250000000 ++#define NS_SLOW_SI_CLOCK 200000000 ++#define NS_FAST_MEM_CLOCK 800000000 ++#define NS_MEM_CLOCK 533000000 ++#define NS_SLOW_MEM_CLOCK 400000000 ++ ++/* HT clock */ ++#define HT_CLOCK 80000000 ++ ++/* corecontrol */ ++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ ++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ ++#define CC_ASYNCGPIO 0x00000004 /* 1=generate GPIO interrupt without backplane clock */ ++#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */ ++ ++/* 4321 chipcontrol */ ++#define CHIPCTRL_4321A0_DEFAULT 0x3a4 ++#define CHIPCTRL_4321A1_DEFAULT 0x0a4 ++#define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */ ++ ++/* Fields in the otpstatus register in rev >= 21 */ ++#define OTPS_OL_MASK 0x000000ff ++#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */ ++#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */ ++#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */ ++#define OTPS_OL_GU 0x00000008 /* general use region is locked */ ++#define OTPS_GUP_MASK 0x00000f00 ++#define OTPS_GUP_SHIFT 8 ++#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ ++#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ ++#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ ++#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ ++#define OTPS_READY 0x00001000 ++#define OTPS_RV(x) (1 << (16 + (x))) /* redundancy entry valid */ ++#define OTPS_RV_MASK 0x0fff0000 ++#define OTPS_PROGOK 0x40000000 ++ ++/* Fields in the otpcontrol register in rev >= 21 */ ++#define OTPC_PROGSEL 0x00000001 ++#define OTPC_PCOUNT_MASK 0x0000000e ++#define OTPC_PCOUNT_SHIFT 1 ++#define OTPC_VSEL_MASK 0x000000f0 ++#define OTPC_VSEL_SHIFT 4 ++#define OTPC_TMM_MASK 0x00000700 ++#define OTPC_TMM_SHIFT 8 ++#define OTPC_ODM 0x00000800 ++#define OTPC_PROGEN 0x80000000 ++ ++/* Fields in the 40nm otpcontrol register in rev >= 40 */ ++#define OTPC_40NM_PROGSEL_SHIFT 0 ++#define OTPC_40NM_PCOUNT_SHIFT 1 ++#define OTPC_40NM_PCOUNT_WR 0xA ++#define OTPC_40NM_PCOUNT_V1X 0xB ++#define OTPC_40NM_REGCSEL_SHIFT 5 ++#define OTPC_40NM_REGCSEL_DEF 0x4 ++#define OTPC_40NM_PROGIN_SHIFT 8 ++#define OTPC_40NM_R2X_SHIFT 10 ++#define OTPC_40NM_ODM_SHIFT 11 ++#define OTPC_40NM_DF_SHIFT 15 ++#define OTPC_40NM_VSEL_SHIFT 16 ++#define OTPC_40NM_VSEL_WR 0xA ++#define OTPC_40NM_VSEL_V1X 0xA ++#define OTPC_40NM_VSEL_R1X 0x5 ++#define OTPC_40NM_COFAIL_SHIFT 30 ++ ++#define OTPC1_CPCSEL_SHIFT 0 ++#define OTPC1_CPCSEL_DEF 6 ++#define OTPC1_TM_SHIFT 8 ++#define OTPC1_TM_WR 0x84 ++#define OTPC1_TM_V1X 0x84 ++#define OTPC1_TM_R1X 0x4 ++ ++/* Fields in otpprog in rev >= 21 and HND OTP */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_COL_SHIFT 0 ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_OC_MASK 0x0f000000 ++#define OTPP_OC_SHIFT 24 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE_MASK 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_START_BUSY 0x80000000 ++#define OTPP_READ 0x40000000 /* HND OTP */ ++ ++/* Fields in otplayout register */ ++#define OTPL_HWRGN_OFF_MASK 0x00000FFF ++#define OTPL_HWRGN_OFF_SHIFT 0 ++#define OTPL_WRAP_REVID_MASK 0x00F80000 ++#define OTPL_WRAP_REVID_SHIFT 19 ++#define OTPL_WRAP_TYPE_MASK 0x00070000 ++#define OTPL_WRAP_TYPE_SHIFT 16 ++#define OTPL_WRAP_TYPE_65NM 0 ++#define OTPL_WRAP_TYPE_40NM 1 ++ ++/* otplayout reg corerev >= 36 */ ++#define OTP_CISFORMAT_NEW 0x80000000 ++ ++/* Opcodes for OTPP_OC field */ ++#define OTPPOC_READ 0 ++#define OTPPOC_BIT_PROG 1 ++#define OTPPOC_VERIFY 3 ++#define OTPPOC_INIT 4 ++#define OTPPOC_SET 5 ++#define OTPPOC_RESET 6 ++#define OTPPOC_OCST 7 ++#define OTPPOC_ROW_LOCK 8 ++#define OTPPOC_PRESCN_TEST 9 ++ ++/* Opcodes for OTPP_OC field (40NM) */ ++#define OTPPOC_READ_40NM 0 ++#define OTPPOC_PROG_ENABLE_40NM 1 ++#define OTPPOC_PROG_DISABLE_40NM 2 ++#define OTPPOC_VERIFY_40NM 3 ++#define OTPPOC_WORD_VERIFY_1_40NM 4 ++#define OTPPOC_ROW_LOCK_40NM 5 ++#define OTPPOC_STBY_40NM 6 ++#define OTPPOC_WAKEUP_40NM 7 ++#define OTPPOC_WORD_VERIFY_0_40NM 8 ++#define OTPPOC_PRESCN_TEST_40NM 9 ++#define OTPPOC_BIT_PROG_40NM 10 ++#define OTPPOC_WORDPROG_40NM 11 ++#define OTPPOC_BURNIN_40NM 12 ++#define OTPPOC_AUTORELOAD_40NM 13 ++#define OTPPOC_OVST_READ_40NM 14 ++#define OTPPOC_OVST_PROG_40NM 15 ++ ++/* Fields in otplayoutextension */ ++#define OTPLAYOUTEXT_FUSE_MASK 0x3FF ++ ++ ++/* Jtagm characteristics that appeared at a given corerev */ ++#define JTAGM_CREV_OLD 10 /* Old command set, 16bit max IR */ ++#define JTAGM_CREV_IRP 22 /* Able to do pause-ir */ ++#define JTAGM_CREV_RTI 28 /* Able to do return-to-idle */ ++ ++/* jtagcmd */ ++#define JCMD_START 0x80000000 ++#define JCMD_BUSY 0x80000000 ++#define JCMD_STATE_MASK 0x60000000 ++#define JCMD_STATE_TLR 0x00000000 /* Test-logic-reset */ ++#define JCMD_STATE_PIR 0x20000000 /* Pause IR */ ++#define JCMD_STATE_PDR 0x40000000 /* Pause DR */ ++#define JCMD_STATE_RTI 0x60000000 /* Run-test-idle */ ++#define JCMD0_ACC_MASK 0x0000f000 ++#define JCMD0_ACC_IRDR 0x00000000 ++#define JCMD0_ACC_DR 0x00001000 ++#define JCMD0_ACC_IR 0x00002000 ++#define JCMD0_ACC_RESET 0x00003000 ++#define JCMD0_ACC_IRPDR 0x00004000 ++#define JCMD0_ACC_PDR 0x00005000 ++#define JCMD0_IRW_MASK 0x00000f00 ++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ ++#define JCMD_ACC_IRDR 0x00000000 ++#define JCMD_ACC_DR 0x00010000 ++#define JCMD_ACC_IR 0x00020000 ++#define JCMD_ACC_RESET 0x00030000 ++#define JCMD_ACC_IRPDR 0x00040000 ++#define JCMD_ACC_PDR 0x00050000 ++#define JCMD_ACC_PIR 0x00060000 ++#define JCMD_ACC_IRDR_I 0x00070000 /* rev 28: return to run-test-idle */ ++#define JCMD_ACC_DR_I 0x00080000 /* rev 28: return to run-test-idle */ ++#define JCMD_IRW_MASK 0x00001f00 ++#define JCMD_IRW_SHIFT 8 ++#define JCMD_DRW_MASK 0x0000003f ++ ++/* jtagctrl */ ++#define JCTRL_FORCE_CLK 4 /* Force clock */ ++#define JCTRL_EXT_EN 2 /* Enable external targets */ ++#define JCTRL_EN 1 /* Enable Jtag master */ ++ ++/* Fields in clkdiv */ ++#define CLKD_SFLASH 0x0f000000 ++#define CLKD_SFLASH_SHIFT 24 ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++#define CLKD_JTAG 0x00000f00 ++#define CLKD_JTAG_SHIFT 8 ++#define CLKD_UART 0x000000ff ++ ++#define CLKD2_SROM 0x00000003 ++ ++/* intstatus/intmask */ ++#define CI_GPIO 0x00000001 /* gpio intr */ ++#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */ ++#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */ ++#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */ ++#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */ ++#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */ ++#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */ ++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ ++ ++/* slow_clk_ctl */ ++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ ++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ ++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ ++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ ++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, ++ * 0: LPO is enabled ++ */ ++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, ++ * 0: power logic control ++ */ ++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors ++ * PLL clock disable requests from core ++ */ ++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't ++ * disable crystal when appropriate ++ */ ++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_SHIFT 16 ++ ++/* system_clk_ctl */ ++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ ++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ ++#define SYCC_FP 0x00000004 /* ForcePLLOn */ ++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_HR 0x00000010 /* Force HT */ ++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_SHIFT 16 ++ ++/* Indirect backplane access */ ++#define BPIA_BYTEEN 0x0000000f ++#define BPIA_SZ1 0x00000001 ++#define BPIA_SZ2 0x00000003 ++#define BPIA_SZ4 0x00000007 ++#define BPIA_SZ8 0x0000000f ++#define BPIA_WRITE 0x00000100 ++#define BPIA_START 0x00000200 ++#define BPIA_BUSY 0x00000200 ++#define BPIA_ERROR 0x00000400 ++ ++/* pcmcia/prog/flash_config */ ++#define CF_EN 0x00000001 /* enable */ ++#define CF_EM_MASK 0x0000000e /* mode */ ++#define CF_EM_SHIFT 1 ++#define CF_EM_FLASH 0 /* flash/asynchronous mode */ ++#define CF_EM_SYNC 2 /* synchronous mode */ ++#define CF_EM_PCMCIA 4 /* pcmcia mode */ ++#define CF_DS 0x00000010 /* destsize: 0=8bit, 1=16bit */ ++#define CF_BS 0x00000020 /* byteswap */ ++#define CF_CD_MASK 0x000000c0 /* clock divider */ ++#define CF_CD_SHIFT 6 ++#define CF_CD_DIV2 0x00000000 /* backplane/2 */ ++#define CF_CD_DIV3 0x00000040 /* backplane/3 */ ++#define CF_CD_DIV4 0x00000080 /* backplane/4 */ ++#define CF_CE 0x00000100 /* clock enable */ ++#define CF_SB 0x00000200 /* size/bytestrobe (synch only) */ ++ ++/* pcmcia_memwait */ ++#define PM_W0_MASK 0x0000003f /* waitcount0 */ ++#define PM_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PM_W1_SHIFT 8 ++#define PM_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PM_W2_SHIFT 16 ++#define PM_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PM_W3_SHIFT 24 ++ ++/* pcmcia_attrwait */ ++#define PA_W0_MASK 0x0000003f /* waitcount0 */ ++#define PA_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PA_W1_SHIFT 8 ++#define PA_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PA_W2_SHIFT 16 ++#define PA_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PA_W3_SHIFT 24 ++ ++/* pcmcia_iowait */ ++#define PI_W0_MASK 0x0000003f /* waitcount0 */ ++#define PI_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PI_W1_SHIFT 8 ++#define PI_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PI_W2_SHIFT 16 ++#define PI_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PI_W3_SHIFT 24 ++ ++/* prog_waitcount */ ++#define PW_W0_MASK 0x0000001f /* waitcount0 */ ++#define PW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PW_W1_SHIFT 8 ++#define PW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PW_W2_SHIFT 16 ++#define PW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PW_W3_SHIFT 24 ++ ++#define PW_W0 0x0000000c ++#define PW_W1 0x00000a00 ++#define PW_W2 0x00020000 ++#define PW_W3 0x01000000 ++ ++/* flash_waitcount */ ++#define FW_W0_MASK 0x0000003f /* waitcount0 */ ++#define FW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define FW_W1_SHIFT 8 ++#define FW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define FW_W2_SHIFT 16 ++#define FW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define FW_W3_SHIFT 24 ++ ++/* When Srom support present, fields in sromcontrol */ ++#define SRC_START 0x80000000 ++#define SRC_BUSY 0x80000000 ++#define SRC_OPCODE 0x60000000 ++#define SRC_OP_READ 0x00000000 ++#define SRC_OP_WRITE 0x20000000 ++#define SRC_OP_WRDIS 0x40000000 ++#define SRC_OP_WREN 0x60000000 ++#define SRC_OTPSEL 0x00000010 ++#define SRC_LOCK 0x00000008 ++#define SRC_SIZE_MASK 0x00000006 ++#define SRC_SIZE_1K 0x00000000 ++#define SRC_SIZE_4K 0x00000002 ++#define SRC_SIZE_16K 0x00000004 ++#define SRC_SIZE_SHIFT 1 ++#define SRC_PRESENT 0x00000001 ++ ++/* Fields in pmucontrol */ ++#define PCTL_ILP_DIV_MASK 0xffff0000 ++#define PCTL_ILP_DIV_SHIFT 16 ++#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ ++#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ ++#define PCTL_HT_REQ_EN 0x00000100 ++#define PCTL_ALP_REQ_EN 0x00000080 ++#define PCTL_XTALFREQ_MASK 0x0000007c ++#define PCTL_XTALFREQ_SHIFT 2 ++#define PCTL_ILP_DIV_EN 0x00000002 ++#define PCTL_LPO_SEL 0x00000001 ++ ++/* Fields in clkstretch */ ++#define CSTRETCH_HT 0xffff0000 ++#define CSTRETCH_ALP 0x0000ffff ++ ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 ++ ++/* clockcontrol_n */ ++#define CN_N1_MASK 0x3f /* n1 control */ ++#define CN_N2_MASK 0x3f00 /* n2 control */ ++#define CN_N2_SHIFT 8 ++#define CN_PLLC_MASK 0xf0000 /* pll control */ ++#define CN_PLLC_SHIFT 16 ++ ++/* clockcontrol_sb/pci/uart */ ++#define CC_M1_MASK 0x3f /* m1 control */ ++#define CC_M2_MASK 0x3f00 /* m2 control */ ++#define CC_M2_SHIFT 8 ++#define CC_M3_MASK 0x3f0000 /* m3 control */ ++#define CC_M3_SHIFT 16 ++#define CC_MC_MASK 0x1f000000 /* mux control */ ++#define CC_MC_SHIFT 24 ++ ++/* N3M Clock control magic field values */ ++#define CC_F6_2 0x02 /* A factor of 2 in */ ++#define CC_F6_3 0x03 /* 6-bit fields like */ ++#define CC_F6_4 0x05 /* N1, M1 or M3 */ ++#define CC_F6_5 0x09 ++#define CC_F6_6 0x11 ++#define CC_F6_7 0x21 ++ ++#define CC_F5_BIAS 5 /* 5-bit fields get this added */ ++ ++#define CC_MC_BYPASS 0x08 ++#define CC_MC_M1 0x04 ++#define CC_MC_M1M2 0x02 ++#define CC_MC_M1M2M3 0x01 ++#define CC_MC_M1M3 0x11 ++ ++/* Type 2 Clock control magic field values */ ++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ ++#define CC_T2M2_BIAS 3 /* m2 bias */ ++ ++#define CC_T2MC_M1BYP 1 ++#define CC_T2MC_M2BYP 2 ++#define CC_T2MC_M3BYP 4 ++ ++/* Type 6 Clock control magic field values */ ++#define CC_T6_MMASK 1 /* bits of interest in m */ ++#define CC_T6_M0 120000000 /* sb clock for m = 0 */ ++#define CC_T6_M1 100000000 /* sb clock for m = 1 */ ++#define SB2MIPS_T6(sb) (2 * (sb)) ++ ++/* Common clock base */ ++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ ++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLLs */ ++ ++/* Clock control values for 200MHz in 5350 */ ++#define CLKC_5350_N 0x0311 ++#define CLKC_5350_M 0x04020009 ++ ++/* Flash types in the chipcommon capabilities register */ ++#define FLASH_NONE 0x000 /* No flash */ ++#define SFLASH_ST 0x100 /* ST serial flash */ ++#define SFLASH_AT 0x200 /* Atmel serial flash */ ++#define NFLASH 0x300 ++#define PFLASH 0x700 /* Parallel flash */ ++#define QSPIFLASH_ST 0x800 ++#define QSPIFLASH_AT 0x900 ++ ++/* Bits in the ExtBus config registers */ ++#define CC_CFG_EN 0x0001 /* Enable */ ++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ ++#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */ ++#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */ ++#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ ++#define CC_CFG_EM_IDE 0x0006 /* IDE */ ++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ ++#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */ ++#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */ ++#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */ ++#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */ ++ ++/* ExtBus address space */ ++#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ ++#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */ ++#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */ ++#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */ ++#define CC_EB_IDE 0x1a800000 /* IDE memory base */ ++#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */ ++#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */ ++#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */ ++#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */ ++ ++ ++/* Start/busy bit in flashcontrol */ ++#define SFLASH_OPCODE 0x000000ff ++#define SFLASH_ACTION 0x00000700 ++#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ ++#define SFLASH_START 0x80000000 ++#define SFLASH_BUSY SFLASH_START ++ ++/* flashcontrol action codes */ ++#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */ ++#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */ ++#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 addr bytes */ ++#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addr & 1 data bytes */ ++#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addr & 4 data bytes */ ++#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addr, 4 don't care & 4 data bytes */ ++#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addr, 1 don't care & 4 data bytes */ ++ ++/* flashcontrol action+opcodes for ST flashes */ ++#define SFLASH_ST_WREN 0x0006 /* Write Enable */ ++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ ++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ ++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ ++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ ++#define SFLASH_ST_PP 0x0302 /* Page Program */ ++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ ++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ ++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ ++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ ++#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */ ++#define SFLASH_ST_SSE 0x0220 /* Sub-sector Erase */ ++ ++#define SFLASH_MXIC_RDID 0x0390 /* Read Manufacture ID */ ++#define SFLASH_MXIC_MFID 0xc2 /* MXIC Manufacture ID */ ++ ++/* Status register bits for ST flashes */ ++#define SFLASH_ST_WIP 0x01 /* Write In Progress */ ++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ ++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ ++#define SFLASH_ST_BP_SHIFT 2 ++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ ++ ++/* flashcontrol action+opcodes for Atmel flashes */ ++#define SFLASH_AT_READ 0x07e8 ++#define SFLASH_AT_PAGE_READ 0x07d2 ++#define SFLASH_AT_BUF1_READ ++#define SFLASH_AT_BUF2_READ ++#define SFLASH_AT_STATUS 0x01d7 ++#define SFLASH_AT_BUF1_WRITE 0x0384 ++#define SFLASH_AT_BUF2_WRITE 0x0387 ++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 ++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 ++#define SFLASH_AT_BUF1_PROGRAM 0x0288 ++#define SFLASH_AT_BUF2_PROGRAM 0x0289 ++#define SFLASH_AT_PAGE_ERASE 0x0281 ++#define SFLASH_AT_BLOCK_ERASE 0x0250 ++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 ++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 ++#define SFLASH_AT_BUF1_LOAD 0x0253 ++#define SFLASH_AT_BUF2_LOAD 0x0255 ++#define SFLASH_AT_BUF1_COMPARE 0x0260 ++#define SFLASH_AT_BUF2_COMPARE 0x0261 ++#define SFLASH_AT_BUF1_REPROGRAM 0x0258 ++#define SFLASH_AT_BUF2_REPROGRAM 0x0259 ++ ++/* Status register bits for Atmel flashes */ ++#define SFLASH_AT_READY 0x80 ++#define SFLASH_AT_MISMATCH 0x40 ++#define SFLASH_AT_ID_MASK 0x38 ++#define SFLASH_AT_ID_SHIFT 3 ++ ++/* SPI register bits, corerev >= 37 */ ++#define GSIO_START 0x80000000 ++#define GSIO_BUSY GSIO_START ++ ++/* ++ * These are the UART port assignments, expressed as offsets from the base ++ * register. These assignments should hold for any serial port based on ++ * a 8250, 16450, or 16550(A). ++ */ ++ ++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ ++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ ++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ ++#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */ ++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ ++#define UART_IIR 2 /* In: Interrupt Identity Register */ ++#define UART_FCR 2 /* Out: FIFO Control Register */ ++#define UART_LCR 3 /* Out: Line Control Register */ ++#define UART_MCR 4 /* Out: Modem Control Register */ ++#define UART_LSR 5 /* In: Line Status Register */ ++#define UART_MSR 6 /* In: Modem Status Register */ ++#define UART_SCR 7 /* I/O: Scratch Register */ ++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ ++#define UART_LCR_WLEN8 0x03 /* Word length: 8 bits */ ++#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */ ++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ ++#define UART_LSR_RX_FIFO 0x80 /* Receive FIFO error */ ++#define UART_LSR_TDHR 0x40 /* Data-hold-register empty */ ++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ ++#define UART_LSR_BREAK 0x10 /* Break interrupt */ ++#define UART_LSR_FRAMING 0x08 /* Framing error */ ++#define UART_LSR_PARITY 0x04 /* Parity error */ ++#define UART_LSR_OVERRUN 0x02 /* Overrun error */ ++#define UART_LSR_RXRDY 0x01 /* Receiver ready */ ++#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ ++ ++/* Interrupt Identity Register (IIR) bits */ ++#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */ ++#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */ ++#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */ ++#define UART_IIR_NOINT 0x1 /* No interrupt pending */ ++#define UART_IIR_THRE 0x2 /* THR empty */ ++#define UART_IIR_RCVD_DATA 0x4 /* Received data available */ ++#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */ ++#define UART_IIR_CHAR_TIME 0xc /* Character time */ ++ ++/* Interrupt Enable Register (IER) bits */ ++#define UART_IER_EDSSI 8 /* enable modem status interrupt */ ++#define UART_IER_ELSI 4 /* enable receiver line status interrupt */ ++#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ ++#define UART_IER_ERBFI 1 /* enable data available interrupt */ ++ ++/* pmustatus */ ++#define PST_EXTLPOAVAIL 0x0100 ++#define PST_WDRESET 0x0080 ++#define PST_INTPEND 0x0040 ++#define PST_SBCLKST 0x0030 ++#define PST_SBCLKST_ILP 0x0010 ++#define PST_SBCLKST_ALP 0x0020 ++#define PST_SBCLKST_HT 0x0030 ++#define PST_ALPAVAIL 0x0008 ++#define PST_HTAVAIL 0x0004 ++#define PST_RESINIT 0x0003 ++ ++/* pmucapabilities */ ++#define PCAP_REV_MASK 0x000000ff ++#define PCAP_RC_MASK 0x00001f00 ++#define PCAP_RC_SHIFT 8 ++#define PCAP_TC_MASK 0x0001e000 ++#define PCAP_TC_SHIFT 13 ++#define PCAP_PC_MASK 0x001e0000 ++#define PCAP_PC_SHIFT 17 ++#define PCAP_VC_MASK 0x01e00000 ++#define PCAP_VC_SHIFT 21 ++#define PCAP_CC_MASK 0x1e000000 ++#define PCAP_CC_SHIFT 25 ++#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ ++#define PCAP5_PC_SHIFT 17 ++#define PCAP5_VC_MASK 0x07c00000 ++#define PCAP5_VC_SHIFT 22 ++#define PCAP5_CC_MASK 0xf8000000 ++#define PCAP5_CC_SHIFT 27 ++ ++/* PMU Resource Request Timer registers */ ++/* This is based on PmuRev0 */ ++#define PRRT_TIME_MASK 0x03ff ++#define PRRT_INTEN 0x0400 ++#define PRRT_REQ_ACTIVE 0x0800 ++#define PRRT_ALP_REQ 0x1000 ++#define PRRT_HT_REQ 0x2000 ++#define PRRT_HQ_REQ 0x4000 ++ ++/* PMU resource bit position */ ++#define PMURES_BIT(bit) (1 << (bit)) ++ ++/* PMU resource number limit */ ++#define PMURES_MAX_RESNUM 30 ++ ++/* PMU chip control0 register */ ++#define PMU_CHIPCTL0 0 ++ ++/* clock req types */ ++#define PMU_CC1_CLKREQ_TYPE_SHIFT 19 ++#define PMU_CC1_CLKREQ_TYPE_MASK (1 << PMU_CC1_CLKREQ_TYPE_SHIFT) ++ ++#define CLKREQ_TYPE_CONFIG_OPENDRAIN 0 ++#define CLKREQ_TYPE_CONFIG_PUSHPULL 1 ++ ++/* PMU chip control1 register */ ++#define PMU_CHIPCTL1 1 ++#define PMU_CC1_RXC_DLL_BYPASS 0x00010000 ++ ++#define PMU_CC1_IF_TYPE_MASK 0x00000030 ++#define PMU_CC1_IF_TYPE_RMII 0x00000000 ++#define PMU_CC1_IF_TYPE_MII 0x00000010 ++#define PMU_CC1_IF_TYPE_RGMII 0x00000020 ++ ++#define PMU_CC1_SW_TYPE_MASK 0x000000c0 ++#define PMU_CC1_SW_TYPE_EPHY 0x00000000 ++#define PMU_CC1_SW_TYPE_EPHYMII 0x00000040 ++#define PMU_CC1_SW_TYPE_EPHYRMII 0x00000080 ++#define PMU_CC1_SW_TYPE_RGMII 0x000000c0 ++ ++/* PMU chip control2 register */ ++#define PMU_CHIPCTL2 2 ++ ++/* PMU chip control3 register */ ++#define PMU_CHIPCTL3 3 ++ ++#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19 ++#define PMU_CC3_ENABLE_RF_SHIFT 22 ++#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 ++ ++ ++/* PMU corerev and chip specific PLL controls. ++ * PMU_PLL_XX where is PMU corerev and is an arbitrary number ++ * to differentiate different PLLs controlled by the same PMU rev. ++ */ ++/* pllcontrol registers */ ++/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */ ++#define PMU0_PLL0_PLLCTL0 0 ++#define PMU0_PLL0_PC0_PDIV_MASK 1 ++#define PMU0_PLL0_PC0_PDIV_FREQ 25000 ++#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 ++#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 ++#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 ++ ++/* PC0_DIV_ARM for PLLOUT_ARM */ ++#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 ++#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 ++#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 ++#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */ ++#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 ++#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 ++#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 ++#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 ++ ++/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */ ++#define PMU0_PLL0_PLLCTL1 1 ++#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 ++#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 ++#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 ++#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 ++#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 ++ ++/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */ ++#define PMU0_PLL0_PLLCTL2 2 ++#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf ++#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 ++ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU1_PLL0_PLLCTL0 0 ++#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 ++#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 ++#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 ++#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU1_PLL0_PLLCTL1 1 ++#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 ++#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 ++#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 ++#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 ++#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 ++#define PMU1_PLL0_PC1_M4DIV_BY_9 9 ++#define PMU1_PLL0_PC1_M4DIV_BY_18 0x12 ++#define PMU1_PLL0_PC1_M4DIV_BY_36 0x24 ++ ++#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 ++#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU1_PLL0_PLLCTL2 2 ++#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 ++#define PMU1_PLL0_PC2_M5DIV_BY_12 0xc ++#define PMU1_PLL0_PC2_M5DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M5DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 ++#define PMU1_PLL0_PC2_M6DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M6DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1 ++#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */ ++#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU1_PLL0_PLLCTL3 3 ++#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU1_PLL0_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU1_PLL0_PLLCTL5 5 ++#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 ++#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 ++ ++/* PMU rev 2 control words */ ++#define PMU2_PHY_PLL_PLLCTL 4 ++#define PMU2_SI_PLL_PLLCTL 10 ++ ++/* PMU rev 2 */ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU2_PLL_PLLCTL0 0 ++#define PMU2_PLL_PC0_P1DIV_MASK 0x00f00000 ++#define PMU2_PLL_PC0_P1DIV_SHIFT 20 ++#define PMU2_PLL_PC0_P2DIV_MASK 0x0f000000 ++#define PMU2_PLL_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU2_PLL_PLLCTL1 1 ++#define PMU2_PLL_PC1_M1DIV_MASK 0x000000ff ++#define PMU2_PLL_PC1_M1DIV_SHIFT 0 ++#define PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC1_M2DIV_SHIFT 8 ++#define PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU2_PLL_PC1_M3DIV_SHIFT 16 ++#define PMU2_PLL_PC1_M4DIV_MASK 0xff000000 ++#define PMU2_PLL_PC1_M4DIV_SHIFT 24 ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU2_PLL_PLLCTL2 2 ++#define PMU2_PLL_PC2_M5DIV_MASK 0x000000ff ++#define PMU2_PLL_PC2_M5DIV_SHIFT 0 ++#define PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC2_M6DIV_SHIFT 8 ++#define PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU2_PLL_PC2_NDIV_MODE_SHIFT 17 ++#define PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU2_PLL_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU2_PLL_PLLCTL3 3 ++#define PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU2_PLL_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU2_PLL_PLLCTL5 5 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28 ++ ++/* PMU rev 5 (& 6) */ ++#define PMU5_PLL_P1P2_OFF 0 ++#define PMU5_PLL_P1_MASK 0x0f000000 ++#define PMU5_PLL_P1_SHIFT 24 ++#define PMU5_PLL_P2_MASK 0x00f00000 ++#define PMU5_PLL_P2_SHIFT 20 ++#define PMU5_PLL_M14_OFF 1 ++#define PMU5_PLL_MDIV_MASK 0x000000ff ++#define PMU5_PLL_MDIV_WIDTH 8 ++#define PMU5_PLL_NM5_OFF 2 ++#define PMU5_PLL_NDIV_MASK 0xfff00000 ++#define PMU5_PLL_NDIV_SHIFT 20 ++#define PMU5_PLL_NDIV_MODE_MASK 0x000e0000 ++#define PMU5_PLL_NDIV_MODE_SHIFT 17 ++#define PMU5_PLL_FMAB_OFF 3 ++#define PMU5_PLL_MRAT_MASK 0xf0000000 ++#define PMU5_PLL_MRAT_SHIFT 28 ++#define PMU5_PLL_ABRAT_MASK 0x08000000 ++#define PMU5_PLL_ABRAT_SHIFT 27 ++#define PMU5_PLL_FDIV_MASK 0x07ffffff ++#define PMU5_PLL_PLLCTL_OFF 4 ++#define PMU5_PLL_PCHI_OFF 5 ++#define PMU5_PLL_PCHI_MASK 0x0000003f ++ ++/* pmu XtalFreqRatio */ ++#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF ++#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 ++#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 ++ ++/* Divider allocation in 4716/47162/5356/5357 */ ++#define PMU5_MAINPLL_CPU 1 ++#define PMU5_MAINPLL_MEM 2 ++#define PMU5_MAINPLL_SI 3 ++ ++/* 4706 PMU */ ++#define PMU4706_MAINPLL_PLL0 0 ++#define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ ++#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 ++#define PMU6_4706_PROC_P2DIV_SHIFT 16 ++#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 ++#define PMU6_4706_PROC_P1DIV_SHIFT 12 ++#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 ++#define PMU6_4706_PROC_NDIV_INT_SHIFT 3 ++#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 ++#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0 ++ ++#define PMU7_PLL_PLLCTL7 7 ++#define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000 ++#define PMU7_PLL_CTL7_M4DIV_SHIFT 24 ++#define PMU7_PLL_CTL7_M4DIV_BY_6 6 ++#define PMU7_PLL_CTL7_M4DIV_BY_12 0xc ++#define PMU7_PLL_CTL7_M4DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL8 8 ++#define PMU7_PLL_CTL8_M5DIV_MASK 0x000000ff ++#define PMU7_PLL_CTL8_M5DIV_SHIFT 0 ++#define PMU7_PLL_CTL8_M5DIV_BY_8 8 ++#define PMU7_PLL_CTL8_M5DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M5DIV_BY_24 0x18 ++#define PMU7_PLL_CTL8_M6DIV_MASK 0x0000ff00 ++#define PMU7_PLL_CTL8_M6DIV_SHIFT 8 ++#define PMU7_PLL_CTL8_M6DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M6DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL11 11 ++#define PMU7_PLL_PLLCTL11_MASK 0xffffff00 ++#define PMU7_PLL_PLLCTL11_VAL 0x22222200 ++ ++/* PMU rev 15 */ ++#define PMU15_PLL_PLLCTL0 0 ++#define PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 ++#define PMU15_PLL_PC0_CLKSEL_SHIFT 0 ++#define PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC ++#define PMU15_PLL_PC0_FREQTGT_SHIFT 2 ++#define PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 ++#define PMU15_PLL_PC0_PRESCALE_SHIFT 22 ++#define PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 ++#define PMU15_PLL_PC0_KPCTRL_SHIFT 24 ++#define PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 ++#define PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 ++#define PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 ++#define PMU15_PLL_PC0_FDCMODE_SHIFT 30 ++#define PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 ++#define PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 ++ ++#define PMU15_PLL_PLLCTL1 1 ++#define PMU15_PLL_PC1_BIAS_CTLM_MASK 0x00000060 ++#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT 5 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK 0x00000040 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT 6 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK 0x0001FF80 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT 7 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK 0x03FE0000 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT 17 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK 0x0C000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT 26 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK 0x10000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT 28 ++#define PMU15_PLL_PC1_OPENLP_EN_MASK 0x40000000 ++#define PMU15_PLL_PC1_OPENLP_EN_SHIFT 30 ++ ++#define PMU15_PLL_PLLCTL2 2 ++#define PMU15_PLL_PC2_CTEN_MASK 0x00000001 ++#define PMU15_PLL_PC2_CTEN_SHIFT 0 ++ ++#define PMU15_PLL_PLLCTL3 3 ++#define PMU15_PLL_PC3_DITHER_EN_MASK 0x00000001 ++#define PMU15_PLL_PC3_DITHER_EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_MASK 0xFE000000 ++#define PMU15_PLL_PC3_DCOCTLSP_SHIFT 25 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK 0x01 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK 0x02 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK 0x04 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK 0x18 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT 3 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK 0x60 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT 5 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5 3 ++ ++#define PMU15_PLL_PLLCTL4 4 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK 0x00000007 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT 0 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK 0x00000038 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT 3 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK 0x000001C0 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT 6 ++#define PMU15_PLL_PC4_DBGMODE_MASK 0x00000E00 ++#define PMU15_PLL_PC4_DBGMODE_SHIFT 9 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK 0x00001000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT 12 ++#define PMU15_PLL_PC4_FLL480_CTLSP_MASK 0x000FE000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT 13 ++#define PMU15_PLL_PC4_DINPOL_MASK 0x00100000 ++#define PMU15_PLL_PC4_DINPOL_SHIFT 20 ++#define PMU15_PLL_PC4_CLKOUT_PD_MASK 0x00200000 ++#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT 21 ++#define PMU15_PLL_PC4_CLKDIV2_PD_MASK 0x00400000 ++#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT 22 ++#define PMU15_PLL_PC4_CLKDIV4_PD_MASK 0x00800000 ++#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT 23 ++#define PMU15_PLL_PC4_CLKDIV8_PD_MASK 0x01000000 ++#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT 24 ++#define PMU15_PLL_PC4_CLKDIV16_PD_MASK 0x02000000 ++#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT 25 ++#define PMU15_PLL_PC4_TEST_EN_MASK 0x04000000 ++#define PMU15_PLL_PC4_TEST_EN_SHIFT 26 ++ ++#define PMU15_PLL_PLLCTL5 5 ++#define PMU15_PLL_PC5_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC5_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC5_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC5_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC5_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC5_PRESCALE_SHIFT 27 ++ ++#define PMU15_PLL_PLLCTL6 6 ++#define PMU15_PLL_PC6_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC6_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC6_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC6_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC6_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC6_PRESCALE_SHIFT 27 ++ ++#define PMU15_FREQTGT_480_DEFAULT 0x19AB1 ++#define PMU15_FREQTGT_492_DEFAULT 0x1A4F5 ++#define PMU15_ARM_96MHZ 96000000 /* 96 Mhz */ ++#define PMU15_ARM_98MHZ 98400000 /* 98.4 Mhz */ ++#define PMU15_ARM_97MHZ 97000000 /* 97 Mhz */ ++ ++ ++#define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070 ++#define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4 ++ ++#define PMU17_PLLCTL2_NDIV_MODE_INT 0 ++#define PMU17_PLLCTL2_NDIV_MODE_INT1B8 1 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111 2 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8 3 ++ ++#define PMU17_PLLCTL0_BBPLL_PWRDWN 0 ++#define PMU17_PLLCTL0_BBPLL_DRST 3 ++#define PMU17_PLLCTL0_BBPLL_DISBL_CLK 8 ++ ++/* PLL usage in 4716/47162 */ ++#define PMU4716_MAINPLL_PLL0 12 ++ ++/* PLL usage in 5356/5357 */ ++#define PMU5356_MAINPLL_PLL0 0 ++#define PMU5357_MAINPLL_PLL0 0 ++ ++/* 4716/47162 resources */ ++#define RES4716_PROC_PLL_ON 0x00000040 ++#define RES4716_PROC_HT_AVAIL 0x00000080 ++ ++/* 4716/4717/4718 Chip specific ChipControl register bits */ ++#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++/* 2nd - 32-bit reg */ ++#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */ ++#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */ ++ ++/* 5354 resources */ ++#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES5354_ILP_REQUEST 4 /* 0x00010 */ ++#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES5354_ROM_SWITCH 7 /* 0x00080 */ ++#define RES5354_PA_REF_LDO 8 /* 0x00100 */ ++#define RES5354_RADIO_LDO 9 /* 0x00200 */ ++#define RES5354_AFE_LDO 10 /* 0x00400 */ ++#define RES5354_PLL_LDO 11 /* 0x00800 */ ++#define RES5354_BG_FILTBYP 12 /* 0x01000 */ ++#define RES5354_TX_FILTBYP 13 /* 0x02000 */ ++#define RES5354_RX_FILTBYP 14 /* 0x04000 */ ++#define RES5354_XTAL_PU 15 /* 0x08000 */ ++#define RES5354_XTAL_EN 16 /* 0x10000 */ ++#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES5354_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ ++#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ ++#define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */ ++ ++/* 4328 resources */ ++#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES4328_ILP_REQUEST 4 /* 0x00010 */ ++#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES4328_ROM_SWITCH 7 /* 0x00080 */ ++#define RES4328_PA_REF_LDO 8 /* 0x00100 */ ++#define RES4328_RADIO_LDO 9 /* 0x00200 */ ++#define RES4328_AFE_LDO 10 /* 0x00400 */ ++#define RES4328_PLL_LDO 11 /* 0x00800 */ ++#define RES4328_BG_FILTBYP 12 /* 0x01000 */ ++#define RES4328_TX_FILTBYP 13 /* 0x02000 */ ++#define RES4328_RX_FILTBYP 14 /* 0x04000 */ ++#define RES4328_XTAL_PU 15 /* 0x08000 */ ++#define RES4328_XTAL_EN 16 /* 0x10000 */ ++#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES4328_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 4325 A0/A1 resources */ ++#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */ ++#define RES4325_CBUCK_BURST 1 /* 0x00000002 */ ++#define RES4325_CBUCK_PWM 2 /* 0x00000004 */ ++#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */ ++#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */ ++#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */ ++#define RES4325_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4325_ABUCK_BURST 7 /* 0x00000080 */ ++#define RES4325_ABUCK_PWM 8 /* 0x00000100 */ ++#define RES4325_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4325_OTP_PU 10 /* 0x00000400 */ ++#define RES4325_LNLDO3_PU 11 /* 0x00000800 */ ++#define RES4325_LNLDO4_PU 12 /* 0x00001000 */ ++#define RES4325_XTAL_PU 13 /* 0x00002000 */ ++#define RES4325_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4325_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4325 B0/C0 resources */ ++#define RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4325B0_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4325B0_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4325B0_CLDO_PU 4 /* 0x00000010 */ ++ ++/* 4325 C1 resources */ ++#define RES4325C1_LNLDO2_PU 12 /* 0x00001000 */ ++ ++/* 4325 chip-specific ChipStatus register bits */ ++#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4325_SDIO_USB_MODE_MASK 0x00000004 ++#define CST4325_SDIO_USB_MODE_SHIFT 2 ++#define CST4325_RCAL_VALID_MASK 0x00000008 ++#define CST4325_RCAL_VALID_SHIFT 3 ++#define CST4325_RCAL_VALUE_MASK 0x000001f0 ++#define CST4325_RCAL_VALUE_SHIFT 4 ++#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */ ++#define CST4325_PMUTOP_2B_SHIFT 9 ++ ++#define RES4329_RESERVED0 0 /* 0x00000001 */ ++#define RES4329_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4329_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4329_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4329_CLDO_PU 4 /* 0x00000010 */ ++#define RES4329_PALDO_PU 5 /* 0x00000020 */ ++#define RES4329_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4329_RESERVED7 7 /* 0x00000080 */ ++#define RES4329_RESERVED8 8 /* 0x00000100 */ ++#define RES4329_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4329_OTP_PU 10 /* 0x00000400 */ ++#define RES4329_RESERVED11 11 /* 0x00000800 */ ++#define RES4329_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4329_XTAL_PU 13 /* 0x00002000 */ ++#define RES4329_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4329_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4329_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4329_HT_AVAIL 21 /* 0x00200000 */ ++ ++#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 ++#define CST4329_SPI_SDIO_MODE_SHIFT 2 ++ ++/* 4312 chip-specific ChipStatus register bits */ ++#define CST4312_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4312_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4312_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4312_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4312_OTP_BAD 3 /* OTP is broken, SPROM is present */ ++ ++/* 4312 resources (all PMU chips with little memory constraint) */ ++#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */ ++#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */ ++#define RES4312_PA_REF_LDO 2 /* 0x00000004 */ ++#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */ ++#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */ ++#define RES4312_RADIO_LDO 5 /* 0x00000020 */ ++#define RES4312_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4312_BG_FILTBYP 7 /* 0x00000080 */ ++#define RES4312_TX_FILTBYP 8 /* 0x00000100 */ ++#define RES4312_RX_FILTBYP 9 /* 0x00000200 */ ++#define RES4312_XTAL_PU 10 /* 0x00000400 */ ++#define RES4312_ALP_AVAIL 11 /* 0x00000800 */ ++#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */ ++#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */ ++#define RES4312_HT_AVAIL 14 /* 0x00004000 */ ++ ++/* 4322 resources */ ++#define RES4322_RF_LDO 0 ++#define RES4322_ILP_REQUEST 1 ++#define RES4322_XTAL_PU 2 ++#define RES4322_ALP_AVAIL 3 ++#define RES4322_SI_PLL_ON 4 ++#define RES4322_HT_SI_AVAIL 5 ++#define RES4322_PHY_PLL_ON 6 ++#define RES4322_HT_PHY_AVAIL 7 ++#define RES4322_OTP_PU 8 ++ ++/* 4322 chip-specific ChipStatus register bits */ ++#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 ++#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 ++#define CST4322_SPROM_OTP_SEL_SHIFT 6 ++#define CST4322_NO_SPROM_OTP 0 /* no OTP, no SPROM */ ++#define CST4322_SPROM_PRESENT 1 /* SPROM is present */ ++#define CST4322_OTP_PRESENT 2 /* OTP is present */ ++#define CST4322_PCI_OR_USB 0x00000100 ++#define CST4322_BOOT_MASK 0x00000600 ++#define CST4322_BOOT_SHIFT 9 ++#define CST4322_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST4322_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST4322_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST4322_BOOT_FROM_INVALID 3 ++#define CST4322_ILP_DIV_EN 0x00000800 ++#define CST4322_FLASH_TYPE_MASK 0x00001000 ++#define CST4322_FLASH_TYPE_SHIFT 12 ++#define CST4322_FLASH_TYPE_SHIFT_ST 0 /* ST serial FLASH */ ++#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /* ATMEL flash */ ++#define CST4322_ARM_TAP_SEL 0x00002000 ++#define CST4322_RES_INIT_MODE_MASK 0x0000c000 ++#define CST4322_RES_INIT_MODE_SHIFT 14 ++#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /* resinitmode: ILP available */ ++#define CST4322_RES_INIT_MODE_ILPREQ 1 /* resinitmode: ILP request */ ++#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /* resinitmode: ALP available */ ++#define CST4322_RES_INIT_MODE_HTAVAIL 3 /* resinitmode: HT available */ ++#define CST4322_PCIPLLCLK_GATING 0x00010000 ++#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 ++#define CST4322_PCI_CARDBUS_MODE 0x00040000 ++ ++/* 43224 chip-specific ChipControl register bits */ ++#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ ++#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ ++#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ ++ ++/* 43236 resources */ ++#define RES43236_REGULATOR 0 ++#define RES43236_ILP_REQUEST 1 ++#define RES43236_XTAL_PU 2 ++#define RES43236_ALP_AVAIL 3 ++#define RES43236_SI_PLL_ON 4 ++#define RES43236_HT_SI_AVAIL 5 ++ ++/* 43236 chip-specific ChipControl register bits */ ++#define CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43236_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43236_GSIO (1<<4) /* 0 disable */ ++ ++/* 43236 Chip specific ChipStatus register bits */ ++#define CST43236_SFLASH_MASK 0x00000040 ++#define CST43236_OTP_SEL_MASK 0x00000080 ++#define CST43236_OTP_SEL_SHIFT 7 ++#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43236_BOOT_MASK 0x00001800 ++#define CST43236_BOOT_SHIFT 11 ++#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43236_BOOT_FROM_INVALID 3 ++ ++/* 43237 resources */ ++#define RES43237_REGULATOR 0 ++#define RES43237_ILP_REQUEST 1 ++#define RES43237_XTAL_PU 2 ++#define RES43237_ALP_AVAIL 3 ++#define RES43237_SI_PLL_ON 4 ++#define RES43237_HT_SI_AVAIL 5 ++ ++/* 43237 chip-specific ChipControl register bits */ ++#define CCTRL43237_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43237_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43237_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43237_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43237_GSIO (1<<4) /* 0 disable */ ++ ++/* 43237 Chip specific ChipStatus register bits */ ++#define CST43237_SFLASH_MASK 0x00000040 ++#define CST43237_OTP_SEL_MASK 0x00000080 ++#define CST43237_OTP_SEL_SHIFT 7 ++#define CST43237_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43237_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43237_BOOT_MASK 0x00001800 ++#define CST43237_BOOT_SHIFT 11 ++#define CST43237_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43237_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43237_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43237_BOOT_FROM_INVALID 3 ++ ++/* 43239 resources */ ++#define RES43239_OTP_PU 9 ++#define RES43239_MACPHY_CLKAVAIL 23 ++#define RES43239_HT_AVAIL 24 ++ ++/* 43239 Chip specific ChipStatus register bits */ ++#define CST43239_SPROM_MASK 0x00000002 ++#define CST43239_SFLASH_MASK 0x00000004 ++#define CST43239_RES_INIT_MODE_SHIFT 7 ++#define CST43239_RES_INIT_MODE_MASK 0x000001f0 ++#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /* SDIO || gSPI */ ++#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /* USB || USBDA */ ++#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /* SDIO */ ++#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */ ++ ++/* 4324 resources */ ++#define RES4324_OTP_PU 10 ++#define RES4324_HT_AVAIL 29 ++#define RES4324_MACPHY_CLKAVAIL 30 ++ ++/* 4324 Chip specific ChipStatus register bits */ ++#define CST4324_SPROM_MASK 0x00000080 ++#define CST4324_SFLASH_MASK 0x00400000 ++#define CST4324_RES_INIT_MODE_SHIFT 10 ++#define CST4324_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4324_CHIPMODE_MASK 0x7 ++#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */ ++#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */ ++ ++/* 4331 resources */ ++#define RES4331_REGULATOR 0 ++#define RES4331_ILP_REQUEST 1 ++#define RES4331_XTAL_PU 2 ++#define RES4331_ALP_AVAIL 3 ++#define RES4331_SI_PLL_ON 4 ++#define RES4331_HT_SI_AVAIL 5 ++ ++/* 4331 chip-specific ChipControl register bits */ ++#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL4331_EXT_LNA_G (1<<2) /* 0 disable */ ++#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */ ++#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */ ++#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */ ++#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ ++#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */ ++#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ ++#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ ++#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ ++#define CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_EXT_LNA_A (1<<13) /* 0 disable */ ++#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ ++#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ ++#define CCTRL4331_EXTPA_ANA_EN (1<<24) /* 0 ext pa disable, 1 ext pa enabled */ ++ ++/* 4331 Chip specific ChipStatus register bits */ ++#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */ ++#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 ++#define CST4331_SPROM_OTP_SEL_SHIFT 1 ++#define CST4331_SPROM_PRESENT 0x00000002 ++#define CST4331_OTP_PRESENT 0x00000004 ++#define CST4331_LDO_RF 0x00000008 ++#define CST4331_LDO_PAR 0x00000010 ++ ++/* 4315 resource */ ++#define RES4315_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4315_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4315_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4315_CLDO_PU 4 /* 0x00000010 */ ++#define RES4315_PALDO_PU 5 /* 0x00000020 */ ++#define RES4315_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4315_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4315_OTP_PU 10 /* 0x00000400 */ ++#define RES4315_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4315_XTAL_PU 13 /* 0x00002000 */ ++#define RES4315_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4315_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4315_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4315_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4315 chip-specific ChipStatus register bits */ ++#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /* gpio [7:6], SDIO CIS selection */ ++#define CST4315_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4315_SPROM_SEL 0x00000001 /* use SPROM, OTP is powered up */ ++#define CST4315_OTP_SEL 0x00000002 /* use OTP, OTP is powered up */ ++#define CST4315_OTP_PWRDN 0x00000003 /* use SPROM, OTP is powered down */ ++#define CST4315_SDIO_MODE 0x00000004 /* gpio [8], sdio/usb mode */ ++#define CST4315_RCAL_VALID 0x00000008 ++#define CST4315_RCAL_VALUE_MASK 0x000001f0 ++#define CST4315_RCAL_VALUE_SHIFT 4 ++#define CST4315_PALDO_EXTPNP 0x00000200 /* PALDO is configured with external PNP */ ++#define CST4315_CBUCK_MODE_MASK 0x00000c00 ++#define CST4315_CBUCK_MODE_BURST 0x00000400 ++#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 ++ ++/* 4319 resources */ ++#define RES4319_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4319_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4319_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4319_CLDO_PU 4 /* 0x00000010 */ ++#define RES4319_PALDO_PU 5 /* 0x00000020 */ ++#define RES4319_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4319_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4319_OTP_PU 10 /* 0x00000400 */ ++#define RES4319_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4319_XTAL_PU 13 /* 0x00002000 */ ++#define RES4319_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4319_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4319_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4319_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4319 chip-specific ChipStatus register bits */ ++#define CST4319_SPI_CPULESSUSB 0x00000001 ++#define CST4319_SPI_CLK_POL 0x00000002 ++#define CST4319_SPI_CLK_PH 0x00000008 ++#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */ ++#define CST4319_SPROM_OTP_SEL_SHIFT 6 ++#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */ ++#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ ++#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ ++#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */ ++#define CST4319_REMAP_SEL_MASK 0x00000600 ++#define CST4319_ILPDIV_EN 0x00000800 ++#define CST4319_XTAL_PD_POL 0x00001000 ++#define CST4319_LPO_SEL 0x00002000 ++#define CST4319_RES_INIT_MODE 0x0000c000 ++#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */ ++#define CST4319_CBUCK_MODE_MASK 0x00060000 ++#define CST4319_CBUCK_MODE_BURST 0x00020000 ++#define CST4319_CBUCK_MODE_LPBURST 0x00060000 ++#define CST4319_RCAL_VALID 0x01000000 ++#define CST4319_RCAL_VALUE_MASK 0x3e000000 ++#define CST4319_RCAL_VALUE_SHIFT 25 ++ ++#define PMU1_PLL0_CHIPCTL0 0 ++#define PMU1_PLL0_CHIPCTL1 1 ++#define PMU1_PLL0_CHIPCTL2 2 ++#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 ++#define CCTL_4319USB_XTAL_SEL_SHIFT 19 ++#define CCTL_4319USB_48MHZ_PLL_SEL 1 ++#define CCTL_4319USB_24MHZ_PLL_SEL 2 ++ ++/* PMU resources for 4336 */ ++#define RES4336_CBUCK_LPOM 0 ++#define RES4336_CBUCK_BURST 1 ++#define RES4336_CBUCK_LP_PWM 2 ++#define RES4336_CBUCK_PWM 3 ++#define RES4336_CLDO_PU 4 ++#define RES4336_DIS_INT_RESET_PD 5 ++#define RES4336_ILP_REQUEST 6 ++#define RES4336_LNLDO_PU 7 ++#define RES4336_LDO3P3_PU 8 ++#define RES4336_OTP_PU 9 ++#define RES4336_XTAL_PU 10 ++#define RES4336_ALP_AVAIL 11 ++#define RES4336_RADIO_PU 12 ++#define RES4336_BG_PU 13 ++#define RES4336_VREG1p4_PU_PU 14 ++#define RES4336_AFE_PWRSW_PU 15 ++#define RES4336_RX_PWRSW_PU 16 ++#define RES4336_TX_PWRSW_PU 17 ++#define RES4336_BB_PWRSW_PU 18 ++#define RES4336_SYNTH_PWRSW_PU 19 ++#define RES4336_MISC_PWRSW_PU 20 ++#define RES4336_LOGEN_PWRSW_PU 21 ++#define RES4336_BBPLL_PWRSW_PU 22 ++#define RES4336_MACPHY_CLKAVAIL 23 ++#define RES4336_HT_AVAIL 24 ++#define RES4336_RSVD 25 ++ ++/* 4336 chip-specific ChipStatus register bits */ ++#define CST4336_SPI_MODE_MASK 0x00000001 ++#define CST4336_SPROM_PRESENT 0x00000002 ++#define CST4336_OTP_PRESENT 0x00000004 ++#define CST4336_ARMREMAP_0 0x00000008 ++#define CST4336_ILPDIV_EN_MASK 0x00000010 ++#define CST4336_ILPDIV_EN_SHIFT 4 ++#define CST4336_XTAL_PD_POL_MASK 0x00000020 ++#define CST4336_XTAL_PD_POL_SHIFT 5 ++#define CST4336_LPO_SEL_MASK 0x00000040 ++#define CST4336_LPO_SEL_SHIFT 6 ++#define CST4336_RES_INIT_MODE_MASK 0x00000180 ++#define CST4336_RES_INIT_MODE_SHIFT 7 ++#define CST4336_CBUCK_MODE_MASK 0x00000600 ++#define CST4336_CBUCK_MODE_SHIFT 9 ++ ++/* 4336 Chip specific PMU ChipControl register bits */ ++#define PCTL_4336_SERIAL_ENAB (1 << 24) ++ ++/* 4330 resources */ ++#define RES4330_CBUCK_LPOM 0 ++#define RES4330_CBUCK_BURST 1 ++#define RES4330_CBUCK_LP_PWM 2 ++#define RES4330_CBUCK_PWM 3 ++#define RES4330_CLDO_PU 4 ++#define RES4330_DIS_INT_RESET_PD 5 ++#define RES4330_ILP_REQUEST 6 ++#define RES4330_LNLDO_PU 7 ++#define RES4330_LDO3P3_PU 8 ++#define RES4330_OTP_PU 9 ++#define RES4330_XTAL_PU 10 ++#define RES4330_ALP_AVAIL 11 ++#define RES4330_RADIO_PU 12 ++#define RES4330_BG_PU 13 ++#define RES4330_VREG1p4_PU_PU 14 ++#define RES4330_AFE_PWRSW_PU 15 ++#define RES4330_RX_PWRSW_PU 16 ++#define RES4330_TX_PWRSW_PU 17 ++#define RES4330_BB_PWRSW_PU 18 ++#define RES4330_SYNTH_PWRSW_PU 19 ++#define RES4330_MISC_PWRSW_PU 20 ++#define RES4330_LOGEN_PWRSW_PU 21 ++#define RES4330_BBPLL_PWRSW_PU 22 ++#define RES4330_MACPHY_CLKAVAIL 23 ++#define RES4330_HT_AVAIL 24 ++#define RES4330_5gRX_PWRSW_PU 25 ++#define RES4330_5gTX_PWRSW_PU 26 ++#define RES4330_5g_LOGEN_PWRSW_PU 27 ++ ++/* 4330 chip-specific ChipStatus register bits */ ++#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */ ++#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */ ++#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */ ++#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */ ++#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */ ++#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */ ++#define CST4330_OTP_PRESENT 0x00000010 ++#define CST4330_LPO_AUTODET_EN 0x00000020 ++#define CST4330_ARMREMAP_0 0x00000040 ++#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */ ++#define CST4330_ILPDIV_EN 0x00000100 ++#define CST4330_LPO_SEL 0x00000200 ++#define CST4330_RES_INIT_MODE_SHIFT 10 ++#define CST4330_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4330_CBUCK_MODE_SHIFT 12 ++#define CST4330_CBUCK_MODE_MASK 0x00003000 ++#define CST4330_CBUCK_POWER_OK 0x00004000 ++#define CST4330_BB_PLL_LOCKED 0x00008000 ++#define SOCDEVRAM_BP_ADDR 0x1E000000 ++#define SOCDEVRAM_ARM_ADDR 0x00800000 ++ ++/* 4330 Chip specific PMU ChipControl register bits */ ++#define PCTL_4330_SERIAL_ENAB (1 << 24) ++ ++/* 4330 Chip specific ChipControl register bits */ ++#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */ ++#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */ ++#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */ ++#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */ ++ ++/* 4334 resources */ ++#define RES4334_LPLDO_PU 0 ++#define RES4334_RESET_PULLDN_DIS 1 ++#define RES4334_PMU_BG_PU 2 ++#define RES4334_HSIC_LDO_PU 3 ++#define RES4334_CBUCK_LPOM_PU 4 ++#define RES4334_CBUCK_PFM_PU 5 ++#define RES4334_CLDO_PU 6 ++#define RES4334_LPLDO2_LVM 7 ++#define RES4334_LNLDO_PU 8 ++#define RES4334_LDO3P3_PU 9 ++#define RES4334_OTP_PU 10 ++#define RES4334_XTAL_PU 11 ++#define RES4334_WL_PWRSW_PU 12 ++#define RES4334_LQ_AVAIL 13 ++#define RES4334_LOGIC_RET 14 ++#define RES4334_MEM_SLEEP 15 ++#define RES4334_MACPHY_RET 16 ++#define RES4334_WL_CORE_READY 17 ++#define RES4334_ILP_REQ 18 ++#define RES4334_ALP_AVAIL 19 ++#define RES4334_MISC_PWRSW_PU 20 ++#define RES4334_SYNTH_PWRSW_PU 21 ++#define RES4334_RX_PWRSW_PU 22 ++#define RES4334_RADIO_PU 23 ++#define RES4334_WL_PMU_PU 24 ++#define RES4334_VCO_LDO_PU 25 ++#define RES4334_AFE_LDO_PU 26 ++#define RES4334_RX_LDO_PU 27 ++#define RES4334_TX_LDO_PU 28 ++#define RES4334_HT_AVAIL 29 ++#define RES4334_MACPHY_CLK_AVAIL 30 ++ ++/* 4334 chip-specific ChipStatus register bits */ ++#define CST4334_CHIPMODE_MASK 7 ++#define CST4334_SDIO_MODE 0x00000000 ++#define CST4334_SPI_MODE 0x00000004 ++#define CST4334_HSIC_MODE 0x00000006 ++#define CST4334_BLUSB_MODE 0x00000007 ++#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE) ++#define CST4334_OTP_PRESENT 0x00000010 ++#define CST4334_LPO_AUTODET_EN 0x00000020 ++#define CST4334_ARMREMAP_0 0x00000040 ++#define CST4334_SPROM_PRESENT 0x00000080 ++#define CST4334_ILPDIV_EN_MASK 0x00000100 ++#define CST4334_ILPDIV_EN_SHIFT 8 ++#define CST4334_LPO_SEL_MASK 0x00000200 ++#define CST4334_LPO_SEL_SHIFT 9 ++#define CST4334_RES_INIT_MODE_MASK 0x00000C00 ++#define CST4334_RES_INIT_MODE_SHIFT 10 ++ ++/* 4334 Chip specific PMU ChipControl register bits */ ++#define PCTL_4334_GPIO3_ENAB (1 << 3) ++ ++/* 4334 Chip control */ ++#define CCTRL4334_HSIC_LDO_PU (1 << 23) ++ ++/* 4324 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++/* 4313 resources */ ++#define RES4313_BB_PU_RSRC 0 ++#define RES4313_ILP_REQ_RSRC 1 ++#define RES4313_XTAL_PU_RSRC 2 ++#define RES4313_ALP_AVAIL_RSRC 3 ++#define RES4313_RADIO_PU_RSRC 4 ++#define RES4313_BG_PU_RSRC 5 ++#define RES4313_VREG1P4_PU_RSRC 6 ++#define RES4313_AFE_PWRSW_RSRC 7 ++#define RES4313_RX_PWRSW_RSRC 8 ++#define RES4313_TX_PWRSW_RSRC 9 ++#define RES4313_BB_PWRSW_RSRC 10 ++#define RES4313_SYNTH_PWRSW_RSRC 11 ++#define RES4313_MISC_PWRSW_RSRC 12 ++#define RES4313_BB_PLL_PWRSW_RSRC 13 ++#define RES4313_HT_AVAIL_RSRC 14 ++#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 ++ ++/* 4313 chip-specific ChipStatus register bits */ ++#define CST4313_SPROM_PRESENT 1 ++#define CST4313_OTP_PRESENT 2 ++#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 ++#define CST4313_SPROM_OTP_SEL_SHIFT 0 ++ ++/* 4313 Chip specific ChipControl register bits */ ++#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ ++ ++/* PMU respources for 4314 */ ++#define RES4314_LPLDO_PU 0 ++#define RES4314_PMU_SLEEP_DIS 1 ++#define RES4314_PMU_BG_PU 2 ++#define RES4314_CBUCK_LPOM_PU 3 ++#define RES4314_CBUCK_PFM_PU 4 ++#define RES4314_CLDO_PU 5 ++#define RES4314_LPLDO2_LVM 6 ++#define RES4314_WL_PMU_PU 7 ++#define RES4314_LNLDO_PU 8 ++#define RES4314_LDO3P3_PU 9 ++#define RES4314_OTP_PU 10 ++#define RES4314_XTAL_PU 11 ++#define RES4314_WL_PWRSW_PU 12 ++#define RES4314_LQ_AVAIL 13 ++#define RES4314_LOGIC_RET 14 ++#define RES4314_MEM_SLEEP 15 ++#define RES4314_MACPHY_RET 16 ++#define RES4314_WL_CORE_READY 17 ++#define RES4314_ILP_REQ 18 ++#define RES4314_ALP_AVAIL 19 ++#define RES4314_MISC_PWRSW_PU 20 ++#define RES4314_SYNTH_PWRSW_PU 21 ++#define RES4314_RX_PWRSW_PU 22 ++#define RES4314_RADIO_PU 23 ++#define RES4314_VCO_LDO_PU 24 ++#define RES4314_AFE_LDO_PU 25 ++#define RES4314_RX_LDO_PU 26 ++#define RES4314_TX_LDO_PU 27 ++#define RES4314_HT_AVAIL 28 ++#define RES4314_MACPHY_CLK_AVAIL 29 ++ ++/* 4314 chip-specific ChipStatus register bits */ ++#define CST4314_OTP_ENABLED 0x00200000 ++ ++/* 43228 resources */ ++#define RES43228_NOT_USED 0 ++#define RES43228_ILP_REQUEST 1 ++#define RES43228_XTAL_PU 2 ++#define RES43228_ALP_AVAIL 3 ++#define RES43228_PLL_EN 4 ++#define RES43228_HT_PHY_AVAIL 5 ++ ++/* 43228 chipstatus reg bits */ ++#define CST43228_ILP_DIV_EN 0x1 ++#define CST43228_OTP_PRESENT 0x2 ++#define CST43228_SERDES_REFCLK_PADSEL 0x4 ++#define CST43228_SDIO_MODE 0x8 ++#define CST43228_SDIO_OTP_PRESENT 0x10 ++#define CST43228_SDIO_RESET 0x20 ++ ++/* 4706 chipstatus reg bits */ ++#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */ ++#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */ ++#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ ++#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */ ++#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */ ++ ++/* 4706 flashstrconfig reg bits */ ++#define FLSTRCF4706_MASK 0x000000ff ++#define FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */ ++#define FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */ ++#define FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ ++#define FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */ ++#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */ ++#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ ++ ++/* 4360 Chip specific ChipControl register bits */ ++#define CCTRL4360_SECI_MODE (1 << 2) ++#define CCTRL4360_BTSWCTRL_MODE (1 << 3) ++#define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) ++#define CCTRL4360_BT_LGCY_MODE (1 << 9) ++#define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) ++ ++/* 4360 PMU resources and chip status bits */ ++#define RES4360_REGULATOR 0 ++#define RES4360_ILP_AVAIL 1 ++#define RES4360_ILP_REQ 2 ++#define RES4360_XTAL_PU 3 ++#define RES4360_ALP_AVAIL 4 ++#define RES4360_BBPLLPWRSW_PU 5 ++#define RES4360_HT_AVAIL 6 ++#define RES4360_OTP_PU 7 ++#define RES4360_USBLDO_PU 8 ++#define RES4360_USBPLL_PWRSW_PU 9 ++#define RES4360_LQ_AVAIL 10 ++ ++#define CST4360_XTAL_40MZ 0x00000001 ++#define CST4360_SFLASH 0x00000002 ++#define CST4360_SPROM_PRESENT 0x00000004 ++#define CST4360_SFLASH_TYPE 0x00000004 ++#define CST4360_OTP_ENABLED 0x00000008 ++#define CST4360_REMAP_ROM 0x00000010 ++#define CST4360_RSRC_INIT_MODE_MASK 0x00000060 ++#define CST4360_RSRC_INIT_MODE_SHIFT 5 ++#define CST4360_ILP_DIVEN 0x00000080 ++#define CST4360_MODE_USB 0x00000100 ++#define CST4360_SPROM_SIZE_MASK 0x00000600 ++#define CST4360_SPROM_SIZE_SHIFT 9 ++#define CST4360_BBPLL_LOCK 0x00000800 ++#define CST4360_AVBBPLL_LOCK 0x00001000 ++#define CST4360_USBBBPLL_LOCK 0x00002000 ++ ++#define CCTL_4360_UART_SEL 2 ++ ++/* 4335 resources */ ++#define RES4335_LPLDO_PO 0 ++#define RES4335_PMU_BG_PU 1 ++#define RES4335_PMU_SLEEP 2 ++#define RES4335_RSVD_3 3 ++#define RES4335_CBUCK_LPOM_PU 4 ++#define RES4335_CBUCK_PFM_PU 5 ++#define RES4335_RSVD_6 6 ++#define RES4335_RSVD_7 7 ++#define RES4335_LNLDO_PU 8 ++#define RES4335_XTALLDO_PU 9 ++#define RES4335_LDO3P3_PU 10 ++#define RES4335_OTP_PU 11 ++#define RES4335_XTAL_PU 12 ++#define RES4335_SR_CLK_START 13 ++#define RES4335_LQ_AVAIL 14 ++#define RES4335_LQ_START 15 ++#define RES4335_RSVD_16 16 ++#define RES4335_WL_CORE_RDY 17 ++#define RES4335_ILP_REQ 18 ++#define RES4335_ALP_AVAIL 19 ++#define RES4335_MINI_PMU 20 ++#define RES4335_RADIO_PU 21 ++#define RES4335_SR_CLK_STABLE 22 ++#define RES4335_SR_SAVE_RESTORE 23 ++#define RES4335_SR_PHY_PWRSW 24 ++#define RES4335_SR_VDDM_PWRSW 25 ++#define RES4335_SR_SUBCORE_PWRSW 26 ++#define RES4335_SR_SLEEP 27 ++#define RES4335_HT_START 28 ++#define RES4335_HT_AVAIL 29 ++#define RES4335_MACPHY_CLKAVAIL 30 ++ ++/* 4335 Chip specific ChipStatus register bits */ ++#define CST4335_SPROM_MASK 0x00000020 ++#define CST4335_SFLASH_MASK 0x00000040 ++#define CST4335_RES_INIT_MODE_SHIFT 7 ++#define CST4335_RES_INIT_MODE_MASK 0x00000180 ++#define CST4335_CHIPMODE_MASK 0xF ++#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */ ++#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */ ++#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) /* USB || USBDA */ ++#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */ ++ ++/* 4335 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++#define CR4_RAM_BASE (0x180000) ++#define PATCHTBL_SIZE (0x800) ++ ++ ++/* 4335 resources--END */ ++ ++/* GCI chipcontrol register indices */ ++#define CC_GCI_CHIPCTRL_00 (0) ++#define CC_GCI_CHIPCTRL_01 (1) ++#define CC_GCI_CHIPCTRL_02 (2) ++#define CC_GCI_CHIPCTRL_03 (3) ++#define CC_GCI_CHIPCTRL_04 (4) ++#define CC_GCI_CHIPCTRL_05 (5) ++#define CC_GCI_CHIPCTRL_06 (6) ++#define CC_GCI_CHIPCTRL_07 (7) ++#define CC_GCI_CHIPCTRL_08 (8) ++ ++#define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) ++ ++/* 4335 pins ++* note: only the values set as default/used are added here. ++*/ ++#define CC4335_PIN_GPIO_00 (0) ++#define CC4335_PIN_GPIO_01 (1) ++#define CC4335_PIN_GPIO_02 (2) ++#define CC4335_PIN_GPIO_03 (3) ++#define CC4335_PIN_GPIO_04 (4) ++#define CC4335_PIN_GPIO_05 (5) ++#define CC4335_PIN_GPIO_06 (6) ++#define CC4335_PIN_GPIO_07 (7) ++#define CC4335_PIN_GPIO_08 (8) ++#define CC4335_PIN_GPIO_09 (9) ++#define CC4335_PIN_GPIO_10 (10) ++#define CC4335_PIN_GPIO_11 (11) ++#define CC4335_PIN_GPIO_12 (12) ++#define CC4335_PIN_GPIO_13 (13) ++#define CC4335_PIN_GPIO_14 (14) ++#define CC4335_PIN_GPIO_15 (15) ++#define CC4335_PIN_SDIO_CLK (16) ++#define CC4335_PIN_SDIO_CMD (17) ++#define CC4335_PIN_SDIO_DATA0 (18) ++#define CC4335_PIN_SDIO_DATA1 (19) ++#define CC4335_PIN_SDIO_DATA2 (20) ++#define CC4335_PIN_SDIO_DATA3 (21) ++#define CC4335_PIN_RF_SW_CTRL_0 (22) ++#define CC4335_PIN_RF_SW_CTRL_1 (23) ++#define CC4335_PIN_RF_SW_CTRL_2 (24) ++#define CC4335_PIN_RF_SW_CTRL_3 (25) ++#define CC4335_PIN_RF_SW_CTRL_4 (26) ++#define CC4335_PIN_RF_SW_CTRL_5 (27) ++#define CC4335_PIN_RF_SW_CTRL_6 (28) ++#define CC4335_PIN_RF_SW_CTRL_7 (29) ++#define CC4335_PIN_RF_SW_CTRL_8 (30) ++#define CC4335_PIN_RF_SW_CTRL_9 (31) ++ ++/* 4335 GCI function sel values ++*/ ++#define CC4335_FNSEL_HWDEF (0) ++#define CC4335_FNSEL_SAMEASPIN (1) ++#define CC4335_FNSEL_GPIO0 (2) ++#define CC4335_FNSEL_GPIO1 (3) ++#define CC4335_FNSEL_GCI0 (4) ++#define CC4335_FNSEL_GCI1 (5) ++#define CC4335_FNSEL_UART (6) ++#define CC4335_FNSEL_SFLASH (7) ++#define CC4335_FNSEL_SPROM (8) ++#define CC4335_FNSEL_MISC0 (9) ++#define CC4335_FNSEL_MISC1 (10) ++#define CC4335_FNSEL_MISC2 (11) ++#define CC4335_FNSEL_IND (12) ++#define CC4335_FNSEL_PDN (13) ++#define CC4335_FNSEL_PUP (14) ++#define CC4335_FNSEL_TRI (15) ++ ++/* find the 4 bit mask given the bit position */ ++#define GCIMASK(pos) (((uint32)0xF) << pos) ++ ++/* get the value which can be used to directly OR with chipcontrol reg */ ++#define GCIPOSVAL(val, pos) ((((uint32)val) << pos) & GCIMASK(pos)) ++ ++/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic ++* for now only UART for bootloader. ++*/ ++#define MUXENAB4335_UART_MASK (0x0000000f) ++ ++ ++/* defines to detect active host interface in use */ ++#define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) & CST4360_MODE_USB) ++ ++/* ++* Maximum delay for the PMU state transition in us. ++* This is an upper bound intended for spinwaits etc. ++*/ ++#define PMU_MAX_TRANSITION_DLY 20000 ++ ++/* PMU resource up transition time in ILP cycles */ ++#define PMURES_UP_TRANSITION 2 ++ ++/* ++* Information from BT to WLAN over eci_inputlo, eci_inputmi & ++* eci_inputhi register. Rev >=21 ++*/ ++/* Fields in eci_inputlo register - [0:31] */ ++#define ECI_INLO_TASKTYPE_MASK 0x0000000f /* [3:0] - 4 bits */ ++#define ECI_INLO_TASKTYPE_SHIFT 0 ++#define ECI_INLO_PKTDUR_MASK 0x000000f0 /* [7:4] - 4 bits */ ++#define ECI_INLO_PKTDUR_SHIFT 4 ++#define ECI_INLO_ROLE_MASK 0x00000100 /* [8] - 1 bits */ ++#define ECI_INLO_ROLE_SHIFT 8 ++#define ECI_INLO_MLP_MASK 0x00000e00 /* [11:9] - 3 bits */ ++#define ECI_INLO_MLP_SHIFT 9 ++#define ECI_INLO_TXPWR_MASK 0x000ff000 /* [19:12] - 8 bits */ ++#define ECI_INLO_TXPWR_SHIFT 12 ++#define ECI_INLO_RSSI_MASK 0x0ff00000 /* [27:20] - 8 bits */ ++#define ECI_INLO_RSSI_SHIFT 20 ++#define ECI_INLO_VAD_MASK 0x10000000 /* [28] - 1 bits */ ++#define ECI_INLO_VAD_SHIFT 28 ++ ++/* ++* Register eci_inputlo bitfield values. ++* - BT packet type information bits [7:0] ++*/ ++/* [3:0] - Task (link) type */ ++#define BT_ACL 0x00 ++#define BT_SCO 0x01 ++#define BT_eSCO 0x02 ++#define BT_A2DP 0x03 ++#define BT_SNIFF 0x04 ++#define BT_PAGE_SCAN 0x05 ++#define BT_INQUIRY_SCAN 0x06 ++#define BT_PAGE 0x07 ++#define BT_INQUIRY 0x08 ++#define BT_MSS 0x09 ++#define BT_PARK 0x0a ++#define BT_RSSISCAN 0x0b ++#define BT_MD_ACL 0x0c ++#define BT_MD_eSCO 0x0d ++#define BT_SCAN_WITH_SCO_LINK 0x0e ++#define BT_SCAN_WITHOUT_SCO_LINK 0x0f ++/* [7:4] = packet duration code */ ++/* [8] - Master / Slave */ ++#define BT_MASTER 0 ++#define BT_SLAVE 1 ++/* [11:9] - multi-level priority */ ++#define BT_LOWEST_PRIO 0x0 ++#define BT_HIGHEST_PRIO 0x3 ++/* [19:12] - BT transmit power */ ++/* [27:20] - BT RSSI */ ++/* [28] - VAD silence */ ++/* [31:29] - Undefined */ ++/* Register eci_inputmi values - [32:63] - none defined */ ++/* [63:32] - Undefined */ ++ ++/* Information from WLAN to BT over eci_output register. */ ++/* Fields in eci_output register - [0:31] */ ++#define ECI48_OUT_MASKMAGIC_HIWORD 0x55550000 ++#define ECI_OUT_CHANNEL_MASK(ccrev) ((ccrev) < 35 ? 0xf : (ECI48_OUT_MASKMAGIC_HIWORD | 0xf000)) ++#define ECI_OUT_CHANNEL_SHIFT(ccrev) ((ccrev) < 35 ? 0 : 12) ++#define ECI_OUT_BW_MASK(ccrev) ((ccrev) < 35 ? 0x70 : (ECI48_OUT_MASKMAGIC_HIWORD | 0xe00)) ++#define ECI_OUT_BW_SHIFT(ccrev) ((ccrev) < 35 ? 4 : 9) ++#define ECI_OUT_ANTENNA_MASK(ccrev) ((ccrev) < 35 ? 0x80 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x100)) ++#define ECI_OUT_ANTENNA_SHIFT(ccrev) ((ccrev) < 35 ? 7 : 8) ++#define ECI_OUT_SIMUL_TXRX_MASK(ccrev) \ ++ ((ccrev) < 35 ? 0x10000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x80)) ++#define ECI_OUT_SIMUL_TXRX_SHIFT(ccrev) ((ccrev) < 35 ? 16 : 7) ++#define ECI_OUT_FM_DISABLE_MASK(ccrev) \ ++ ((ccrev) < 35 ? 0x40000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x40)) ++#define ECI_OUT_FM_DISABLE_SHIFT(ccrev) ((ccrev) < 35 ? 18 : 6) ++ ++/* Indicate control of ECI bits between s/w and dot11mac. ++ * 0 => FW control, 1=> MAC/ucode control ++ ++ * Current assignment (ccrev >= 35): ++ * 0 - TxConf (ucode) ++ * 38 - FM disable (wl) ++ * 39 - Allow sim rx (ucode) ++ * 40 - Num antennas (wl) ++ * 43:41 - WLAN channel exclusion BW (wl) ++ * 47:44 - WLAN channel (wl) ++ * ++ * (ccrev < 35) ++ * 15:0 - wl ++ * 16 - ++ * 18 - FM disable ++ * 30 - wl interrupt ++ * 31 - ucode interrupt ++ * others - unassigned (presumed to be with dot11mac/ucode) ++ */ ++#define ECI_MACCTRL_BITS 0xbffb0000 ++#define ECI_MACCTRLLO_BITS 0x1 ++#define ECI_MACCTRLHI_BITS 0xFF ++ ++ ++/* SECI configuration */ ++#define SECI_MODE_UART 0x0 ++#define SECI_MODE_SECI 0x1 ++#define SECI_MODE_LEGACY_3WIRE_BT 0x2 ++#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3 ++#define SECI_MODE_HALF_SECI 0x4 ++ ++#define SECI_RESET (1 << 0) ++#define SECI_RESET_BAR_UART (1 << 1) ++#define SECI_ENAB_SECI_ECI (1 << 2) ++#define SECI_ENAB_SECIOUT_DIS (1 << 3) ++#define SECI_MODE_MASK 0x7 ++#define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */ ++#define SECI_UPD_SECI (1 << 7) ++ ++#define SECI_SIGNOFF_0 0xDB ++#define SECI_SIGNOFF_1 0 ++ ++/* seci clk_ctl_st bits */ ++#define CLKCTL_STS_SECI_CLK_REQ (1 << 8) ++#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24) ++ ++#define SECI_UART_MSR_CTS_STATE (1 << 0) ++#define SECI_UART_MSR_RTS_STATE (1 << 1) ++#define SECI_UART_SECI_IN_STATE (1 << 2) ++#define SECI_UART_SECI_IN2_STATE (1 << 3) ++ ++/* SECI UART LCR/MCR register bits */ ++#define SECI_UART_LCR_STOP_BITS (1 << 0) /* 0 - 1bit, 1 - 2bits */ ++#define SECI_UART_LCR_PARITY_EN (1 << 1) ++#define SECI_UART_LCR_PARITY (1 << 2) /* 0 - odd, 1 - even */ ++#define SECI_UART_LCR_RX_EN (1 << 3) ++#define SECI_UART_LCR_LBRK_CTRL (1 << 4) /* 1 => SECI_OUT held low */ ++#define SECI_UART_LCR_TXO_EN (1 << 5) ++#define SECI_UART_LCR_RTSO_EN (1 << 6) ++#define SECI_UART_LCR_SLIPMODE_EN (1 << 7) ++#define SECI_UART_LCR_RXCRC_CHK (1 << 8) ++#define SECI_UART_LCR_TXCRC_INV (1 << 9) ++#define SECI_UART_LCR_TXCRC_LSBF (1 << 10) ++#define SECI_UART_LCR_TXCRC_EN (1 << 11) ++ ++#define SECI_UART_MCR_TX_EN (1 << 0) ++#define SECI_UART_MCR_PRTS (1 << 1) ++#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2) ++#define SECI_UART_MCR_HIGHRATE_EN (1 << 3) ++#define SECI_UART_MCR_LOOPBK_EN (1 << 4) ++#define SECI_UART_MCR_AUTO_RTS (1 << 5) ++#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6) ++#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7) ++#define SECI_UART_MCR_XONOFF_RPT (1 << 9) ++ ++/* WLAN channel numbers - used from wifi.h */ ++ ++/* WLAN BW */ ++#define ECI_BW_20 0x0 ++#define ECI_BW_25 0x1 ++#define ECI_BW_30 0x2 ++#define ECI_BW_35 0x3 ++#define ECI_BW_40 0x4 ++#define ECI_BW_45 0x5 ++#define ECI_BW_50 0x6 ++#define ECI_BW_ALL 0x7 ++ ++/* WLAN - number of antenna */ ++#define WLAN_NUM_ANT1 TXANT_0 ++#define WLAN_NUM_ANT2 TXANT_1 ++ ++#endif /* _SBCHIPC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbconfig.h b/drivers/bcmdrivers/gmac/src/include/sbconfig.h +new file mode 100755 +index 0000000..cd13ce6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch new file mode 100644 index 00000000..8010ca8b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch @@ -0,0 +1,282 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbconfig.h +@@ -0,0 +1,276 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SiliconBackplane hardware register definitions. ++ * ++ * $Id: sbconfig.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _SBCONFIG_H ++#define _SBCONFIG_H ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif ++ ++/* enumeration in SB is based on the premise that cores are contiguos in the ++ * enumeration space. ++ */ ++#define SB_BUS_SIZE 0x10000 /* Each bus gets 64Kbytes for cores */ ++#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) ++#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /* Max cores per bus */ ++ ++/* ++ * Sonics Configuration Space Registers. ++ */ ++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ ++ ++#define SBIPSFLAG 0x08 ++#define SBTPSFLAG 0x18 ++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ ++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ ++#define SBADMATCH3 0x60 ++#define SBADMATCH2 0x68 ++#define SBADMATCH1 0x70 ++#define SBIMSTATE 0x90 ++#define SBINTVEC 0x94 ++#define SBTMSTATELOW 0x98 ++#define SBTMSTATEHIGH 0x9c ++#define SBBWA0 0xa0 ++#define SBIMCONFIGLOW 0xa8 ++#define SBIMCONFIGHIGH 0xac ++#define SBADMATCH0 0xb0 ++#define SBTMCONFIGLOW 0xb8 ++#define SBTMCONFIGHIGH 0xbc ++#define SBBCONFIG 0xc0 ++#define SBBSTATE 0xc8 ++#define SBACTCNFG 0xd8 ++#define SBFLAGST 0xe8 ++#define SBIDLOW 0xf8 ++#define SBIDHIGH 0xfc ++ ++/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have ++ * a few registers *below* that line. I think it would be very confusing to try ++ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here, ++ */ ++ ++#define SBIMERRLOGA 0xea8 ++#define SBIMERRLOG 0xeb0 ++#define SBTMPORTCONNID0 0xed8 ++#define SBTMPORTLOCK0 0xef8 ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _sbconfig { ++ uint32 PAD[2]; ++ uint32 sbipsflag; /* initiator port ocp slave flag */ ++ uint32 PAD[3]; ++ uint32 sbtpsflag; /* target port ocp slave flag */ ++ uint32 PAD[11]; ++ uint32 sbtmerrloga; /* (sonics >= 2.3) */ ++ uint32 PAD; ++ uint32 sbtmerrlog; /* (sonics >= 2.3) */ ++ uint32 PAD[3]; ++ uint32 sbadmatch3; /* address match3 */ ++ uint32 PAD; ++ uint32 sbadmatch2; /* address match2 */ ++ uint32 PAD; ++ uint32 sbadmatch1; /* address match1 */ ++ uint32 PAD[7]; ++ uint32 sbimstate; /* initiator agent state */ ++ uint32 sbintvec; /* interrupt mask */ ++ uint32 sbtmstatelow; /* target state */ ++ uint32 sbtmstatehigh; /* target state */ ++ uint32 sbbwa0; /* bandwidth allocation table0 */ ++ uint32 PAD; ++ uint32 sbimconfiglow; /* initiator configuration */ ++ uint32 sbimconfighigh; /* initiator configuration */ ++ uint32 sbadmatch0; /* address match0 */ ++ uint32 PAD; ++ uint32 sbtmconfiglow; /* target configuration */ ++ uint32 sbtmconfighigh; /* target configuration */ ++ uint32 sbbconfig; /* broadcast configuration */ ++ uint32 PAD; ++ uint32 sbbstate; /* broadcast state */ ++ uint32 PAD[3]; ++ uint32 sbactcnfg; /* activate configuration */ ++ uint32 PAD[3]; ++ uint32 sbflagst; /* current sbflags */ ++ uint32 PAD[3]; ++ uint32 sbidlow; /* identification */ ++ uint32 sbidhigh; /* identification */ ++} sbconfig_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* sbipsflag */ ++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ ++#define SBIPS_INT1_SHIFT 0 ++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ ++#define SBIPS_INT2_SHIFT 8 ++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ ++#define SBIPS_INT3_SHIFT 16 ++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ ++#define SBIPS_INT4_SHIFT 24 ++ ++/* sbtpsflag */ ++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ ++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ ++ ++/* sbtmerrlog */ ++#define SBTMEL_CM 0x00000007 /* command */ ++#define SBTMEL_CI 0x0000ff00 /* connection id */ ++#define SBTMEL_EC 0x0f000000 /* error code */ ++#define SBTMEL_ME 0x80000000 /* multiple error */ ++ ++/* sbimstate */ ++#define SBIM_PC 0xf /* pipecount */ ++#define SBIM_AP_MASK 0x30 /* arbitration policy */ ++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ ++#define SBIM_AP_TS 0x10 /* use timesliaces only */ ++#define SBIM_AP_TK 0x20 /* use token only */ ++#define SBIM_AP_RSV 0x30 /* reserved */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++ ++/* sbtmstatelow */ ++#define SBTML_RESET 0x0001 /* reset */ ++#define SBTML_REJ_MASK 0x0006 /* reject field */ ++#define SBTML_REJ 0x0002 /* reject */ ++#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ ++ ++#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ ++ ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x0001 /* serror */ ++#define SBTMH_INT 0x0002 /* interrupt */ ++#define SBTMH_BUSY 0x0004 /* busy */ ++#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ ++ ++#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ ++ ++/* sbbwa0 */ ++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ ++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ ++#define SBBWA_TAB1_SHIFT 16 ++ ++/* sbimconfiglow */ ++#define SBIMCL_STO_MASK 0x7 /* service timeout */ ++#define SBIMCL_RTO_MASK 0x70 /* request timeout */ ++#define SBIMCL_RTO_SHIFT 4 ++#define SBIMCL_CID_MASK 0xff0000 /* connection id */ ++#define SBIMCL_CID_SHIFT 16 ++ ++/* sbimconfighigh */ ++#define SBIMCH_IEM_MASK 0xc /* inband error mode */ ++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ ++#define SBIMCH_TEM_SHIFT 4 ++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ ++#define SBIMCH_BEM_SHIFT 6 ++ ++/* sbadmatch0 */ ++#define SBAM_TYPE_MASK 0x3 /* address type */ ++#define SBAM_AD64 0x4 /* reserved */ ++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ ++#define SBAM_ADINT0_SHIFT 3 ++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ ++#define SBAM_ADINT1_SHIFT 3 ++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ ++#define SBAM_ADINT2_SHIFT 3 ++#define SBAM_ADEN 0x400 /* enable */ ++#define SBAM_ADNEG 0x800 /* negative decode */ ++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ ++#define SBAM_BASE0_SHIFT 8 ++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ ++#define SBAM_BASE1_SHIFT 12 ++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ ++#define SBAM_BASE2_SHIFT 16 ++ ++/* sbtmconfiglow */ ++#define SBTMCL_CD_MASK 0xff /* clock divide */ ++#define SBTMCL_CO_MASK 0xf800 /* clock offset */ ++#define SBTMCL_CO_SHIFT 11 ++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ ++#define SBTMCL_IF_SHIFT 18 ++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ ++#define SBTMCL_IM_SHIFT 24 ++ ++/* sbtmconfighigh */ ++#define SBTMCH_BM_MASK 0x3 /* busy mode */ ++#define SBTMCH_RM_MASK 0x3 /* retry mode */ ++#define SBTMCH_RM_SHIFT 2 ++#define SBTMCH_SM_MASK 0x30 /* stop mode */ ++#define SBTMCH_SM_SHIFT 4 ++#define SBTMCH_EM_MASK 0x300 /* sb error mode */ ++#define SBTMCH_EM_SHIFT 8 ++#define SBTMCH_IM_MASK 0xc00 /* int mode */ ++#define SBTMCH_IM_SHIFT 10 ++ ++/* sbbconfig */ ++#define SBBC_LAT_MASK 0x3 /* sb latency */ ++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ ++#define SBBC_MAX0_SHIFT 16 ++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ ++#define SBBC_MAX1_SHIFT 20 ++ ++/* sbbstate */ ++#define SBBS_SRD 0x1 /* st reg disable */ ++#define SBBS_HRD 0x2 /* hold reg disable */ ++ ++/* sbidlow */ ++#define SBIDL_CS_MASK 0x3 /* config space */ ++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ ++#define SBIDL_AR_SHIFT 3 ++#define SBIDL_SYNCH 0x40 /* sync */ ++#define SBIDL_INIT 0x80 /* initiator */ ++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ ++#define SBIDL_MINLAT_SHIFT 8 ++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ ++#define SBIDL_MAXLAT_SHIFT 12 ++#define SBIDL_FIRST 0x10000 /* this initiator is first */ ++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ ++#define SBIDL_CW_SHIFT 18 ++#define SBIDL_TP_MASK 0xf00000 /* target ports */ ++#define SBIDL_TP_SHIFT 20 ++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ ++#define SBIDL_IP_SHIFT 24 ++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ ++#define SBIDL_RV_SHIFT 28 ++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ ++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ ++ ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 ++ ++#define SB_COMMIT 0xfd8 /* update buffered registers value */ ++ ++/* vendor codes */ ++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ ++ ++#endif /* _SBCONFIG_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbhndarm.h b/drivers/bcmdrivers/gmac/src/include/sbhndarm.h +new file mode 100755 +index 0000000..f925da3 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch new file mode 100644 index 00000000..cecf2c96 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch @@ -0,0 +1,299 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbhndarm.h +@@ -0,0 +1,293 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SiliconBackplane ARM definitions ++ * ++ * $Id: sbhndarm.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _sbhndarm_h_ ++#define _sbhndarm_h_ ++ ++#include ++#include ++ ++/* register offsets */ ++#define ARM7_CORECTL 0 ++ ++/* bits in corecontrol */ ++#define ACC_FORCED_RST 0x1 ++#define ACC_SERRINT 0x2 ++#define ACC_NOTSLEEPINGCLKREQ_SHIFT 24 ++ ++/* arm resetlog */ ++#define SBRESETLOG 0x1 ++#define SERRORLOG 0x2 ++ ++/* arm core-specific control flags */ ++#define SICF_REMAP_MSK 0x001c ++#define SICF_REMAP_NONE 0 ++#define SICF_REMAP_ROM 0x0004 ++#define SIFC_REMAP_FLASH 0x0008 ++ ++/* misc core-specific defines */ ++#if defined(__ARM_ARCH_4T__) ++/* arm7tdmi-s */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARM7S_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARM7S_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 SI_ARM7S_SRAM2 /* RAM backplane address when remap is 1 or 2 */ ++#elif defined(__ARM_ARCH_7M__) ++/* cortex-m3 */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCM3_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARMCM3_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 SI_ARMCM3_SRAM2 /* RAM backplane address when remap is 1 or 2 */ ++/* core registers offsets */ ++#define ARMCM3_CYCLECNT 0x90 /* Cortex-M3 core registers offsets */ ++#define ARMCM3_INTTIMER 0x94 ++#define ARMCM3_INTMASK 0x98 ++#define ARMCM3_INTSTATUS 0x9c ++/* interrupt/exception */ ++#define ARMCM3_NUMINTS 16 /* # of external interrupts */ ++#define ARMCM3_INTALL ((1 << ARMCM3_NUMINTS) - 1) /* Interrupt mask */ ++#define ARMCM3_FAULTMASK 0x40000000 /* Master fault enable/disable */ ++#define ARMCM3_PRIMASK 0x80000000 /* Master interrupt enable/disable */ ++#define ARMCM3_SHARED_INT 0 /* Interrupt shared by multiple cores */ ++#define ARMCM3_INT(i) (1 << (i)) /* Individual interrupt enable/disable */ ++/* compatible with arm7tdmi-s */ ++#define PS_I ARMCM3_PRIMASK ++#define PS_F ARMCM3_FAULTMASK ++/* intmask/intstatus bits */ ++#define ARMCM3_INTMASK_TIMER 0x1 ++#define ARMCM3_INTMASK_SYSRESET 0x4 ++#define ARMCM3_INTMASK_LOCKUP 0x8 ++ ++/* ++ * Overlay Support in Rev 5 ++ */ ++#define ARMCM3_OVL_VALID_SHIFT 0 ++#define ARMCM3_OVL_VALID 1 ++#define ARMCM3_OVL_SZ_SHIFT 1 ++#define ARMCM3_OVL_SZ_MASK 0x0000000e ++#define ARMCM3_OVL_SZ_512B 0 /* 512B */ ++#define ARMCM3_OVL_SZ_1KB 1 /* 1KB */ ++#define ARMCM3_OVL_SZ_2KB 2 /* 2KB */ ++#define ARMCM3_OVL_SZ_4KB 3 /* 4KB */ ++#define ARMCM3_OVL_SZ_8KB 4 /* 8KB */ ++#define ARMCM3_OVL_SZ_16KB 5 /* 16KB */ ++#define ARMCM3_OVL_SZ_32KB 6 /* 32KB */ ++#define ARMCM3_OVL_SZ_64KB 7 /* 64KB */ ++#define ARMCM3_OVL_ADDR_SHIFT 9 ++#define ARMCM3_OVL_ADDR_MASK 0x003FFE00 ++#define ARMCM3_OVL_MAX 16 ++ ++#elif defined(__ARM_ARCH_7R__) ++/* cortex-r4 */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCR4_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARMCR4_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 0x0 /* In the cr4 the RAM is just not available ++ * when remap is 1 ++ */ ++ ++/* core registers offsets */ ++#define ARMCR4_CORECTL 0 ++#define ARMCR4_CORECAP 4 ++#define ARMCR4_COREST 8 ++ ++#define ARMCR4_FIQRSTATUS 0x10 ++#define ARMCR4_FIQMASK 0x14 ++#define ARMCR4_IRQMASK 0x18 ++ ++#define ARMCR4_INTSTATUS 0x20 ++#define ARMCR4_INTMASK 0x24 ++#define ARMCR4_CYCLECNT 0x28 ++#define ARMCR4_INTTIMER 0x2c ++ ++#define ARMCR4_GPIOSEL 0x30 ++#define ARMCR4_GPIOEN 0x34 ++ ++#define ARMCR4_BANKIDX 0x40 ++#define ARMCR4_BANKINFO 0x44 ++#define ARMCR4_BANKSTBY 0x48 ++#define ARMCR4_BANKPDA 0x4c ++ ++#define ARMCR4_TCAMPATCHCTRL 0x68 ++#define ARMCR4_TCAMPATCHTBLBASEADDR 0x6C ++#define ARMCR4_TCAMCMDREG 0x70 ++#define ARMCR4_TCAMDATAREG 0x74 ++#define ARMCR4_TCAMBANKXMASKREG 0x78 ++ ++#define ARMCR4_ROMNB_MASK 0xf00 ++#define ARMCR4_ROMNB_SHIFT 8 ++#define ARMCR4_TCBBNB_MASK 0xf0 ++#define ARMCR4_TCBBNB_SHIFT 4 ++#define ARMCR4_TCBANB_MASK 0xf ++#define ARMCR4_TCBANB_SHIFT 0 ++ ++#define ARMCR4_MT_MASK 0x300 ++#define ARMCR4_MT_SHIFT 8 ++#define ARMCR4_MT_ROM 0x100 ++#define ARMCR4_MT_RAM 0 ++ ++#define ARMCR4_BSZ_MASK 0x3f ++#define ARMCR4_BSZ_MULT 8192 ++ ++#define ARMCR4_TCAM_ENABLE (1 << 31) ++#define ARMCR4_TCAM_CLKENAB (1 << 30) ++#define ARMCR4_TCAM_PATCHCNT_MASK 0xf ++ ++#define ARMCR4_TCAM_CMD_DONE (1 << 31) ++#define ARMCR4_TCAM_MATCH (1 << 24) ++#define ARMCR4_TCAM_OPCODE_MASK (3 << 16) ++#define ARMCR4_TCAM_OPCODE_SHIFT 16 ++#define ARMCR4_TCAM_ADDR_MASK 0xffff ++#define ARMCR4_TCAM_NONE (0 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_READ (1 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_WRITE (2 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_COMPARE (3 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_CMD_DONE_DLY 1000 ++ ++#define ARMCR4_DATA_MASK (~0x7) ++#define ARMCR4_DATA_VALID (1 << 0) ++ ++ ++/* arm core-specific conrol flags */ ++#define SICF_CPUHALT 0x0020 ++#define SICF_UPDATEFW 0x0040 ++ ++/* arm core-specific status flags */ ++#define SISF_SDRENABLE 0x0001 ++#define SISF_TCMPROT 0x0002 ++ ++#define CHIP_SDRENABLE(sih) (sih->boardflags2 & BFL2_SDR_EN) ++#define CHIP_TCMPROTENAB(sih) (si_arm_sflags(sih) & SISF_TCMPROT) ++ ++#elif defined(__ARM_ARCH_7A__) ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCA9_CORE_ID /* arm coreid */ ++ ++#else /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ ++#error Unrecognized ARM Architecture ++#endif /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++#if defined(__ARM_ARCH_4T__) ++/* arm7tdmi-s */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0 */ ++ uint32 sleepcontrol; /* 4 */ ++ uint32 PAD; ++ uint32 biststatus; /* 0xc */ ++ uint32 firqstatus; /* 0x10 */ ++ uint32 fiqmask; /* 0x14 */ ++ uint32 irqmask; /* 0x18 */ ++ uint32 PAD; ++ uint32 resetlog; /* 0x20 */ ++ uint32 gpioselect; /* 0x24 */ ++ uint32 gpioenable; /* 0x28 */ ++ uint32 PAD; ++ uint32 bpaddrlo; /* 0x30 */ ++ uint32 bpaddrhi; /* 0x34 */ ++ uint32 bpdata; /* 0x38 */ ++ uint32 bpindaccess; /* 0x3c */ ++ uint32 PAD[104]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; /* 0x1e4 */ ++} armregs_t; ++#define ARMREG(regs, reg) (&((armregs_t *)regs)->reg) ++#endif /* __ARM_ARCH_4T__ */ ++ ++#if defined(__ARM_ARCH_7M__) ++/* cortex-m3 */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0x0 */ ++ uint32 corestatus; /* 0x4 */ ++ uint32 PAD[1]; ++ uint32 biststatus; /* 0xc */ ++ uint32 nmiisrst; /* 0x10 */ ++ uint32 nmimask; /* 0x14 */ ++ uint32 isrmask; /* 0x18 */ ++ uint32 PAD[1]; ++ uint32 resetlog; /* 0x20 */ ++ uint32 gpioselect; /* 0x24 */ ++ uint32 gpioenable; /* 0x28 */ ++ uint32 PAD[1]; ++ uint32 bpaddrlo; /* 0x30 */ ++ uint32 bpaddrhi; /* 0x34 */ ++ uint32 bpdata; /* 0x38 */ ++ uint32 bpindaccess; /* 0x3c */ ++ uint32 ovlidx; /* 0x40 */ ++ uint32 ovlmatch; /* 0x44 */ ++ uint32 ovladdr; /* 0x48 */ ++ uint32 PAD[13]; ++ uint32 bwalloc; /* 0x80 */ ++ uint32 PAD[3]; ++ uint32 cyclecnt; /* 0x90 */ ++ uint32 inttimer; /* 0x94 */ ++ uint32 intmask; /* 0x98 */ ++ uint32 intstatus; /* 0x9c */ ++ uint32 PAD[80]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++} cm3regs_t; ++#define ARMREG(regs, reg) (&((cm3regs_t *)regs)->reg) ++#endif /* __ARM_ARCH_7M__ */ ++ ++#if defined(__ARM_ARCH_7R__) ++/* cortex-R4 */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0x0 */ ++ uint32 corecapabilities; /* 0x4 */ ++ uint32 corestatus; /* 0x8 */ ++ uint32 biststatus; /* 0xc */ ++ uint32 nmiisrst; /* 0x10 */ ++ uint32 nmimask; /* 0x14 */ ++ uint32 isrmask; /* 0x18 */ ++ uint32 PAD[1]; ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; /* 0x24 */ ++ uint32 cyclecnt; /* 0x28 */ ++ uint32 inttimer; /* 0x2c */ ++ uint32 gpioselect; /* 0x30 */ ++ uint32 gpioenable; /* 0x34 */ ++ uint32 PAD[2]; ++ uint32 bankidx; /* 0x40 */ ++ uint32 bankinfo; /* 0x44 */ ++ uint32 bankstbyctl; /* 0x48 */ ++ uint32 bankpda; /* 0x4c */ ++ uint32 PAD[6]; ++ uint32 tcampatchctrl; /* 0x68 */ ++ uint32 tcampatchtblbaseaddr; /* 0x6c */ ++ uint32 tcamcmdreg; /* 0x70 */ ++ uint32 tcamdatareg; /* 0x74 */ ++ uint32 tcambankxmaskreg; /* 0x78 */ ++ uint32 PAD[89]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++} cr4regs_t; ++#define ARMREG(regs, reg) (&((cr4regs_t *)regs)->reg) ++#endif /* __ARM_ARCH_7R__ */ ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#endif /* _sbhndarm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbhnddma.h b/drivers/bcmdrivers/gmac/src/include/sbhnddma.h +new file mode 100755 +index 0000000..3003687 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch new file mode 100644 index 00000000..e49d6ea2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch @@ -0,0 +1,409 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbhnddma.h +@@ -0,0 +1,403 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: sbhnddma.h 321146 2012-03-14 08:27:23Z $ ++ */ ++ ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ ++ ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++ ++ ++/* 32 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 addr; /* descriptor ring base address (4K aligned) */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 status; /* current active descriptor, et al */ ++} dma32regs_t; ++ ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma32diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl; /* misc control bits & bufcount */ ++ uint32 addr; /* data buffer address */ ++} dma32dd_t; ++ ++/* ++ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. ++ */ ++#define D32RINGALIGN_BITS 12 ++#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) ++#define D32RINGALIGN (1 << D32RINGALIGN_BITS) ++ ++#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) ++ ++/* transmit channel control */ ++#define XC_XE ((uint32)1 << 0) /* transmit enable */ ++#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ ++#define XC_LE ((uint32)1 << 2) /* loopback enable */ ++#define XC_FL ((uint32)1 << 4) /* flush request */ ++#define XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define XC_MR_SHIFT 6 ++#define XC_PD ((uint32)1 << 11) /* parity check disable */ ++#define XC_AE ((uint32)3 << 16) /* address extension bits */ ++#define XC_AE_SHIFT 16 ++#define XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define XC_BL_SHIFT 18 ++#define XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define XC_PC_SHIFT 21 ++#define XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define XC_PT_SHIFT 24 ++ ++/* Multiple outstanding reads */ ++#define DMA_MR_1 0 ++#define DMA_MR_2 1 ++/* 2, 3: reserved */ ++ ++/* DMA Burst Length in bytes */ ++#define DMA_BL_16 0 ++#define DMA_BL_32 1 ++#define DMA_BL_64 2 ++#define DMA_BL_128 3 ++#define DMA_BL_256 4 ++#define DMA_BL_512 5 ++#define DMA_BL_1024 6 ++ ++/* Prefetch control */ ++#define DMA_PC_0 0 ++#define DMA_PC_4 1 ++#define DMA_PC_8 2 ++#define DMA_PC_16 3 ++/* others: reserved */ ++ ++/* Prefetch threshold */ ++#define DMA_PT_1 0 ++#define DMA_PT_2 1 ++#define DMA_PT_4 2 ++#define DMA_PT_8 3 ++ ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define XS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define XS_XS_MASK 0xf000 /* transmit state */ ++#define XS_XS_SHIFT 12 ++#define XS_XS_DISABLED 0x0000 /* disabled */ ++#define XS_XS_ACTIVE 0x1000 /* active */ ++#define XS_XS_IDLE 0x2000 /* idle wait */ ++#define XS_XS_STOPPED 0x3000 /* stopped */ ++#define XS_XS_SUSP 0x4000 /* suspend pending */ ++#define XS_XE_MASK 0xf0000 /* transmit errors */ ++#define XS_XE_SHIFT 16 ++#define XS_XE_NOERR 0x00000 /* no error */ ++#define XS_XE_DPE 0x10000 /* descriptor protocol error */ ++#define XS_XE_DFU 0x20000 /* data fifo underrun */ ++#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ ++#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ ++#define XS_AD_MASK 0xfff00000 /* active descriptor */ ++#define XS_AD_SHIFT 20 ++ ++/* receive channel control */ ++#define RC_RE ((uint32)1 << 0) /* receive enable */ ++#define RC_RO_MASK 0xfe /* receive frame offset */ ++#define RC_RO_SHIFT 1 ++#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ ++#define RC_SH ((uint32)1 << 9) /* separate rx header descriptor enable */ ++#define RC_OC ((uint32)1 << 10) /* overflow continue */ ++#define RC_PD ((uint32)1 << 11) /* parity check disable */ ++#define RC_AE ((uint32)3 << 16) /* address extension bits */ ++#define RC_AE_SHIFT 16 ++#define RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define RC_BL_SHIFT 18 ++#define RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define RC_PC_SHIFT 21 ++#define RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define RC_PT_SHIFT 24 ++ ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define RS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define RS_RS_MASK 0xf000 /* receive state */ ++#define RS_RS_SHIFT 12 ++#define RS_RS_DISABLED 0x0000 /* disabled */ ++#define RS_RS_ACTIVE 0x1000 /* active */ ++#define RS_RS_IDLE 0x2000 /* idle wait */ ++#define RS_RS_STOPPED 0x3000 /* reserved */ ++#define RS_RE_MASK 0xf0000 /* receive errors */ ++#define RS_RE_SHIFT 16 ++#define RS_RE_NOERR 0x00000 /* no error */ ++#define RS_RE_DPE 0x10000 /* descriptor protocol error */ ++#define RS_RE_DFO 0x20000 /* data fifo overflow */ ++#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ ++#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ ++#define RS_AD_MASK 0xfff00000 /* active descriptor */ ++#define RS_AD_SHIFT 20 ++ ++/* fifoaddr */ ++#define FA_OFF_MASK 0xffff /* offset */ ++#define FA_SEL_MASK 0xf0000 /* select */ ++#define FA_SEL_SHIFT 16 ++#define FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define FA_SEL_RDD 0x40000 /* receive dma data */ ++#define FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags */ ++#define CTRL_BC_MASK 0x00001fff /* buffer byte count, real data len must <= 4KB */ ++#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ ++#define CTRL_AE_SHIFT 16 ++#define CTRL_PARITY ((uint32)3 << 18) /* parity bit */ ++#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ ++#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ ++ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ ++ uint32 status0; /* current descriptor, xmt state */ ++ uint32 status1; /* active descriptor, xmt error */ ++} dma64regs_t; ++ ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma64diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl1; /* misc control bits */ ++ uint32 ctrl2; /* buffer count and address extension */ ++ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++} dma64dd_t; ++ ++/* ++ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. ++ */ ++#define D64RINGALIGN_BITS 13 ++#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) ++#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS) ++ ++#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) ++ ++/* for cores with large descriptor ring support, descriptor ring size can be up to 4096 */ ++#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t)) ++ ++/* for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross ++ * 64K boundary ++ */ ++#define D64RINGBOUNDARY_LARGE (1 << 16) ++ ++/* ++ * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11. ++ * When this field contains the value N, the burst length is 2**(N + 4) bytes. ++ */ ++#define D64_DEF_USBBURSTLEN 2 ++#define D64_DEF_SDIOBURSTLEN 1 ++ ++ ++#ifndef D64_USBBURSTLEN ++#define D64_USBBURSTLEN DMA_BL_64 ++#endif ++#ifndef D64_SDIOBURSTLEN ++#define D64_SDIOBURSTLEN DMA_BL_32 ++#endif ++ ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define D64_XC_MR_SHIFT 6 ++#define D64_XC_PD 0x00000800 /* parity check disable */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 ++#define D64_XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_XC_BL_SHIFT 18 ++#define D64_XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_XC_PC_SHIFT 21 ++#define D64_XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_XC_PT_SHIFT 24 ++ ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ ++/* receive channel control */ ++#define D64_RC_RE 0x00000001 /* receive enable */ ++#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ ++#define D64_RC_RO_SHIFT 1 ++#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ ++#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ ++#define D64_RC_OC 0x00000400 /* overflow continue */ ++#define D64_RC_PD 0x00000800 /* parity check disable */ ++#define D64_RC_GE 0x00004000 /* Glom enable */ ++#define D64_RC_AE 0x00030000 /* address extension bits */ ++#define D64_RC_AE_SHIFT 16 ++#define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_RC_BL_SHIFT 18 ++#define D64_RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_RC_PC_SHIFT 21 ++#define D64_RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_RC_PT_SHIFT 24 ++ ++/* flags for dma controller */ ++#define DMA_CTRL_PEN (1 << 0) /* partity enable */ ++#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */ ++#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */ ++#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */ ++#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4) ++#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /* DMA avoidance WAR for 4331 */ ++#define DMA_CTRL_RXSINGLE (1 << 6) /* always single buffer */ ++ ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++ ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags 1 */ ++#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ ++#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* descriptor control flags 2 */ ++#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */ ++#define D64_CTRL2_AE 0x00030000 /* address extension bits */ ++#define D64_CTRL2_AE_SHIFT 16 ++#define D64_CTRL2_PARITY 0x00040000 /* parity bit */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 ++ ++#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ ++#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ ++#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1, d11corerev >= 22 */ ++#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ ++ ++/* receive frame status */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++} dma_rxh_t; ++ ++#endif /* _sbhnddma_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbsocram.h b/drivers/bcmdrivers/gmac/src/include/sbsocram.h +new file mode 100755 +index 0000000..1afd2e3 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch new file mode 100644 index 00000000..725e16a0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch @@ -0,0 +1,199 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbsocram.h +@@ -0,0 +1,193 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM47XX Sonics SiliconBackplane embedded ram core ++ * ++ * $Id: sbsocram.h 271781 2011-07-13 20:00:06Z $ ++ */ ++ ++#ifndef _SBSOCRAM_H ++#define _SBSOCRAM_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* Memcsocram core registers */ ++typedef volatile struct sbsocramregs { ++ uint32 coreinfo; ++ uint32 bwalloc; ++ uint32 extracoreinfo; ++ uint32 biststat; ++ uint32 bankidx; ++ uint32 standbyctrl; ++ ++ uint32 errlogstatus; /* rev 6 */ ++ uint32 errlogaddr; /* rev 6 */ ++ /* used for patching rev 3 & 5 */ ++ uint32 cambankidx; ++ uint32 cambankstandbyctrl; ++ uint32 cambankpatchctrl; ++ uint32 cambankpatchtblbaseaddr; ++ uint32 cambankcmdreg; ++ uint32 cambankdatareg; ++ uint32 cambankmaskreg; ++ uint32 PAD[1]; ++ uint32 bankinfo; /* corev 8 */ ++ uint32 PAD[15]; ++ uint32 extmemconfig; ++ uint32 extmemparitycsr; ++ uint32 extmemparityerrdata; ++ uint32 extmemparityerrcnt; ++ uint32 extmemwrctrlandsize; ++ uint32 PAD[84]; ++ uint32 workaround; ++ uint32 pwrctl; /* corerev >= 2 */ ++ uint32 PAD[133]; ++ uint32 sr_control; /* corerev >= 15 */ ++ uint32 sr_status; /* corerev >= 15 */ ++ uint32 sr_address; /* corerev >= 15 */ ++ uint32 sr_data; /* corerev >= 15 */ ++} sbsocramregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Register offsets */ ++#define SR_COREINFO 0x00 ++#define SR_BWALLOC 0x04 ++#define SR_BISTSTAT 0x0c ++#define SR_BANKINDEX 0x10 ++#define SR_BANKSTBYCTL 0x14 ++#define SR_PWRCTL 0x1e8 ++ ++/* Coreinfo register */ ++#define SRCI_PT_MASK 0x00070000 /* corerev >= 6; port type[18:16] */ ++#define SRCI_PT_SHIFT 16 ++/* port types : SRCI_PT__ */ ++#define SRCI_PT_OCP_OCP 0 ++#define SRCI_PT_AXI_OCP 1 ++#define SRCI_PT_ARM7AHB_OCP 2 ++#define SRCI_PT_CM3AHB_OCP 3 ++#define SRCI_PT_AXI_AXI 4 ++#define SRCI_PT_AHB_AXI 5 ++/* corerev >= 3 */ ++#define SRCI_LSS_MASK 0x00f00000 ++#define SRCI_LSS_SHIFT 20 ++#define SRCI_LRS_MASK 0x0f000000 ++#define SRCI_LRS_SHIFT 24 ++ ++/* In corerev 0, the memory size is 2 to the power of the ++ * base plus 16 plus to the contents of the memsize field plus 1. ++ */ ++#define SRCI_MS0_MASK 0xf ++#define SR_MS0_BASE 16 ++ ++/* ++ * In corerev 1 the bank size is 2 ^ the bank size field plus 14, ++ * the memory size is number of banks times bank size. ++ * The same applies to rom size. ++ */ ++#define SRCI_ROMNB_MASK 0xf000 ++#define SRCI_ROMNB_SHIFT 12 ++#define SRCI_ROMBSZ_MASK 0xf00 ++#define SRCI_ROMBSZ_SHIFT 8 ++#define SRCI_SRNB_MASK 0xf0 ++#define SRCI_SRNB_SHIFT 4 ++#define SRCI_SRBSZ_MASK 0xf ++#define SRCI_SRBSZ_SHIFT 0 ++ ++#define SR_BSZ_BASE 14 ++ ++/* Standby control register */ ++#define SRSC_SBYOVR_MASK 0x80000000 ++#define SRSC_SBYOVR_SHIFT 31 ++#define SRSC_SBYOVRVAL_MASK 0x60000000 ++#define SRSC_SBYOVRVAL_SHIFT 29 ++#define SRSC_SBYEN_MASK 0x01000000 /* rev >= 3 */ ++#define SRSC_SBYEN_SHIFT 24 ++ ++/* Power control register */ ++#define SRPC_PMU_STBYDIS_MASK 0x00000010 /* rev >= 3 */ ++#define SRPC_PMU_STBYDIS_SHIFT 4 ++#define SRPC_STBYOVRVAL_MASK 0x00000008 ++#define SRPC_STBYOVRVAL_SHIFT 3 ++#define SRPC_STBYOVR_MASK 0x00000007 ++#define SRPC_STBYOVR_SHIFT 0 ++ ++/* Extra core capability register */ ++#define SRECC_NUM_BANKS_MASK 0x000000F0 ++#define SRECC_NUM_BANKS_SHIFT 4 ++#define SRECC_BANKSIZE_MASK 0x0000000F ++#define SRECC_BANKSIZE_SHIFT 0 ++ ++#define SRECC_BANKSIZE(value) (1 << (value)) ++ ++/* CAM bank patch control */ ++#define SRCBPC_PATCHENABLE 0x80000000 ++ ++#define SRP_ADDRESS 0x0001FFFC ++#define SRP_VALID 0x8000 ++ ++/* CAM bank command reg */ ++#define SRCMD_WRITE 0x00020000 ++#define SRCMD_READ 0x00010000 ++#define SRCMD_DONE 0x80000000 ++ ++#define SRCMD_DONE_DLY 1000 ++ ++/* bankidx and bankinfo reg defines corerev >= 8 */ ++#define SOCRAM_BANKINFO_SZMASK 0x7f ++#define SOCRAM_BANKIDX_ROM_MASK 0x100 ++ ++#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 ++/* socram bankinfo memtype */ ++#define SOCRAM_MEMTYPE_RAM 0 ++#define SOCRAM_MEMTYPE_R0M 1 ++#define SOCRAM_MEMTYPE_DEVRAM 2 ++ ++#define SOCRAM_BANKINFO_REG 0x40 ++#define SOCRAM_BANKIDX_REG 0x10 ++#define SOCRAM_BANKINFO_STDBY_MASK 0x400 ++#define SOCRAM_BANKINFO_STDBY_TIMER 0x800 ++ ++/* bankinfo rev >= 10 */ ++#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT 13 ++#define SOCRAM_BANKINFO_DEVRAMSEL_MASK 0x2000 ++#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT 14 ++#define SOCRAM_BANKINFO_DEVRAMPRO_MASK 0x4000 ++#define SOCRAM_BANKINFO_SLPSUPP_SHIFT 15 ++#define SOCRAM_BANKINFO_SLPSUPP_MASK 0x8000 ++#define SOCRAM_BANKINFO_RETNTRAM_SHIFT 16 ++#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 ++#define SOCRAM_BANKINFO_PDASZ_SHIFT 17 ++#define SOCRAM_BANKINFO_PDASZ_MASK 0x003E0000 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT 24 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK 0x01000000 ++ ++/* extracoreinfo register */ ++#define SOCRAM_DEVRAMBANK_MASK 0xF000 ++#define SOCRAM_DEVRAMBANK_SHIFT 12 ++ ++/* bank info to calculate bank size */ ++#define SOCRAM_BANKINFO_SZBASE 8192 ++#define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */ ++ ++ ++#endif /* _SBSOCRAM_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/siutils.h b/drivers/bcmdrivers/gmac/src/include/siutils.h +new file mode 100755 +index 0000000..5e4ce7d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch new file mode 100644 index 00000000..0c4ab04c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_siutils.h.patch @@ -0,0 +1,262 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/siutils.h +@@ -0,0 +1,256 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing the SOC Interconnects ++ * of Broadcom HNBU chips. ++ * ++ * $Id: siutils.h 323456 2012-03-24 07:17:39Z $ ++ */ ++ ++#ifndef _siutils_h_ ++#define _siutils_h_ ++ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++#include "bcm_rpc.h" ++#endif ++/* ++ * Data structure to export all chip specific common variables ++ * public (read-only) portion of siutils handle returned by si_attach()/si_kattach() ++ */ ++struct si_pub { ++ uint socitype; /* SOCI_SB, SOCI_AI */ ++ ++ uint bustype; /* SI_BUS, PCI_BUS */ ++ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ uint32 cccaps; /* chip common capabilities */ ++ uint32 cccaps_ext; /* chip common capabilities extension */ ++ int pmurev; /* pmu core rev */ ++ uint32 pmucaps; /* pmu capabilities */ ++ uint boardtype; /* board type */ ++ uint boardrev; /* board rev */ ++ uint boardvendor; /* board vendor */ ++ uint boardflags; /* board flags */ ++ uint boardflags2; /* board flags2 */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ uint32 chipst; /* chip status */ ++ bool issim; /* chip is in simulation or emulation */ ++ uint socirev; /* SOC interconnect rev */ ++ bool pci_pr32414; ++ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++ rpc_info_t *rpc; ++#endif ++#ifdef SI_ENUM_BASE_VARIABLE ++ uint32 si_enum_base; ++#endif /* SI_ENUM_BASE_VARIABLE */ ++}; ++ ++/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver ++ * for monolithic driver, it is readonly to prevent accident change ++ */ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++typedef struct si_pub si_t; ++#else ++typedef const struct si_pub si_t; ++#endif ++ ++#ifdef ATE_BUILD ++typedef struct _ate_params { ++ void* wl; ++ uint8 gpio_input; ++ uint8 gpio_output; ++ bool cmd_proceed; ++ uint16 cmd_idx; ++ bool ate_cmd_done; ++} ate_params_t; ++#endif /* ATE_BUILD */ ++ ++/* ++ * Many of the routines below take an 'sih' handle as their first arg. ++ * Allocate this by calling si_attach(). Free it by calling si_detach(). ++ * At any one time, the sih is logically focused on one particular si core ++ * (the "current core"). ++ * Use si_setcore() or si_setcoreidx() to change the association to another core. ++ */ ++#define SI_OSH NULL /* Use for si_kattach when no osh is available */ ++ ++#define BADIDX (SI_MAXCORES + 1) ++ ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ ++ ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ ++ ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ ++#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ ++ ++/* GPIO pull up/down */ ++#define GPIO_PULLUP 0 ++#define GPIO_PULLDN 1 ++ ++/* GPIO event regtype */ ++#define GPIO_REGEVT 0 /* GPIO register event */ ++#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ ++#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ ++ ++/* device path */ ++#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ ++ ++/* SI routine enumeration: to be used by update function with multiple hooks */ ++#define SI_DOATTACH 1 ++#define SI_PCIDOWN 2 ++#define SI_PCIUP 3 ++ ++#if defined(BCMQT) ++#define ISSIM_ENAB(sih) ((sih)->issim) ++#else ++#define ISSIM_ENAB(sih) 0 ++#endif ++ ++/* PMU clock/power control */ ++#if defined(BCMPMUCTL) ++#define PMUCTL_ENAB(sih) (BCMPMUCTL) ++#else ++#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) ++#endif ++ ++/* chipcommon clock/power control (exclusive with PMU's) */ ++#if defined(BCMPMUCTL) && BCMPMUCTL ++#define CCCTL_ENAB(sih) (0) ++#define CCPLL_ENAB(sih) (0) ++#else ++#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) ++#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) ++#endif ++ ++typedef void (*gpio_handler_t)(uint32 stat, void *arg); ++/* External BT Coex enable mask */ ++#define CC_BTCOEX_EN_MASK 0x01 ++/* External PA enable mask */ ++#define GPIO_CTRL_EPA_EN_MASK 0x40 ++/* WL/BT control enable mask */ ++#define GPIO_CTRL_5_6_EN_MASK 0x60 ++#define GPIO_CTRL_7_6_EN_MASK 0xC0 ++#define GPIO_OUT_7_EN_MASK 0x80 ++ ++ ++ ++ ++/* === exported functions === */ ++extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *si_kattach(osl_t *osh); ++extern void si_detach(si_t *sih); ++ ++extern uint si_corelist(si_t *sih, uint coreid[]); ++extern uint si_coreid(si_t *sih); ++extern uint si_flag(si_t *sih); ++extern uint si_intflag(si_t *sih); ++extern uint si_coreidx(si_t *sih); ++extern uint si_coreunit(si_t *sih); ++extern uint si_corevendor(si_t *sih); ++extern uint si_corerev(si_t *sih); ++extern void *si_osh(si_t *sih); ++extern void si_setosh(si_t *sih, osl_t *osh); ++extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void *si_coreregs(si_t *sih); ++extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); ++#ifdef WLC_HIGH_ONLY ++extern bool wlc_bmac_iscoreup(si_t *sih); ++#define si_iscoreup(sih) wlc_bmac_iscoreup(sih) ++#else ++extern bool si_iscoreup(si_t *sih); ++#endif /* __CONFIG_USBAP__ */ ++extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit); ++extern void *si_setcoreidx(si_t *sih, uint coreidx); ++extern void *si_setcore(si_t *sih, uint coreid, uint coreunit); ++extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); ++extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); ++extern int si_numaddrspaces(si_t *sih); ++extern uint32 si_addrspace(si_t *sih, uint asidx); ++extern uint32 si_addrspacesize(si_t *sih, uint asidx); ++extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern int si_corebist(si_t *sih); ++extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void si_core_disable(si_t *sih, uint32 bits); ++extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); ++extern uint32 si_clock(si_t *sih); ++extern uint32 si_alp_clock(si_t *sih); ++extern void si_setint(si_t *sih, int siflag); ++extern bool si_backplane64(si_t *sih); ++extern void si_clkctl_init(si_t *sih); ++extern bool si_clkctl_cc(si_t *sih, uint mode); ++extern int si_clkctl_xtal(si_t *sih, uint what, bool on); ++ ++extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool si_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool si_pci_fastpmecap(struct osl_info *osh); ++ ++/* SPROM availability */ ++#ifdef SI_SPROM_PROBE ++extern void si_sprom_init(si_t *sih); ++#endif /* SI_SPROM_PROBE */ ++ ++/* Fab-id information */ ++#define DEFAULT_FAB 0x0 /* Original/first fab used for this chip */ ++#define CSM_FAB7 0x1 /* CSM Fab7 chip */ ++#define TSMC_FAB12 0x2 /* TSMC Fab12/Fab14 chip */ ++#define SMIC_FAB4 0x3 /* SMIC Fab4 chip */ ++ ++/* ++ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. ++ * The returned path is NULL terminated and has trailing '/'. ++ * Return 0 on success, nonzero otherwise. ++ */ ++extern int si_devpath(si_t *sih, char *path, int size); ++/* Read variable with prepending the devpath to the name */ ++extern int si_getdevpathintvar(si_t *sih, const char *name); ++extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name); ++ ++ ++extern void si_war42780_clkreq(si_t *sih, bool clkreq); ++extern void si_pcie_extendL1timer(si_t *sih, bool extend); ++ ++/* === debug routines === */ ++ ++#ifdef BCMDBG ++extern void si_view(si_t *sih, bool verbose); ++extern void si_viewall(si_t *sih, bool verbose); ++#endif ++ ++#if defined(BCMDBG) ++struct bcmstrbuf; ++extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b); ++#endif ++ ++ ++#endif /* _siutils_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/trxhdr.h b/drivers/bcmdrivers/gmac/src/include/trxhdr.h +new file mode 100755 +index 0000000..4926311 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch new file mode 100644 index 00000000..98448ab4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch @@ -0,0 +1,92 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/trxhdr.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * TRX image file header format. ++ * ++ * $Id: trxhdr.h 314841 2012-02-14 18:28:33Z $ ++ */ ++ ++#ifndef _TRX_HDR_H ++#define _TRX_HDR_H ++ ++#include ++ ++#define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_MAX_LEN 0x3B0000 /* Max length */ ++#define TRX_NO_HEADER 1 /* Do not write TRX header */ ++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ ++#define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ ++#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ ++#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ ++#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */ ++ ++#define TRX_V1 1 ++#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */ ++ ++#ifndef BCMTRXV2 ++#define TRX_VERSION TRX_V1 /* Version 1 */ ++#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS ++#endif ++ ++/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as ++ * Ver 2 of trx header. To make it generic, trx_header is structure is modified ++ * as below where size of "offsets" field will vary as per the TRX version. ++ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well. ++ * To make sure, other applications like "dhdl" which are yet to be enhanced to support ++ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2 ++ * is defined. ++ */ ++struct trx_header { ++ uint32 magic; /* "HDR0" */ ++ uint32 len; /* Length of file including header */ ++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32 flag_version; /* 0:15 flags, 16:31 version */ ++#ifndef BCMTRXV2 ++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++#else ++ uint32 offsets[1]; /* Offsets of partitions from start of header */ ++#endif ++}; ++ ++#ifdef BCMTRXV2 ++#define TRX_VERSION TRX_V2 /* Version 2 */ ++#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS ++ ++#define TRX_V2 2 ++/* V2: Max number of individual files ++ * To support SDR signature + Config data region ++ */ ++#define TRX_V2_MAX_OFFSETS 5 ++#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32)) ++#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32)) ++#define TRX_VER(trx) (trx->flag_version>>16) ++#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1) ++#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2) ++/* For V2, return size of V2 size: others, return V1 size */ ++#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1) ++#else ++#define SIZEOF_TRX(trx) (sizeof(struct trx_header)) ++#endif /* BCMTRXV2 */ ++ ++/* Compatibility */ ++typedef struct trx_header TRXHDR, *PTRXHDR; ++ ++#endif /* _TRX_HDR_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/typedefs.h b/drivers/bcmdrivers/gmac/src/include/typedefs.h +new file mode 100644 +index 0000000..5caa36a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch new file mode 100644 index 00000000..048141c0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_typedefs.h.patch @@ -0,0 +1,458 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/typedefs.h +@@ -0,0 +1,452 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: typedefs.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++#ifndef _TYPEDEFS_H_ ++#define _TYPEDEFS_H_ ++ ++#ifdef SITE_TYPEDEFS ++ ++/* ++ * Define SITE_TYPEDEFS in the compile to include a site-specific ++ * typedef file "site_typedefs.h". ++ * ++ * If SITE_TYPEDEFS is not defined, then the code section below makes ++ * inferences about the compile environment based on defined symbols and ++ * possibly compiler pragmas. ++ * ++ * Following these two sections is the Default Typedefs section. ++ * This section is only processed if USE_TYPEDEF_DEFAULTS is ++ * defined. This section has a default set of typedefs and a few ++ * preprocessor symbols (TRUE, FALSE, NULL, ...). ++ */ ++ ++#include "site_typedefs.h" ++ ++#else ++ ++/* ++ * Infer the compile environment based on preprocessor symbols and pragmas. ++ * Override type definitions as needed, and include configuration-dependent ++ * header files to define types. ++ */ ++ ++#ifdef __cplusplus ++ ++#define TYPEDEF_BOOL ++#ifndef FALSE ++#define FALSE false ++#endif ++#ifndef TRUE ++#define TRUE true ++#endif ++ ++#else /* ! __cplusplus */ ++ ++#if defined(_WIN32) ++ ++#define TYPEDEF_BOOL ++typedef unsigned char bool; /* consistent w/BOOL */ ++ ++#endif /* _WIN32 */ ++ ++#endif /* ! __cplusplus */ ++ ++#if defined(_WIN64) && !defined(EFI) ++/* use the Windows ULONG_PTR type when compiling for 64 bit */ ++#include ++#define TYPEDEF_UINTPTR ++typedef ULONG_PTR uintptr; ++#elif defined(__x86_64__) ++#define TYPEDEF_UINTPTR ++typedef unsigned long long int uintptr; ++#endif ++ ++ ++#if defined(_MINOSL_) ++#define _NEED_SIZE_T_ ++#endif ++ ++#if defined(EFI) && !defined(_WIN64) ++#define _NEED_SIZE_T_ ++#endif ++ ++#if defined(TARGETOS_nucleus) ++/* for 'size_t' type */ ++#include ++ ++/* float_t types conflict with the same typedefs from the standard ANSI-C ++** math.h header file. Don't re-typedef them here. ++*/ ++#define TYPEDEF_FLOAT_T ++#endif /* TARGETOS_nucleus */ ++ ++#if defined(_NEED_SIZE_T_) ++typedef long unsigned int size_t; ++#endif ++ ++#ifdef _MSC_VER /* Microsoft C */ ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++typedef signed __int64 int64; ++typedef unsigned __int64 uint64; ++#endif ++ ++#if defined(MACOSX) ++#define TYPEDEF_BOOL ++#endif ++ ++#if defined(__NetBSD__) ++#define TYPEDEF_BOOL ++#ifndef _KERNEL ++#include ++#endif ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* defined(__NetBSD__) */ ++ ++#if defined(__sparc__) ++#define TYPEDEF_ULONG ++#endif ++ ++ ++#ifdef linux ++/* ++ * If this is either a Linux hybrid build or the per-port code of a hybrid build ++ * then use the Linux header files to get some of the typedefs. Otherwise, define ++ * them entirely in this file. We can't always define the types because we get ++ * a duplicate typedef error; there is no way to "undefine" a typedef. ++ * We know when it's per-port code because each file defines LINUX_PORT at the top. ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#define TYPEDEF_UINT ++#ifndef TARGETENV_android ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* TARGETENV_android */ ++#ifdef __KERNEL__ ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) ++#define TYPEDEF_BOOL ++#endif /* >= 2.6.19 */ ++/* special detection for 2.6.18-128.7.1.0.1.el5 */ ++#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18)) ++#include ++#ifdef noinline_for_stack ++#define TYPEDEF_BOOL ++#endif ++#endif /* == 2.6.18 */ ++#endif /* __KERNEL__ */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++#endif /* linux */ ++ ++#if defined(__ECOS) ++#define TYPEDEF_UCHAR ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#define TYPEDEF_BOOL ++#endif ++ ++#if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \ ++ !defined(__DJGPP__) && !defined(__ECOS) && !defined(__BOB__) && \ ++ !defined(TARGETOS_nucleus) && !defined(EFI) && !defined(__FreeBSD__) ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#endif ++ ++ ++/* Do not support the (u)int64 types with strict ansi for GNU C */ ++#if defined(__GNUC__) && defined(__STRICT_ANSI__) ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++#endif ++ ++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode ++ * for signed or unsigned ++ */ ++#if defined(__ICL) ++ ++#define TYPEDEF_INT64 ++ ++#if defined(__STDC__) ++#define TYPEDEF_UINT64 ++#endif ++ ++#endif /* __ICL */ ++ ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && !defined(__DJGPP__) && \ ++ !defined(__BOB__) && !defined(TARGETOS_nucleus) && !defined(EFI) ++ ++/* pick up ushort & uint from standard types.h */ ++#if defined(linux) && defined(__KERNEL__) ++ ++/* See note above */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#ifdef USER_MODE ++#include ++#else ++#include /* sys/types.h and linux/types.h are oil and water */ ++#endif /* USER_MODE */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++#else ++ ++#if defined(__ECOS) ++#include ++#include ++#include ++#endif ++ ++#include ++ ++#endif /* linux && __KERNEL__ */ ++ ++#endif ++ ++#if defined(CONFIG_MACH_NSP) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) /* JIRA:LINUXDEV- */ ++#ifdef CONFIG_CPU_BIG_ENDIAN ++#define IL_BIGENDIAN ++#endif /* CONFIG_CPU_BIG_ENDIAN */ ++#else ++ ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++ ++#endif ++ ++#if defined(MACOSX) ++ ++#ifdef __BIG_ENDIAN__ ++#define IL_BIGENDIAN ++#else ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++#endif /* __BIG_ENDIAN__ */ ++ ++#if !defined(__cplusplus) ++ ++#if defined(__i386__) ++typedef unsigned char bool; ++#else ++typedef unsigned int bool; ++#endif ++#define TYPE_BOOL 1 ++enum { ++ false = 0, ++ true = 1 ++}; ++ ++#if defined(KERNEL) ++#include ++#endif /* KERNEL */ ++ ++#endif /* __cplusplus */ ++ ++#endif /* MACOSX */ ++ ++ ++/* use the default typedefs in the next section of this file */ ++#define USE_TYPEDEF_DEFAULTS ++ ++#endif /* SITE_TYPEDEFS */ ++ ++ ++/* ++ * Default Typedefs ++ */ ++ ++#ifdef USE_TYPEDEF_DEFAULTS ++#undef USE_TYPEDEF_DEFAULTS ++ ++#ifndef TYPEDEF_BOOL ++typedef /* @abstract@ */ unsigned char bool; ++#endif ++ ++/* define uchar, ushort, uint, ulong */ ++ ++#ifndef TYPEDEF_UCHAR ++typedef unsigned char uchar; ++#endif ++ ++#ifndef TYPEDEF_USHORT ++typedef unsigned short ushort; ++#endif ++ ++#ifndef TYPEDEF_UINT ++typedef unsigned int uint; ++#endif ++ ++#ifndef TYPEDEF_ULONG ++typedef unsigned long ulong; ++#endif ++ ++/* define [u]int8/16/32/64, uintptr */ ++ ++#ifndef TYPEDEF_UINT8 ++typedef unsigned char uint8; ++#endif ++ ++#ifndef TYPEDEF_UINT16 ++typedef unsigned short uint16; ++#endif ++ ++#ifndef TYPEDEF_UINT32 ++typedef unsigned int uint32; ++#endif ++ ++#ifndef TYPEDEF_UINT64 ++typedef unsigned long long uint64; ++#endif ++ ++#ifndef TYPEDEF_UINTPTR ++typedef unsigned int uintptr; ++#endif ++ ++#ifndef TYPEDEF_INT8 ++typedef signed char int8; ++#endif ++ ++#ifndef TYPEDEF_INT16 ++typedef signed short int16; ++#endif ++ ++#ifndef TYPEDEF_INT32 ++typedef signed int int32; ++#endif ++ ++#ifndef TYPEDEF_INT64 ++typedef signed long long int64; ++#endif ++ ++/* define float32/64, float_t */ ++ ++#ifndef TYPEDEF_FLOAT32 ++typedef float float32; ++#endif ++ ++#ifndef TYPEDEF_FLOAT64 ++typedef double float64; ++#endif ++ ++/* ++ * abstracted floating point type allows for compile time selection of ++ * single or double precision arithmetic. Compiling with -DFLOAT32 ++ * selects single precision; the default is double precision. ++ */ ++ ++#ifndef TYPEDEF_FLOAT_T ++ ++#if defined(FLOAT32) ++typedef float32 float_t; ++#else /* default to double precision floating point */ ++typedef float64 float_t; ++#endif ++ ++#endif /* TYPEDEF_FLOAT_T */ ++ ++/* define macro values */ ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 /* TRUE */ ++#endif ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++#ifndef OFF ++#define OFF 0 ++#endif ++ ++#ifndef ON ++#define ON 1 /* ON = 1 */ ++#endif ++ ++#define AUTO (-1) /* Auto = -1 */ ++ ++/* define PTRSZ, INLINE */ ++ ++#ifndef PTRSZ ++#define PTRSZ sizeof(char*) ++#endif ++ ++ ++/* Detect compiler type. */ ++#ifdef _MSC_VER ++ #define BWL_COMPILER_MICROSOFT ++#elif defined(__GNUC__) || defined(__lint) ++ #define BWL_COMPILER_GNU ++#elif defined(__CC_ARM) && __CC_ARM ++ #define BWL_COMPILER_ARMCC ++#else ++ #error "Unknown compiler!" ++#endif /* _MSC_VER */ ++ ++ ++#ifndef INLINE ++ #if defined(BWL_COMPILER_MICROSOFT) ++ #define INLINE __inline ++ #elif defined(BWL_COMPILER_GNU) ++ #define INLINE __inline__ ++ #elif defined(BWL_COMPILER_ARMCC) ++ #define INLINE __inline ++ #else ++ #define INLINE ++ #endif /* _MSC_VER */ ++#endif /* INLINE */ ++ ++#undef TYPEDEF_BOOL ++#undef TYPEDEF_UCHAR ++#undef TYPEDEF_USHORT ++#undef TYPEDEF_UINT ++#undef TYPEDEF_ULONG ++#undef TYPEDEF_UINT8 ++#undef TYPEDEF_UINT16 ++#undef TYPEDEF_UINT32 ++#undef TYPEDEF_UINT64 ++#undef TYPEDEF_UINTPTR ++#undef TYPEDEF_INT8 ++#undef TYPEDEF_INT16 ++#undef TYPEDEF_INT32 ++#undef TYPEDEF_INT64 ++#undef TYPEDEF_FLOAT32 ++#undef TYPEDEF_FLOAT64 ++#undef TYPEDEF_FLOAT_T ++ ++#endif /* USE_TYPEDEF_DEFAULTS */ ++ ++/* Suppress unused parameter warning */ ++#define UNUSED_PARAMETER(x) (void)(x) ++ ++/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ ++#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) ++ ++/* ++ * Including the bcmdefs.h here, to make sure everyone including typedefs.h ++ * gets this automatically ++*/ ++#include ++#endif /* _TYPEDEFS_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/wlioctl.h b/drivers/bcmdrivers/gmac/src/include/wlioctl.h +new file mode 100755 +index 0000000..3aef8ca diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch new file mode 100644 index 00000000..9db6e3c3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch @@ -0,0 +1,4889 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/wlioctl.h +@@ -0,0 +1,4883 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Custom OID/ioctl definitions for ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * $Id: wlioctl.h 324203 2012-03-28 09:55:17Z $ ++ */ ++ ++#ifndef _wlioctl_h_ ++#define _wlioctl_h_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#ifdef __NetBSD__ ++/* NetBSD 2.0 does not have SIOCDEVPRIVATE. */ ++#define SIOCDEVPRIVATE _IOWR('i', 139, struct ifreq) ++#endif ++ ++#ifndef INTF_NAME_SIZ ++#define INTF_NAME_SIZ 16 ++#endif ++ ++/* Used to send ioctls over the transport pipe */ ++typedef struct remote_ioctl { ++ cdc_ioctl_t msg; ++ uint data_len; ++#ifndef OLYMPIC_RWL ++ char intf_name[INTF_NAME_SIZ]; ++#endif ++} rem_ioctl_t; ++#define REMOTE_SIZE sizeof(rem_ioctl_t) ++#ifdef EFI ++#define BCMWL_IOCTL_GUID \ ++ {0xB4910A35, 0x88C5, 0x4328, { 0x90, 0x08, 0x9F, 0xB2, 0x00, 0x00, 0x0, 0x0 } } ++#endif /* EFI */ ++ ++#define ACTION_FRAME_SIZE 1800 ++ ++typedef struct wl_action_frame { ++ struct ether_addr da; ++ uint16 len; ++ uint32 packetId; ++ uint8 data[ACTION_FRAME_SIZE]; ++} wl_action_frame_t; ++ ++#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) ++ ++typedef struct ssid_info ++{ ++ uint8 ssid_len; /* the length of SSID */ ++ uint8 ssid[32]; /* SSID string */ ++} ssid_info_t; ++ ++typedef struct wl_af_params { ++ uint32 channel; ++ int32 dwell_time; ++ struct ether_addr BSSID; ++ wl_action_frame_t action_frame; ++} wl_af_params_t; ++ ++#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params) ++ ++#define MFP_TEST_FLAG_NORMAL 0 ++#define MFP_TEST_FLAG_ANY_KEY 1 ++typedef struct wl_sa_query { ++ uint32 flag; ++ uint8 action; ++ uint16 id; ++ struct ether_addr da; ++} wl_sa_query_t; ++ ++ ++/* require default structure packing */ ++#define BWL_DEFAULT_PACKING ++#include ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Legacy structure to help keep backward compatible wl tool and tray app */ ++ ++#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ ++ ++typedef struct wl_bss_info_107 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ uint8 channel; /* Channel no. */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* variable length Information Elements */ ++} wl_bss_info_107_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* ++ * Per-BSS information structure. ++ */ ++ ++#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info_108 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint32 reserved32[1]; /* Reserved for expansion of BSS properties */ ++ uint8 flags; /* flags */ ++ uint8 reserved[3]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_108_t; ++ ++#define WL_BSS_INFO_VERSION 109 /* current version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint16 vht_rxmcsmap; /* VHT rx mcs map */ ++ uint16 vht_txmcsmap; /* VHT tx mcs map */ ++ uint8 flags; /* flags */ ++ uint8 vht_cap; /* BSS is vht capable */ ++ uint8 reserved[2]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ int16 SNR; /* average SNR of during frame reception */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_t; ++ ++typedef struct wl_bsscfg { ++ uint32 wsec; ++ uint32 WPA_auth; ++ uint32 wsec_index; ++ uint32 associated; ++ uint32 BSS; ++ uint32 phytest_on; ++ struct ether_addr prev_BSSID; ++ struct ether_addr BSSID; ++} wl_bsscfg_t; ++ ++typedef struct wl_bss_config { ++ uint32 atim_window; ++ uint32 beacon_period; ++ uint32 chanspec; ++} wl_bss_config_t; ++ ++#define DLOAD_HANDLER_VER 1 /* Downloader version */ ++#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ ++#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ ++ ++#define DL_CRC_NOT_INUSE 0x0001 ++ ++/* generic download types & flags */ ++enum { ++ DL_TYPE_UCODE = 1, ++ DL_TYPE_CLM = 2 ++}; ++ ++/* ucode type values */ ++enum { ++ UCODE_FW, ++ INIT_VALS, ++ BS_INIT_VALS ++}; ++ ++struct wl_dload_data { ++ uint16 flag; ++ uint16 dload_type; ++ uint32 len; ++ uint32 crc; ++ uint8 data[1]; ++}; ++typedef struct wl_dload_data wl_dload_data_t; ++ ++struct wl_ucode_info { ++ uint32 ucode_type; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_num; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_ucode_info wl_ucode_info_t; ++ ++struct wl_clm_dload_info { ++ uint32 ds_id; ++ uint32 clm_total_len; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_offset; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_clm_dload_info wl_clm_dload_info_t; ++ ++typedef struct wlc_ssid { ++ uint32 SSID_len; ++ uchar SSID[32]; ++} wlc_ssid_t; ++ ++#define MAX_PREFERRED_AP_NUM 5 ++typedef struct wlc_fastssidinfo { ++ uint32 SSID_channel[MAX_PREFERRED_AP_NUM]; ++ wlc_ssid_t SSID_info[MAX_PREFERRED_AP_NUM]; ++} wlc_fastssidinfo_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct wnm_url { ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT wnm_url_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct chan_scandata { ++ uint8 txpower; ++ uint8 pad; ++ chanspec_t channel; /* Channel num, bw, ctrl_sb and band */ ++ uint32 channel_mintime; ++ uint32 channel_maxtime; ++} chan_scandata_t; ++ ++typedef enum wl_scan_type { ++ EXTDSCAN_FOREGROUND_SCAN, ++ EXTDSCAN_BACKGROUND_SCAN, ++ EXTDSCAN_FORCEDBACKGROUND_SCAN ++} wl_scan_type_t; ++ ++#define WLC_EXTDSCAN_MAX_SSID 5 ++ ++#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ ++#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ ++#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info was received on channel (vs offchannel) */ ++ ++typedef struct wl_extdscan_params { ++ int8 nprobes; /* 0, passive, otherwise active */ ++ int8 split_scan; /* split scan */ ++ int8 band; /* band */ ++ int8 pad; ++ wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */ ++ uint32 tx_rate; /* in 500ksec units */ ++ wl_scan_type_t scan_type; /* enum */ ++ int32 channel_num; ++ chan_scandata_t channel_list[1]; /* list of chandata structs */ ++} wl_extdscan_params_t; ++ ++#define WL_EXTDSCAN_PARAMS_FIXED_SIZE (sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t)) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_BSSTYPE_INFRA 1 ++#define WL_BSSTYPE_INDEP 0 ++#define WL_BSSTYPE_ANY 2 ++ ++/* Bitmask for scan_type */ ++#define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ ++#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ ++#define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ ++ ++#define WL_SCAN_PARAMS_SSID_MAX 10 ++ ++typedef struct wl_scan_params { ++ wlc_ssid_t ssid; /* default: {0, ""} */ ++ struct ether_addr bssid; /* default: bcast */ ++ int8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ uint8 scan_type; /* flags, 0 use default */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++ int32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in channel_list, 0 ++ * means default (use all available channels) ++ * ++ * high half is entries in wlc_ssid_t array that ++ * follows channel_list, aligned for int32 (4 bytes) ++ * meaning an odd channel count implies a 2-byte pad ++ * between end of channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the fixed ++ * parameter portion is assumed, otherwise ssid in ++ * the fixed portion is ignored ++ */ ++ uint16 channel_list[1]; /* list of chanspecs */ ++} wl_scan_params_t; ++ ++/* size of wl_scan_params not including variable length array */ ++#define WL_SCAN_PARAMS_FIXED_SIZE 64 ++ ++/* masks for channel and ssid count */ ++#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff ++#define WL_SCAN_PARAMS_NSSID_SHIFT 16 ++ ++#define WL_SCAN_ACTION_START 1 ++#define WL_SCAN_ACTION_CONTINUE 2 ++#define WL_SCAN_ACTION_ABORT 3 ++ ++#define ISCAN_REQ_VERSION 1 ++ ++/* incremental scan struct */ ++typedef struct wl_iscan_params { ++ uint32 version; ++ uint16 action; ++ uint16 scan_duration; ++ wl_scan_params_t params; ++} wl_iscan_params_t; ++ ++/* 3 fields + size of wl_scan_params, not including variable length array */ ++#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_scan_results { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ wl_bss_info_t bss_info[1]; ++} wl_scan_results_t; ++ ++/* size of wl_scan_results not including variable length array */ ++#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t)) ++ ++/* wl_iscan_results status values */ ++#define WL_SCAN_RESULTS_SUCCESS 0 ++#define WL_SCAN_RESULTS_PARTIAL 1 ++#define WL_SCAN_RESULTS_PENDING 2 ++#define WL_SCAN_RESULTS_ABORTED 3 ++#define WL_SCAN_RESULTS_NO_MEM 4 ++ ++/* Used in EXT_STA */ ++#define DNGL_RXCTXT_SIZE 45 ++ ++#if defined(SIMPLE_ISCAN) ++#define ISCAN_RETRY_CNT 5 ++#define ISCAN_STATE_IDLE 0 ++#define ISCAN_STATE_SCANING 1 ++#define ISCAN_STATE_PENDING 2 ++ ++/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */ ++#define WLC_IW_ISCAN_MAXLEN 2048 ++typedef struct iscan_buf { ++ struct iscan_buf * next; ++ char iscan_buf[WLC_IW_ISCAN_MAXLEN]; ++} iscan_buf_t; ++#endif /* SIMPLE_ISCAN */ ++ ++#define ESCAN_REQ_VERSION 1 ++ ++typedef struct wl_escan_params { ++ uint32 version; ++ uint16 action; ++ uint16 sync_id; ++ wl_scan_params_t params; ++} wl_escan_params_t; ++ ++#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_escan_result { ++ uint32 buflen; ++ uint32 version; ++ uint16 sync_id; ++ uint16 bss_count; ++ wl_bss_info_t bss_info[1]; ++} wl_escan_result_t; ++ ++#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) ++ ++/* incremental scan results struct */ ++typedef struct wl_iscan_results { ++ uint32 status; ++ wl_scan_results_t results; ++} wl_iscan_results_t; ++ ++/* size of wl_iscan_results not including variable length array */ ++#define WL_ISCAN_RESULTS_FIXED_SIZE \ ++ (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results)) ++ ++typedef struct wl_probe_params { ++ wlc_ssid_t ssid; ++ struct ether_addr bssid; ++ struct ether_addr mac; ++} wl_probe_params_t; ++ ++#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */ ++typedef struct wl_rateset { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++} wl_rateset_t; ++ ++typedef struct wl_rateset_args { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ ++} wl_rateset_args_t; ++ ++/* uint32 list */ ++typedef struct wl_uint32_list { ++ /* in - # of elements, out - # of entries */ ++ uint32 count; ++ /* variable length uint32 list */ ++ uint32 element[1]; ++} wl_uint32_list_t; ++ ++/* used for association with a specific BSSID and chanspec list */ ++typedef struct wl_assoc_params { ++ struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ ++ int32 chanspec_num; /* 0: all available channels, ++ * otherwise count of chanspecs in chanspec_list ++ */ ++ chanspec_t chanspec_list[1]; /* list of chanspecs */ ++} wl_assoc_params_t; ++#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list) ++ ++/* used for reassociation/roam to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_reassoc_params_t; ++#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for association to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_join_assoc_params_t; ++#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for join with or without a specific bssid and channel list */ ++typedef struct wl_join_params { ++ wlc_ssid_t ssid; ++ wl_assoc_params_t params; /* optional field, but it must include the fixed portion ++ * of the wl_assoc_params_t struct when it does present. ++ */ ++} wl_join_params_t; ++#define WL_JOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_join_params_t, params) + \ ++ WL_ASSOC_PARAMS_FIXED_SIZE) ++/* scan params for extended join */ ++typedef struct wl_join_scan_params { ++ uint8 scan_type; /* 0 use default, active or passive scan */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++} wl_join_scan_params_t; ++ ++/* extended join params */ ++typedef struct wl_extjoin_params { ++ wlc_ssid_t ssid; /* {0, ""}: wildcard scan */ ++ wl_join_scan_params_t scan; ++ wl_join_assoc_params_t assoc; /* optional field, but it must include the fixed portion ++ * of the wl_join_assoc_params_t struct when it does ++ * present. ++ */ ++} wl_extjoin_params_t; ++#define WL_EXTJOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_extjoin_params_t, assoc) + \ ++ WL_JOIN_ASSOC_PARAMS_FIXED_SIZE) ++ ++/* All builds use the new 11ac ratespec/chanspec */ ++#undef D11AC_IOTYPES ++#define D11AC_IOTYPES ++ ++#ifndef D11AC_IOTYPES ++ ++/* defines used by the nrate iovar */ ++#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ ++#define NRATE_SGI_SHIFT 23 /* sgi mode */ ++#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ ++ ++#define NRATE_STF_SISO 0 /* stf mode SISO */ ++#define NRATE_STF_CDD 1 /* stf mode CDD */ ++#define NRATE_STF_STBC 2 /* stf mode STBC */ ++#define NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#else /* D11AC_IOTYPES */ ++ ++/* WL_RSPEC defines for rate information */ ++#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */ ++#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */ ++#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */ ++#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */ ++#define WL_RSPEC_TXEXP_MASK 0x00000300 ++#define WL_RSPEC_TXEXP_SHIFT 8 ++#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ ++#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ ++#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ ++#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ ++#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ ++#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ ++#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */ ++#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */ ++ ++/* WL_RSPEC_ENCODING field defs */ ++#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */ ++ ++/* WL_RSPEC_BW field defs */ ++#define WL_RSPEC_BW_UNSPECIFIED 0 ++#define WL_RSPEC_BW_20MHZ 0x00010000 ++#define WL_RSPEC_BW_40MHZ 0x00020000 ++#define WL_RSPEC_BW_80MHZ 0x00030000 ++#define WL_RSPEC_BW_160MHZ 0x00040000 ++ ++/* Legacy defines for the nrate iovar */ ++#define OLD_NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define OLD_NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define OLD_NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define OLD_NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define OLD_NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define OLD_NRATE_SGI 0x00800000 /* sgi mode */ ++#define OLD_NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++ ++#define OLD_NRATE_STF_SISO 0 /* stf mode SISO */ ++#define OLD_NRATE_STF_CDD 1 /* stf mode CDD */ ++#define OLD_NRATE_STF_STBC 2 /* stf mode STBC */ ++#define OLD_NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#endif /* D11AC_IOTYPES */ ++ ++#define ANTENNA_NUM_1 1 /* total number of antennas to be used */ ++#define ANTENNA_NUM_2 2 ++#define ANTENNA_NUM_3 3 ++#define ANTENNA_NUM_4 4 ++ ++#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ ++#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ ++#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */ ++#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ ++#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ ++#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ ++#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ ++ ++#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ ++ ++typedef struct { ++ uint8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ ++ uint8 num_antcfg; /* number of available antenna configurations */ ++} wlc_antselcfg_t; ++ ++#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ ++ ++#define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */ ++#define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */ ++ ++#define IBSS_MED 15 /* Mediom in-bss congestion percentage */ ++#define IBSS_HI 25 /* Hi in-bss congestion percentage */ ++#define OBSS_MED 12 ++#define OBSS_HI 25 ++#define INTERFER_MED 5 ++#define INTERFER_HI 10 ++ ++#define CCA_FLAG_2G_ONLY 0x01 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_5G_ONLY 0x02 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_IGNORE_DURATION 0x04 /* Ignore dwell time for each channel */ ++#define CCA_FLAGS_PREFER_1_6_11 0x10 ++#define CCA_FLAG_IGNORE_INTERFER 0x20 /* do not exlude channel based on interfer level */ ++ ++#define CCA_ERRNO_BAND 1 /* After filtering for band pref, no choices left */ ++#define CCA_ERRNO_DURATION 2 /* After filtering for duration, no choices left */ ++#define CCA_ERRNO_PREF_CHAN 3 /* After filtering for chan pref, no choices left */ ++#define CCA_ERRNO_INTERFER 4 /* After filtering for interference, no choices left */ ++#define CCA_ERRNO_TOO_FEW 5 /* Only 1 channel was input */ ++ ++typedef struct { ++ uint32 duration; /* millisecs spent sampling this channel */ ++ uint32 congest_ibss; /* millisecs in our bss (presumably this traffic will */ ++ /* move if cur bss moves channels) */ ++ uint32 congest_obss; /* traffic not in our bss */ ++ uint32 interference; /* millisecs detecting a non 802.11 interferer. */ ++ uint32 timestamp; /* second timestamp */ ++} cca_congest_t; ++ ++typedef struct { ++ chanspec_t chanspec; /* Which channel? */ ++ uint8 num_secs; /* How many secs worth of data */ ++ cca_congest_t secs[1]; /* Data */ ++} cca_congest_channel_req_t; ++ ++/* interference source detection and identification mode */ ++#define ITFR_MODE_DISABLE 0 /* disable feature */ ++#define ITFR_MODE_MANUAL_ENABLE 1 /* enable manual detection */ ++#define ITFR_MODE_AUTO_ENABLE 2 /* enable auto detection */ ++ ++/* interference sources */ ++enum interference_source { ++ ITFR_NONE = 0, /* interference */ ++ ITFR_PHONE, /* wireless phone */ ++ ITFR_VIDEO_CAMERA, /* wireless video camera */ ++ ITFR_MICROWAVE_OVEN, /* microwave oven */ ++ ITFR_BABY_MONITOR, /* wireless baby monitor */ ++ ITFR_BLUETOOTH, /* bluetooth */ ++ ITFR_VIDEO_CAMERA_OR_BABY_MONITOR, /* wireless camera or baby monitor */ ++ ITFR_BLUETOOTH_OR_BABY_MONITOR, /* bluetooth or baby monitor */ ++ ITFR_VIDEO_CAMERA_OR_PHONE, /* video camera or phone */ ++ ITFR_UNIDENTIFIED /* interference from unidentified source */ ++}; ++ ++/* structure for interference source report */ ++typedef struct { ++ uint32 flags; /* flags. bit definitions below */ ++ uint32 source; /* last detected interference source */ ++ uint32 timestamp; /* second timestamp on interferenced flag change */ ++} interference_source_rep_t; ++ ++/* bit definitions for flags in interference source report */ ++#define ITFR_INTERFERENCED 1 /* interference detected */ ++#define ITFR_HOME_CHANNEL 2 /* home channel has interference */ ++#define ITFR_NOISY_ENVIRONMENT 4 /* noisy environemnt so feature stopped */ ++ ++#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ ++ ++typedef struct wl_country { ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in ++ * the Country IE ++ */ ++ int32 rev; /* revision specifier for ccode ++ * on set, -1 indicates unspecified. ++ * on get, rev >= 0 ++ */ ++ char ccode[WLC_CNTRY_BUF_SZ]; /* nul-terminated built-in country code. ++ * variable length, but fixed size in ++ * struct allows simple allocation for ++ * expected country strings <= 3 chars. ++ */ ++} wl_country_t; ++ ++typedef struct wl_channels_in_country { ++ uint32 buflen; ++ uint32 band; ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; ++ uint32 count; ++ uint32 channel[1]; ++} wl_channels_in_country_t; ++ ++typedef struct wl_country_list { ++ uint32 buflen; ++ uint32 band_set; ++ uint32 band; ++ uint32 count; ++ char country_abbrev[1]; ++} wl_country_list_t; ++ ++#define WL_NUM_RPI_BINS 8 ++#define WL_RM_TYPE_BASIC 1 ++#define WL_RM_TYPE_CCA 2 ++#define WL_RM_TYPE_RPI 3 ++ ++#define WL_RM_FLAG_PARALLEL (1<<0) ++ ++#define WL_RM_FLAG_LATE (1<<1) ++#define WL_RM_FLAG_INCAPABLE (1<<2) ++#define WL_RM_FLAG_REFUSED (1<<3) ++ ++typedef struct wl_rm_req_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++} wl_rm_req_elt_t; ++ ++typedef struct wl_rm_req { ++ uint32 token; /* overall measurement set token */ ++ uint32 count; /* number of measurement requests */ ++ void *cb; /* completion callback function: may be NULL */ ++ void *cb_arg; /* arg to completion callback function */ ++ wl_rm_req_elt_t req[1]; /* variable length block of requests */ ++} wl_rm_req_t; ++#define WL_RM_REQ_FIXED_LEN OFFSETOF(wl_rm_req_t, req) ++ ++typedef struct wl_rm_rep_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++ uint32 len; /* byte length of data block */ ++ uint8 data[1]; /* variable length data block */ ++} wl_rm_rep_elt_t; ++#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */ ++ ++#define WL_RPI_REP_BIN_NUM 8 ++typedef struct wl_rm_rpi_rep { ++ uint8 rpi[WL_RPI_REP_BIN_NUM]; ++ int8 rpi_max[WL_RPI_REP_BIN_NUM]; ++} wl_rm_rpi_rep_t; ++ ++typedef struct wl_rm_rep { ++ uint32 token; /* overall measurement set token */ ++ uint32 len; /* length of measurement report block */ ++ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ ++} wl_rm_rep_t; ++#define WL_RM_REP_FIXED_LEN 8 ++ ++ ++#if defined(BCMSUP_PSK) ++typedef enum sup_auth_status { ++ /* Basic supplicant authentication states */ ++ WLC_SUP_DISCONNECTED = 0, ++ WLC_SUP_CONNECTING, ++ WLC_SUP_IDREQUIRED, ++ WLC_SUP_AUTHENTICATING, ++ WLC_SUP_AUTHENTICATED, ++ WLC_SUP_KEYXCHANGE, ++ WLC_SUP_KEYED, ++ WLC_SUP_TIMEOUT, ++ WLC_SUP_LAST_BASIC_STATE, ++ ++ /* Extended supplicant authentication states */ ++ /* Waiting to receive handshake msg M1 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, ++ /* Preparing to send handshake msg M2 */ ++ WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, ++ /* Waiting to receive handshake msg M3 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, ++ WLC_SUP_KEYXCHANGE_PREP_M4, /* Preparing to send handshake msg M4 */ ++ WLC_SUP_KEYXCHANGE_WAIT_G1, /* Waiting to receive handshake msg G1 */ ++ WLC_SUP_KEYXCHANGE_PREP_G2 /* Preparing to send handshake msg G2 */ ++} sup_auth_status_t; ++#endif ++ ++/* Enumerate crypto algorithms */ ++#define CRYPTO_ALGO_OFF 0 ++#define CRYPTO_ALGO_WEP1 1 ++#define CRYPTO_ALGO_TKIP 2 ++#define CRYPTO_ALGO_WEP128 3 ++#define CRYPTO_ALGO_AES_CCM 4 ++#define CRYPTO_ALGO_AES_OCB_MSDU 5 ++#define CRYPTO_ALGO_AES_OCB_MPDU 6 ++#define CRYPTO_ALGO_NALG 7 ++#define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ ++ ++#define WSEC_GEN_MIC_ERROR 0x0001 ++#define WSEC_GEN_REPLAY 0x0002 ++#define WSEC_GEN_ICV_ERROR 0x0004 ++#define WSEC_GEN_MFP_ACT_ERROR 0x0008 ++#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010 ++#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020 ++ ++#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ ++#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ ++#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ ++#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ ++#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ ++ ++typedef struct wl_wsec_key { ++ uint32 index; /* key index */ ++ uint32 len; /* key length */ ++ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */ ++ uint32 pad_1[18]; ++ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ uint32 flags; /* misc flags */ ++ uint32 pad_2[2]; ++ int pad_3; ++ int iv_initialized; /* has IV been initialized already? */ ++ int pad_4; ++ /* Rx IV */ ++ struct { ++ uint32 hi; /* upper 32 bits of IV */ ++ uint16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ uint32 pad_5[2]; ++ struct ether_addr ea; /* per station */ ++} wl_wsec_key_t; ++ ++#define WSEC_MIN_PSK_LEN 8 ++#define WSEC_MAX_PSK_LEN 64 ++ ++/* Flag for key material needing passhash'ing */ ++#define WSEC_PASSPHRASE (1<<0) ++ ++/* receptacle for WLC_SET_WSEC_PMK parameter */ ++typedef struct { ++ ushort key_len; /* octets in key material */ ++ ushort flags; /* key handling qualification */ ++ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */ ++} wsec_pmk_t; ++ ++/* wireless security bitvec */ ++#define WEP_ENABLED 0x0001 ++#define TKIP_ENABLED 0x0002 ++#define AES_ENABLED 0x0004 ++#define WSEC_SWFLAG 0x0008 ++#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ ++ ++/* wsec macros for operating on the above definitions */ ++#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED) ++#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) ++#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) ++ ++#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) ++ ++#ifdef MFP ++#define MFP_CAPABLE 0x0200 ++#define MFP_REQUIRED 0x0400 ++#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ ++#endif /* MFP */ ++ ++/* WPA authentication mode bitvec */ ++#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ ++#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ ++#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ ++#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ ++/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ ++#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ ++#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ ++#define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ ++#define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ ++#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ ++#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ ++#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++/* pmkid */ ++#define MAXPMKID 16 ++ ++typedef struct _pmkid { ++ struct ether_addr BSSID; ++ uint8 PMKID[WPA2_PMKID_LEN]; ++} pmkid_t; ++ ++typedef struct _pmkid_list { ++ uint32 npmkid; ++ pmkid_t pmkid[1]; ++} pmkid_list_t; ++ ++typedef struct _pmkid_cand { ++ struct ether_addr BSSID; ++ uint8 preauth; ++} pmkid_cand_t; ++ ++typedef struct _pmkid_cand_list { ++ uint32 npmkid_cand; ++ pmkid_cand_t pmkid_cand[1]; ++} pmkid_cand_list_t; ++ ++typedef struct wl_assoc_info { ++ uint32 req_len; ++ uint32 resp_len; ++ uint32 flags; ++ struct dot11_assoc_req req; ++ struct ether_addr reassoc_bssid; /* used in reassoc's */ ++ struct dot11_assoc_resp resp; ++} wl_assoc_info_t; ++ ++/* flags */ ++#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct wl_led_info { ++ uint32 index; /* led index */ ++ uint32 behavior; ++ uint8 activehi; ++} wl_led_info_t; ++ ++ ++/* srom read/write struct passed through ioctl */ ++typedef struct { ++ uint byteoff; /* byte offset */ ++ uint nbytes; /* number of bytes */ ++ uint16 buf[1]; ++} srom_rw_t; ++ ++/* similar cis (srom or otp) struct [iovar: may not be aligned] */ ++typedef struct { ++ uint32 source; /* cis source */ ++ uint32 byteoff; /* byte offset */ ++ uint32 nbytes; /* number of bytes */ ++ /* data follows here */ ++} cis_rw_t; ++ ++#define WLC_CIS_DEFAULT 0 /* built-in default */ ++#define WLC_CIS_SROM 1 /* source is sprom */ ++#define WLC_CIS_OTP 2 /* source is otp */ ++ ++/* R_REG and W_REG struct passed through ioctl */ ++typedef struct { ++ uint32 byteoff; /* byte offset of the field in d11regs_t */ ++ uint32 val; /* read/write value of the field */ ++ uint32 size; /* sizeof the field */ ++ uint band; /* band (optional) */ ++} rw_reg_t; ++ ++/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ ++/* PCL - Power Control Loop */ ++/* current gain setting is replaced by user input */ ++#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ ++#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ ++/* current gain setting is maintained */ ++#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ ++ ++typedef struct { ++ uint16 auto_ctrl; /* WL_ATTEN_XX */ ++ uint16 bb; /* Baseband attenuation */ ++ uint16 radio; /* Radio attenuation */ ++ uint16 txctl1; /* Radio TX_CTL1 value */ ++} atten_t; ++ ++/* Per-AC retry parameters */ ++struct wme_tx_params_s { ++ uint8 short_retry; ++ uint8 short_fallback; ++ uint8 long_retry; ++ uint8 long_fallback; ++ uint16 max_rate; /* In units of 512 Kbps */ ++}; ++ ++typedef struct wme_tx_params_s wme_tx_params_t; ++ ++#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) ++ ++/* defines used by poweridx iovar - it controls power in a-band */ ++/* current gain setting is maintained */ ++#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ ++#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ ++#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ ++#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ ++/* value >= 0 causes ++ * - input to be set to that value ++ * - PCL to be off ++ */ ++ ++/* Used to get specific link/ac parameters */ ++typedef struct { ++ int ac; ++ uint8 val; ++ struct ether_addr ea; ++} link_val_t; ++ ++#define BCM_MAC_STATUS_INDICATION (0x40010200L) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint16 cap; /* sta's advertised capabilities */ ++ uint32 flags; /* flags defined below */ ++ uint32 idle; /* time since data pkt rx'd from sta */ ++ struct ether_addr ea; /* Station address */ ++ wl_rateset_t rateset; /* rateset in use */ ++ uint32 in; /* seconds elapsed since associated */ ++ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */ ++ uint32 tx_pkts; /* # of packets transmitted */ ++ uint32 tx_failures; /* # of packets failed */ ++ uint32 rx_ucast_pkts; /* # of unicast packets received */ ++ uint32 rx_mcast_pkts; /* # of multicast packets received */ ++ uint32 tx_rate; /* Rate of last successful tx frame */ ++ uint32 rx_rate; /* Rate of last successful rx frame */ ++ uint32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ ++ uint32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */ ++} sta_info_t; ++ ++#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_pkts) ++ ++#define WL_STA_VER 3 ++ ++/* Flags for sta_info_t indicating properties of STA */ ++#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ ++#define WL_STA_WME 0x2 /* WMM association */ ++#define WL_STA_UNUSED 0x4 ++#define WL_STA_AUTHE 0x8 /* Authenticated */ ++#define WL_STA_ASSOC 0x10 /* Associated */ ++#define WL_STA_AUTHO 0x20 /* Authorized */ ++#define WL_STA_WDS 0x40 /* Wireless Distribution System */ ++#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ ++#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ ++#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ ++#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ ++#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ ++#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ ++#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ ++#define WL_STA_SCBSTATS 0x4000 /* Per STA debug stats */ ++ ++#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++/* Used to get specific STA parameters */ ++typedef struct { ++ uint32 val; ++ struct ether_addr ea; ++} scb_val_t; ++ ++/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */ ++typedef struct { ++ uint32 code; ++ scb_val_t ioctl_args; ++} authops_t; ++ ++/* channel encoding */ ++typedef struct channel_info { ++ int hw_channel; ++ int target_channel; ++ int scan_channel; ++} channel_info_t; ++ ++/* For ioctls that take a list of MAC addresses */ ++struct maclist { ++ uint count; /* number of MAC addresses */ ++ struct ether_addr ea[1]; /* variable length array of MAC addresses */ ++}; ++ ++/* get pkt count struct passed through ioctl */ ++typedef struct get_pktcnt { ++ uint rx_good_pkt; ++ uint rx_bad_pkt; ++ uint tx_good_pkt; ++ uint tx_bad_pkt; ++ uint rx_ocast_good_pkt; /* unicast packets destined for others */ ++} get_pktcnt_t; ++ ++/* NINTENDO2 */ ++#define LQ_IDX_MIN 0 ++#define LQ_IDX_MAX 1 ++#define LQ_IDX_AVG 2 ++#define LQ_IDX_SUM 2 ++#define LQ_IDX_LAST 3 ++#define LQ_STOP_MONITOR 0 ++#define LQ_START_MONITOR 1 ++ ++/* Get averages RSSI, Rx PHY rate and SNR values */ ++typedef struct { ++ int rssi[LQ_IDX_LAST]; /* Array to keep min, max, avg rssi */ ++ int snr[LQ_IDX_LAST]; /* Array to keep min, max, avg snr */ ++ int isvalid; /* Flag indicating whether above data is valid */ ++} wl_lq_t; /* Link Quality */ ++ ++typedef enum wl_wakeup_reason_type { ++ LCD_ON = 1, ++ LCD_OFF, ++ DRC1_WAKE, ++ DRC2_WAKE, ++ REASON_LAST ++} wl_wr_type_t; ++ ++typedef struct { ++/* Unique filter id */ ++ uint32 id; ++ ++/* stores the reason for the last wake up */ ++ uint8 reason; ++} wl_wr_t; ++ ++/* Get MAC specific rate histogram command */ ++typedef struct { ++ struct ether_addr ea; /* MAC Address */ ++ uint8 ac_cat; /* Access Category */ ++ uint8 num_pkts; /* Number of packet entries to be averaged */ ++} wl_mac_ratehisto_cmd_t; /* MAC Specific Rate Histogram command */ ++ ++/* Get MAC rate histogram response */ ++typedef struct { ++ uint32 rate[WLC_MAXRATE + 1]; /* Rates */ ++ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ ++ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ ++ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ ++} wl_mac_ratehisto_res_t; /* MAC Specific Rate Histogram Response */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++#define WL_IOCTL_ACTION_GET 0x0 ++#define WL_IOCTL_ACTION_SET 0x1 ++#define WL_IOCTL_ACTION_OVL_IDX_MASK 0x1e ++#define WL_IOCTL_ACTION_OVL_RSV 0x20 ++#define WL_IOCTL_ACTION_OVL 0x40 ++#define WL_IOCTL_ACTION_MASK 0x7e ++#define WL_IOCTL_ACTION_OVL_SHIFT 1 ++ ++/* Linux network driver ioctl encoding */ ++typedef struct wl_ioctl { ++ uint cmd; /* common ioctl definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ uint8 set; /* 1=set IOCTL; 0=query IOCTL */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++} wl_ioctl_t; ++ ++/* reference to wl_ioctl_t struct used by usermode driver */ ++#define ioctl_subtype set /* subtype param */ ++#define ioctl_pid used /* pid param */ ++#define ioctl_status needed /* status param */ ++ ++/* ++ * Structure for passing hardware and software ++ * revision info up from the driver. ++ */ ++typedef struct wlc_rev_info { ++ uint vendorid; /* PCI vendor id */ ++ uint deviceid; /* device id of chip */ ++ uint radiorev; /* radio revision */ ++ uint chiprev; /* chip revision */ ++ uint corerev; /* core revision */ ++ uint boardid; /* board identifier (usu. PCI sub-device id) */ ++ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */ ++ uint boardrev; /* board revision */ ++ uint driverrev; /* driver version */ ++ uint ucoderev; /* microcode version */ ++ uint bus; /* bus type */ ++ uint chipnum; /* chip number */ ++ uint phytype; /* phy type */ ++ uint phyrev; /* phy revision */ ++ uint anarev; /* anacore rev */ ++ uint chippkg; /* chip package info */ ++} wlc_rev_info_t; ++ ++#define WL_REV_INFO_LEGACY_LENGTH 48 ++ ++#define WL_BRAND_MAX 10 ++typedef struct wl_instance_info { ++ uint instance; ++ char brand[WL_BRAND_MAX]; ++} wl_instance_info_t; ++ ++/* structure to change size of tx fifo */ ++typedef struct wl_txfifo_sz { ++ uint16 magic; ++ uint16 fifo; ++ uint16 size; ++} wl_txfifo_sz_t; ++/* magic pattern used for mismatch driver and wl */ ++#define WL_TXFIFO_SZ_MAGIC 0xa5a5 ++ ++/* Transfer info about an IOVar from the driver */ ++/* Max supported IOV name size in bytes, + 1 for nul termination */ ++#define WLC_IOV_NAME_LEN 30 ++typedef struct wlc_iov_trx_s { ++ uint8 module; ++ uint8 type; ++ char name[WLC_IOV_NAME_LEN]; ++} wlc_iov_trx_t; ++ ++/* check this magic number */ ++#define WLC_IOCTL_MAGIC 0x14e46c77 ++ ++/* bump this number if you change the ioctl interface */ ++#ifdef D11AC_IOTYPES ++#define WLC_IOCTL_VERSION 2 ++#define WLC_IOCTL_VERSION_LEGACY_IOTYPES 1 ++#else ++#define WLC_IOCTL_VERSION 1 ++#endif /* D11AC_IOTYPES */ ++ ++#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ ++#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ ++#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ ++#ifdef WLC_HIGH_ONLY ++#define WLC_SAMPLECOLLECT_MAXLEN 1024 /* limit sample size for bmac */ ++#else ++#if defined(LCNCONF) || defined(LCN40CONF) ++#define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */ ++#else ++#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ ++#endif ++#endif /* WLC_HIGH_ONLY */ ++ ++/* common ioctl definitions */ ++#define WLC_GET_MAGIC 0 ++#define WLC_GET_VERSION 1 ++#define WLC_UP 2 ++#define WLC_DOWN 3 ++#define WLC_GET_LOOP 4 ++#define WLC_SET_LOOP 5 ++#define WLC_DUMP 6 ++#define WLC_GET_MSGLEVEL 7 ++#define WLC_SET_MSGLEVEL 8 ++#define WLC_GET_PROMISC 9 ++#define WLC_SET_PROMISC 10 ++/* #define WLC_OVERLAY_IOCTL 11 */ /* not supported */ ++#define WLC_GET_RATE 12 ++#define WLC_GET_MAX_RATE 13 ++#define WLC_GET_INSTANCE 14 ++/* #define WLC_GET_FRAG 15 */ /* no longer supported */ ++/* #define WLC_SET_FRAG 16 */ /* no longer supported */ ++/* #define WLC_GET_RTS 17 */ /* no longer supported */ ++/* #define WLC_SET_RTS 18 */ /* no longer supported */ ++#define WLC_GET_INFRA 19 ++#define WLC_SET_INFRA 20 ++#define WLC_GET_AUTH 21 ++#define WLC_SET_AUTH 22 ++#define WLC_GET_BSSID 23 ++#define WLC_SET_BSSID 24 ++#define WLC_GET_SSID 25 ++#define WLC_SET_SSID 26 ++#define WLC_RESTART 27 ++#define WLC_TERMINATED 28 ++/* #define WLC_DUMP_SCB 28 */ /* no longer supported */ ++#define WLC_GET_CHANNEL 29 ++#define WLC_SET_CHANNEL 30 ++#define WLC_GET_SRL 31 ++#define WLC_SET_SRL 32 ++#define WLC_GET_LRL 33 ++#define WLC_SET_LRL 34 ++#define WLC_GET_PLCPHDR 35 ++#define WLC_SET_PLCPHDR 36 ++#define WLC_GET_RADIO 37 ++#define WLC_SET_RADIO 38 ++#define WLC_GET_PHYTYPE 39 ++#define WLC_DUMP_RATE 40 ++#define WLC_SET_RATE_PARAMS 41 ++#define WLC_GET_FIXRATE 42 ++#define WLC_SET_FIXRATE 43 ++/* #define WLC_GET_WEP 42 */ /* no longer supported */ ++/* #define WLC_SET_WEP 43 */ /* no longer supported */ ++#define WLC_GET_KEY 44 ++#define WLC_SET_KEY 45 ++#define WLC_GET_REGULATORY 46 ++#define WLC_SET_REGULATORY 47 ++#define WLC_GET_PASSIVE_SCAN 48 ++#define WLC_SET_PASSIVE_SCAN 49 ++#define WLC_SCAN 50 ++#define WLC_SCAN_RESULTS 51 ++#define WLC_DISASSOC 52 ++#define WLC_REASSOC 53 ++#define WLC_GET_ROAM_TRIGGER 54 ++#define WLC_SET_ROAM_TRIGGER 55 ++#define WLC_GET_ROAM_DELTA 56 ++#define WLC_SET_ROAM_DELTA 57 ++#define WLC_GET_ROAM_SCAN_PERIOD 58 ++#define WLC_SET_ROAM_SCAN_PERIOD 59 ++#define WLC_EVM 60 /* diag */ ++#define WLC_GET_TXANT 61 ++#define WLC_SET_TXANT 62 ++#define WLC_GET_ANTDIV 63 ++#define WLC_SET_ANTDIV 64 ++/* #define WLC_GET_TXPWR 65 */ /* no longer supported */ ++/* #define WLC_SET_TXPWR 66 */ /* no longer supported */ ++#define WLC_GET_CLOSED 67 ++#define WLC_SET_CLOSED 68 ++#define WLC_GET_MACLIST 69 ++#define WLC_SET_MACLIST 70 ++#define WLC_GET_RATESET 71 ++#define WLC_SET_RATESET 72 ++/* #define WLC_GET_LOCALE 73 */ /* no longer supported */ ++#define WLC_LONGTRAIN 74 ++#define WLC_GET_BCNPRD 75 ++#define WLC_SET_BCNPRD 76 ++#define WLC_GET_DTIMPRD 77 ++#define WLC_SET_DTIMPRD 78 ++#define WLC_GET_SROM 79 ++#define WLC_SET_SROM 80 ++#define WLC_GET_WEP_RESTRICT 81 ++#define WLC_SET_WEP_RESTRICT 82 ++#define WLC_GET_COUNTRY 83 ++#define WLC_SET_COUNTRY 84 ++#define WLC_GET_PM 85 ++#define WLC_SET_PM 86 ++#define WLC_GET_WAKE 87 ++#define WLC_SET_WAKE 88 ++/* #define WLC_GET_D11CNTS 89 */ /* -> "counters" iovar */ ++#define WLC_GET_FORCELINK 90 /* ndis only */ ++#define WLC_SET_FORCELINK 91 /* ndis only */ ++#define WLC_FREQ_ACCURACY 92 /* diag */ ++#define WLC_CARRIER_SUPPRESS 93 /* diag */ ++#define WLC_GET_PHYREG 94 ++#define WLC_SET_PHYREG 95 ++#define WLC_GET_RADIOREG 96 ++#define WLC_SET_RADIOREG 97 ++#define WLC_GET_REVINFO 98 ++#define WLC_GET_UCANTDIV 99 ++#define WLC_SET_UCANTDIV 100 ++#define WLC_R_REG 101 ++#define WLC_W_REG 102 ++/* #define WLC_DIAG_LOOPBACK 103 old tray diag */ ++/* #define WLC_RESET_D11CNTS 104 */ /* -> "reset_d11cnts" iovar */ ++#define WLC_GET_MACMODE 105 ++#define WLC_SET_MACMODE 106 ++#define WLC_GET_MONITOR 107 ++#define WLC_SET_MONITOR 108 ++#define WLC_GET_GMODE 109 ++#define WLC_SET_GMODE 110 ++#define WLC_GET_LEGACY_ERP 111 ++#define WLC_SET_LEGACY_ERP 112 ++#define WLC_GET_RX_ANT 113 ++#define WLC_GET_CURR_RATESET 114 /* current rateset */ ++#define WLC_GET_SCANSUPPRESS 115 ++#define WLC_SET_SCANSUPPRESS 116 ++#define WLC_GET_AP 117 ++#define WLC_SET_AP 118 ++#define WLC_GET_EAP_RESTRICT 119 ++#define WLC_SET_EAP_RESTRICT 120 ++#define WLC_SCB_AUTHORIZE 121 ++#define WLC_SCB_DEAUTHORIZE 122 ++#define WLC_GET_WDSLIST 123 ++#define WLC_SET_WDSLIST 124 ++#define WLC_GET_ATIM 125 ++#define WLC_SET_ATIM 126 ++#define WLC_GET_RSSI 127 ++#define WLC_GET_PHYANTDIV 128 ++#define WLC_SET_PHYANTDIV 129 ++#define WLC_AP_RX_ONLY 130 ++#define WLC_GET_TX_PATH_PWR 131 ++#define WLC_SET_TX_PATH_PWR 132 ++#define WLC_GET_WSEC 133 ++#define WLC_SET_WSEC 134 ++#define WLC_GET_PHY_NOISE 135 ++#define WLC_GET_BSS_INFO 136 ++#define WLC_GET_PKTCNTS 137 ++#define WLC_GET_LAZYWDS 138 ++#define WLC_SET_LAZYWDS 139 ++#define WLC_GET_BANDLIST 140 ++#define WLC_GET_BAND 141 ++#define WLC_SET_BAND 142 ++#define WLC_SCB_DEAUTHENTICATE 143 ++#define WLC_GET_SHORTSLOT 144 ++#define WLC_GET_SHORTSLOT_OVERRIDE 145 ++#define WLC_SET_SHORTSLOT_OVERRIDE 146 ++#define WLC_GET_SHORTSLOT_RESTRICT 147 ++#define WLC_SET_SHORTSLOT_RESTRICT 148 ++#define WLC_GET_GMODE_PROTECTION 149 ++#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 ++#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 ++#define WLC_UPGRADE 152 ++/* #define WLC_GET_MRATE 153 */ /* no longer supported */ ++/* #define WLC_SET_MRATE 154 */ /* no longer supported */ ++#define WLC_GET_IGNORE_BCNS 155 ++#define WLC_SET_IGNORE_BCNS 156 ++#define WLC_GET_SCB_TIMEOUT 157 ++#define WLC_SET_SCB_TIMEOUT 158 ++#define WLC_GET_ASSOCLIST 159 ++#define WLC_GET_CLK 160 ++#define WLC_SET_CLK 161 ++#define WLC_GET_UP 162 ++#define WLC_OUT 163 ++#define WLC_GET_WPA_AUTH 164 ++#define WLC_SET_WPA_AUTH 165 ++#define WLC_GET_UCFLAGS 166 ++#define WLC_SET_UCFLAGS 167 ++#define WLC_GET_PWRIDX 168 ++#define WLC_SET_PWRIDX 169 ++#define WLC_GET_TSSI 170 ++#define WLC_GET_SUP_RATESET_OVERRIDE 171 ++#define WLC_SET_SUP_RATESET_OVERRIDE 172 ++/* #define WLC_SET_FAST_TIMER 173 */ /* no longer supported */ ++/* #define WLC_GET_FAST_TIMER 174 */ /* no longer supported */ ++/* #define WLC_SET_SLOW_TIMER 175 */ /* no longer supported */ ++/* #define WLC_GET_SLOW_TIMER 176 */ /* no longer supported */ ++/* #define WLC_DUMP_PHYREGS 177 */ /* no longer supported */ ++#define WLC_GET_PROTECTION_CONTROL 178 ++#define WLC_SET_PROTECTION_CONTROL 179 ++#define WLC_GET_PHYLIST 180 ++#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */ ++#define WLC_DECRYPT_STATUS 182 /* ndis only */ ++#define WLC_GET_KEY_SEQ 183 ++#define WLC_GET_SCAN_CHANNEL_TIME 184 ++#define WLC_SET_SCAN_CHANNEL_TIME 185 ++#define WLC_GET_SCAN_UNASSOC_TIME 186 ++#define WLC_SET_SCAN_UNASSOC_TIME 187 ++#define WLC_GET_SCAN_HOME_TIME 188 ++#define WLC_SET_SCAN_HOME_TIME 189 ++#define WLC_GET_SCAN_NPROBES 190 ++#define WLC_SET_SCAN_NPROBES 191 ++#define WLC_GET_PRB_RESP_TIMEOUT 192 ++#define WLC_SET_PRB_RESP_TIMEOUT 193 ++#define WLC_GET_ATTEN 194 ++#define WLC_SET_ATTEN 195 ++#define WLC_GET_SHMEM 196 /* diag */ ++#define WLC_SET_SHMEM 197 /* diag */ ++/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */ ++/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */ ++#define WLC_SET_WSEC_TEST 200 ++#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 ++#define WLC_TKIP_COUNTERMEASURES 202 ++#define WLC_GET_PIOMODE 203 ++#define WLC_SET_PIOMODE 204 ++#define WLC_SET_ASSOC_PREFER 205 ++#define WLC_GET_ASSOC_PREFER 206 ++#define WLC_SET_ROAM_PREFER 207 ++#define WLC_GET_ROAM_PREFER 208 ++#define WLC_SET_LED 209 ++#define WLC_GET_LED 210 ++#define WLC_GET_INTERFERENCE_MODE 211 ++#define WLC_SET_INTERFERENCE_MODE 212 ++#define WLC_GET_CHANNEL_QA 213 ++#define WLC_START_CHANNEL_QA 214 ++#define WLC_GET_CHANNEL_SEL 215 ++#define WLC_START_CHANNEL_SEL 216 ++#define WLC_GET_VALID_CHANNELS 217 ++#define WLC_GET_FAKEFRAG 218 ++#define WLC_SET_FAKEFRAG 219 ++#define WLC_GET_PWROUT_PERCENTAGE 220 ++#define WLC_SET_PWROUT_PERCENTAGE 221 ++#define WLC_SET_BAD_FRAME_PREEMPT 222 ++#define WLC_GET_BAD_FRAME_PREEMPT 223 ++#define WLC_SET_LEAP_LIST 224 ++#define WLC_GET_LEAP_LIST 225 ++#define WLC_GET_CWMIN 226 ++#define WLC_SET_CWMIN 227 ++#define WLC_GET_CWMAX 228 ++#define WLC_SET_CWMAX 229 ++#define WLC_GET_WET 230 ++#define WLC_SET_WET 231 ++#define WLC_GET_PUB 232 ++/* #define WLC_SET_GLACIAL_TIMER 233 */ /* no longer supported */ ++/* #define WLC_GET_GLACIAL_TIMER 234 */ /* no longer supported */ ++#define WLC_GET_KEY_PRIMARY 235 ++#define WLC_SET_KEY_PRIMARY 236 ++/* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */ ++#define WLC_GET_ACI_ARGS 238 ++#define WLC_SET_ACI_ARGS 239 ++#define WLC_UNSET_CALLBACK 240 ++#define WLC_SET_CALLBACK 241 ++#define WLC_GET_RADAR 242 ++#define WLC_SET_RADAR 243 ++#define WLC_SET_SPECT_MANAGMENT 244 ++#define WLC_GET_SPECT_MANAGMENT 245 ++#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */ ++#define WLC_WDS_GET_WPA_SUP 247 ++#define WLC_SET_CS_SCAN_TIMER 248 ++#define WLC_GET_CS_SCAN_TIMER 249 ++#define WLC_MEASURE_REQUEST 250 ++#define WLC_INIT 251 ++#define WLC_SEND_QUIET 252 ++#define WLC_KEEPALIVE 253 ++#define WLC_SEND_PWR_CONSTRAINT 254 ++#define WLC_UPGRADE_STATUS 255 ++#define WLC_CURRENT_PWR 256 ++#define WLC_GET_SCAN_PASSIVE_TIME 257 ++#define WLC_SET_SCAN_PASSIVE_TIME 258 ++#define WLC_LEGACY_LINK_BEHAVIOR 259 ++#define WLC_GET_CHANNELS_IN_COUNTRY 260 ++#define WLC_GET_COUNTRY_LIST 261 ++#define WLC_GET_VAR 262 /* get value of named variable */ ++#define WLC_SET_VAR 263 /* set named variable to value */ ++#define WLC_NVRAM_GET 264 /* deprecated */ ++#define WLC_NVRAM_SET 265 ++#define WLC_NVRAM_DUMP 266 ++#define WLC_REBOOT 267 ++#define WLC_SET_WSEC_PMK 268 ++#define WLC_GET_AUTH_MODE 269 ++#define WLC_SET_AUTH_MODE 270 ++#define WLC_GET_WAKEENTRY 271 ++#define WLC_SET_WAKEENTRY 272 ++#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */ ++#define WLC_NVOTPW 274 ++#define WLC_OTPW 275 ++#define WLC_IOV_BLOCK_GET 276 ++#define WLC_IOV_MODULES_GET 277 ++#define WLC_SOFT_RESET 278 ++#define WLC_GET_ALLOW_MODE 279 ++#define WLC_SET_ALLOW_MODE 280 ++#define WLC_GET_DESIRED_BSSID 281 ++#define WLC_SET_DESIRED_BSSID 282 ++#define WLC_DISASSOC_MYAP 283 ++#define WLC_GET_NBANDS 284 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES 285 /* for Dongle EXT_STA support */ ++#define WLC_GET_WLC_BSS_INFO 286 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_INFO 287 /* for Dongle EXT_STA support */ ++#define WLC_GET_OID_PHY 288 /* for Dongle EXT_STA support */ ++#define WLC_SET_OID_PHY 289 /* for Dongle EXT_STA support */ ++#define WLC_SET_ASSOC_TIME 290 /* for Dongle EXT_STA support */ ++#define WLC_GET_DESIRED_SSID 291 /* for Dongle EXT_STA support */ ++#define WLC_GET_CHANSPEC 292 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_STATE 293 /* for Dongle EXT_STA support */ ++#define WLC_SET_PHY_STATE 294 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCAN_PENDING 295 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCANREQ_PENDING 296 /* for Dongle EXT_STA support */ ++#define WLC_GET_PREV_ROAM_REASON 297 /* for Dongle EXT_STA support */ ++#define WLC_SET_PREV_ROAM_REASON 298 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES_PI 299 /* for Dongle EXT_STA support */ ++#define WLC_GET_PHY_STATE 300 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA_RSN 301 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA2_RSN 302 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_BCN_TS 303 /* for Dongle EXT_STA support */ ++#define WLC_GET_INT_DISASSOC 304 /* for Dongle EXT_STA support */ ++#define WLC_SET_NUM_PEERS 305 /* for Dongle EXT_STA support */ ++#define WLC_GET_NUM_BSS 306 /* for Dongle EXT_STA support */ ++#define WLC_PHY_SAMPLE_COLLECT 307 /* phy sample collect mode */ ++/* #define WLC_UM_PRIV 308 */ /* Deprecated: usermode driver */ ++#define WLC_GET_CMD 309 ++/* #define WLC_LAST 310 */ /* Never used - can be reused */ ++#define WLC_SET_INTERFERENCE_OVERRIDE_MODE 311 /* set inter mode override */ ++#define WLC_GET_INTERFERENCE_OVERRIDE_MODE 312 /* get inter mode override */ ++/* #define WLC_GET_WAI_RESTRICT 313 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_RESTRICT 314 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */ ++#define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */ ++#define WLC_GET_NAT_STATE 317 ++#define WLC_LAST 318 ++ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* vx wlc ioctl's offset */ ++#define CMN_IOCTL_OFF 0x180 ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++ ++/* begin 0x1f values beyond the start of the ET driver range. */ ++#define WL_OID_BASE 0xFFE41420 ++ ++/* NDIS overrides */ ++#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) ++#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK) ++#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK) ++#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH) ++#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS) ++#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR) ++#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) ++ ++/* EXT_STA Dongle suuport */ ++#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC) ++#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS) ++#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY) ++#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY) ++#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME) ++#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID) ++#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE) ++#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING) ++#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING) ++#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON) ++#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON) ++#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE) ++#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC) ++#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS) ++#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS) ++ ++/* NAT filter driver support */ ++#define OID_NAT_SET_CONFIG (WL_OID_BASE + WLC_SET_NAT_CONFIG) ++#define OID_NAT_GET_STATE (WL_OID_BASE + WLC_GET_NAT_STATE) ++ ++#define WL_DECRYPT_STATUS_SUCCESS 1 ++#define WL_DECRYPT_STATUS_FAILURE 2 ++#define WL_DECRYPT_STATUS_UNKNOWN 3 ++ ++/* allows user-mode app to poll the status of USB image upgrade */ ++#define WLC_UPGRADE_SUCCESS 0 ++#define WLC_UPGRADE_PENDING 1 ++ ++#ifdef CONFIG_USBRNDIS_RETAIL ++/* struct passed in for WLC_NDCONFIG_ITEM */ ++typedef struct { ++ char *name; ++ void *param; ++} ndconfig_item_t; ++#endif ++ ++ ++/* WLC_GET_AUTH, WLC_SET_AUTH values */ ++#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ ++#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ ++ ++/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ ++#define WL_RADIO_SW_DISABLE (1<<0) ++#define WL_RADIO_HW_DISABLE (1<<1) ++#define WL_RADIO_MPC_DISABLE (1<<2) ++#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ ++ ++#define WL_SPURAVOID_OFF 0 ++#define WL_SPURAVOID_ON1 1 ++#define WL_SPURAVOID_ON2 2 ++ ++/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ ++#define WL_TXPWR_OVERRIDE (1U<<31) ++#define WL_TXPWR_NEG (1U<<30) ++ ++#define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ ++ ++#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */ ++#define WL_PHY_PAVAR_VER 1 /* pavars version */ ++typedef struct wl_pavars2 { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* len of this structure */ ++ uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */ ++ uint16 phy_type; /* phy type */ ++ uint16 bandrange; ++ uint16 chain; ++ uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */ ++} wl_pavars2_t; ++ ++typedef struct wl_po { ++ uint16 phy_type; /* Phy type */ ++ uint16 band; ++ uint16 cckpo; ++ uint32 ofdmpo; ++ uint16 mcspo[8]; ++} wl_po_t; ++ ++/* a large TX Power as an init value to factor out of MIN() calculations, ++ * keep low enough to fit in an int8, units are .25 dBm ++ */ ++#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++/* "diag" iovar argument and error code */ ++#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */ ++#define WL_DIAG_LOOPBACK 2 /* d11 loopback data test */ ++#define WL_DIAG_MEMORY 3 /* d11 memory test */ ++#define WL_DIAG_LED 4 /* LED test */ ++#define WL_DIAG_REG 5 /* d11/phy register test */ ++#define WL_DIAG_SROM 6 /* srom read/crc test */ ++#define WL_DIAG_DMA 7 /* DMA test */ ++#define WL_DIAG_LOOPBACK_EXT 8 /* enhenced d11 loopback data test */ ++ ++#define WL_DIAGERR_SUCCESS 0 ++#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */ ++#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */ ++#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */ ++#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */ ++#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */ ++#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */ ++#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */ ++#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */ ++#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */ ++#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */ ++ ++#define WL_DIAGERR_MEMORY_TIMEOUT 11 /* d11 memory test didn't finish in time */ ++#define WL_DIAGERR_MEMORY_BADPATTERN 12 /* d11 memory test result in bad pattern */ ++ ++/* band types */ ++#define WLC_BAND_AUTO 0 /* auto-select */ ++#define WLC_BAND_5G 1 /* 5 Ghz */ ++#define WLC_BAND_2G 2 /* 2.4 Ghz */ ++#define WLC_BAND_ALL 3 /* all bands */ ++ ++/* band range returned by band_range iovar */ ++#define WL_CHAN_FREQ_RANGE_2G 0 ++#define WL_CHAN_FREQ_RANGE_5GL 1 ++#define WL_CHAN_FREQ_RANGE_5GM 2 ++#define WL_CHAN_FREQ_RANGE_5GH 3 ++ ++#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 ++#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 ++#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 ++#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 ++#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 ++ ++#define WL_CHAN_FREQ_RANGE_5G_BAND0 1 ++#define WL_CHAN_FREQ_RANGE_5G_BAND1 2 ++#define WL_CHAN_FREQ_RANGE_5G_BAND2 3 ++#define WL_CHAN_FREQ_RANGE_5G_BAND3 4 ++ ++#define WL_CHAN_FREQ_RANGE_5G_4BAND 5 ++ ++/* phy types (returned by WLC_GET_PHYTPE) */ ++#define WLC_PHY_TYPE_A 0 ++#define WLC_PHY_TYPE_B 1 ++#define WLC_PHY_TYPE_G 2 ++#define WLC_PHY_TYPE_N 4 ++#define WLC_PHY_TYPE_LP 5 ++#define WLC_PHY_TYPE_SSN 6 ++#define WLC_PHY_TYPE_HT 7 ++#define WLC_PHY_TYPE_LCN 8 ++#define WLC_PHY_TYPE_LCN40 10 ++#define WLC_PHY_TYPE_AC 11 ++#define WLC_PHY_TYPE_NULL 0xf ++ ++/* MAC list modes */ ++#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */ ++#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */ ++#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */ ++ ++/* ++ * 54g modes (basic bits may still be overridden) ++ * ++ * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11 ++ * Preamble: Long ++ * Shortslot: Off ++ * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: Auto ++ * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 ++ * Extended Rateset: 6b, 9, 12b, 48 ++ * Preamble: Short required ++ * Shortslot: Auto ++ * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: On ++ * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 ++ * Preamble: Short required ++ * Shortslot: On and required ++ * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b ++ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 ++ * Preamble: Long ++ * Shortslot: Auto ++ */ ++#define GMODE_LEGACY_B 0 ++#define GMODE_AUTO 1 ++#define GMODE_ONLY 2 ++#define GMODE_B_DEFERRED 3 ++#define GMODE_PERFORMANCE 4 ++#define GMODE_LRS 5 ++#define GMODE_MAX 6 ++ ++/* values for PLCPHdr_override */ ++#define WLC_PLCP_AUTO -1 ++#define WLC_PLCP_SHORT 0 ++#define WLC_PLCP_LONG 1 ++ ++/* values for g_protection_override and n_protection_override */ ++#define WLC_PROTECTION_AUTO -1 ++#define WLC_PROTECTION_OFF 0 ++#define WLC_PROTECTION_ON 1 ++#define WLC_PROTECTION_MMHDR_ONLY 2 ++#define WLC_PROTECTION_CTS_ONLY 3 ++ ++/* values for g_protection_control and n_protection_control */ ++#define WLC_PROTECTION_CTL_OFF 0 ++#define WLC_PROTECTION_CTL_LOCAL 1 ++#define WLC_PROTECTION_CTL_OVERLAP 2 ++ ++/* values for n_protection */ ++#define WLC_N_PROTECTION_OFF 0 ++#define WLC_N_PROTECTION_OPTIONAL 1 ++#define WLC_N_PROTECTION_20IN40 2 ++#define WLC_N_PROTECTION_MIXEDMODE 3 ++ ++/* values for n_preamble_type */ ++#define WLC_N_PREAMBLE_MIXEDMODE 0 ++#define WLC_N_PREAMBLE_GF 1 ++#define WLC_N_PREAMBLE_GF_BRCM 2 ++ ++/* values for band specific 40MHz capabilities (deprecated) */ ++#define WLC_N_BW_20ALL 0 ++#define WLC_N_BW_40ALL 1 ++#define WLC_N_BW_20IN2G_40IN5G 2 ++ ++#define WLC_BW_20MHZ_BIT (1<<0) ++#define WLC_BW_40MHZ_BIT (1<<1) ++#define WLC_BW_80MHZ_BIT (1<<2) ++ ++/* Bandwidth capabilities */ ++#define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_UNRESTRICTED 0xFF ++ ++#define WL_BW_CAP_20MHZ(bw_cap) (((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_40MHZ(bw_cap) (((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_80MHZ(bw_cap) (((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE) ++ ++/* values to force tx/rx chain */ ++#define WLC_N_TXRX_CHAIN0 0 ++#define WLC_N_TXRX_CHAIN1 1 ++ ++/* bitflags for SGI support (sgi_rx iovar) */ ++#define WLC_N_SGI_20 0x01 ++#define WLC_N_SGI_40 0x02 ++ ++/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ ++#define WLC_SGI_ALL 0x02 ++ ++/* Values for PM */ ++#define PM_OFF 0 ++#define PM_MAX 1 ++#define PM_FAST 2 ++#define PM_FORCE_OFF 3 /* use this bit to force PM off even bt is active */ ++ ++#define LISTEN_INTERVAL 10 ++/* interference mitigation options */ ++#define INTERFERE_OVRRIDE_OFF -1 /* interference override off */ ++#define INTERFERE_NONE 0 /* off */ ++#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */ ++#define WLAN_MANUAL 2 /* ACI: no auto detection */ ++#define WLAN_AUTO 3 /* ACI: auto detect */ ++#define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */ ++#define AUTO_ACTIVE (1 << 7) /* Auto is currently active */ ++ ++typedef struct wl_aci_args { ++ int enter_aci_thresh; /* Trigger level to start detecting ACI */ ++ int exit_aci_thresh; /* Trigger level to exit ACI mode */ ++ int usec_spin; /* microsecs to delay between rssi samples */ ++ int glitch_delay; /* interval between ACI scans when glitch count is consistently high */ ++ uint16 nphy_adcpwr_enter_thresh; /* ADC power to enter ACI mitigation mode */ ++ uint16 nphy_adcpwr_exit_thresh; /* ADC power to exit ACI mitigation mode */ ++ uint16 nphy_repeat_ctr; /* Number of tries per channel to compute power */ ++ uint16 nphy_num_samples; /* Number of samples to compute power on one channel */ ++ uint16 nphy_undetect_window_sz; /* num of undetects to exit ACI Mitigation mode */ ++ uint16 nphy_b_energy_lo_aci; /* low ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_md_aci; /* mid ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_hi_aci; /* high ACI power energy threshold for bphy */ ++ uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */ ++ uint16 nphy_noise_noassoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_glitch_th_up; ++ uint16 nphy_noise_assoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_aci_glitch_th_up; ++ uint16 nphy_noise_assoc_aci_glitch_th_dn; ++ uint16 nphy_noise_assoc_enter_th; ++ uint16 nphy_noise_noassoc_enter_th; ++ uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th; ++ uint16 nphy_noise_noassoc_crsidx_incr; ++ uint16 nphy_noise_assoc_crsidx_incr; ++ uint16 nphy_noise_crsidx_decr; ++} wl_aci_args_t; ++ ++#define TRIGGER_NOW 0 ++#define TRIGGER_CRS 0x01 ++#define TRIGGER_CRSDEASSERT 0x02 ++#define TRIGGER_GOODFCS 0x04 ++#define TRIGGER_BADFCS 0x08 ++#define TRIGGER_BADPLCP 0x10 ++#define TRIGGER_CRSGLITCH 0x20 ++#define WL_ACI_ARGS_LEGACY_LENGTH 16 /* bytes of pre NPHY aci args */ ++#define WL_SAMPLECOLLECT_T_VERSION 2 /* version of wl_samplecollect_args_t struct */ ++typedef struct wl_samplecollect_args { ++ /* version 0 fields */ ++ uint8 coll_us; ++ int cores; ++ /* add'l version 1 fields */ ++ uint16 version; /* see definition of WL_SAMPLECOLLECT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ int8 trigger; ++ uint16 timeout; ++ uint16 mode; ++ uint32 pre_dur; ++ uint32 post_dur; ++ uint8 gpio_sel; ++ bool downsamp; ++ bool be_deaf; ++ bool agc; /* loop from init gain and going down */ ++ bool filter; /* override high pass corners to lowest */ ++ /* add'l version 2 fields */ ++ uint8 trigger_state; ++ uint8 module_sel1; ++ uint8 module_sel2; ++ uint16 nsamps; ++} wl_samplecollect_args_t; ++ ++#define WL_SAMPLEDATA_HEADER_TYPE 1 ++#define WL_SAMPLEDATA_HEADER_SIZE 80 /* sample collect header size (bytes) */ ++#define WL_SAMPLEDATA_TYPE 2 ++#define WL_SAMPLEDATA_SEQ 0xff /* sequence # */ ++#define WL_SAMPLEDATA_MORE_DATA 0x100 /* more data mask */ ++#define WL_SAMPLEDATA_T_VERSION 1 /* version of wl_samplecollect_args_t struct */ ++/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */ ++#define WL_SAMPLEDATA_T_VERSION_SPEC_AN 2 ++ ++typedef struct wl_sampledata { ++ uint16 version; /* structure version */ ++ uint16 size; /* size of structure */ ++ uint16 tag; /* Header/Data */ ++ uint16 length; /* data length */ ++ uint32 flag; /* bit def */ ++} wl_sampledata_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* wl_radar_args_t */ ++typedef struct { ++ int npulses; /* required number of pulses at n * t_int */ ++ int ncontig; /* required number of pulses at t_int */ ++ int min_pw; /* minimum pulse width (20 MHz clocks) */ ++ int max_pw; /* maximum pulse width (20 MHz clocks) */ ++ uint16 thresh0; /* Radar detection, thresh 0 */ ++ uint16 thresh1; /* Radar detection, thresh 1 */ ++ uint16 blank; /* Radar detection, blank control */ ++ uint16 fmdemodcfg; /* Radar detection, fmdemod config */ ++ int npulses_lp; /* Radar detection, minimum long pulses */ ++ int min_pw_lp; /* Minimum pulsewidth for long pulses */ ++ int max_pw_lp; /* Maximum pulsewidth for long pulses */ ++ int min_fm_lp; /* Minimum fm for long pulses */ ++ int max_span_lp; /* Maximum deltat for long pulses */ ++ int min_deltat; /* Minimum spacing between pulses */ ++ int max_deltat; /* Maximum spacing between pulses */ ++ uint16 autocorr; /* Radar detection, autocorr on or off */ ++ uint16 st_level_time; /* Radar detection, start_timing level */ ++ uint16 t2_min; /* minimum clocks needed to remain in state 2 */ ++ uint32 version; /* version */ ++ uint32 fra_pulse_err; /* sample error margin for detecting French radar pulsed */ ++ int npulses_fra; /* Radar detection, minimum French pulses set */ ++ int npulses_stg2; /* Radar detection, minimum staggered-2 pulses set */ ++ int npulses_stg3; /* Radar detection, minimum staggered-3 pulses set */ ++ uint16 percal_mask; /* defines which period cal is masked from radar detection */ ++ int quant; /* quantization resolution to pulse positions */ ++ uint32 min_burst_intv_lp; /* minimum burst to burst interval for bin3 radar */ ++ uint32 max_burst_intv_lp; /* maximum burst to burst interval for bin3 radar */ ++ int nskip_rst_lp; /* number of skipped pulses before resetting lp buffer */ ++ int max_pw_tol; /* maximum tollerance allowed in detected pulse width for radar detection */ ++ uint16 feature_mask; /* 16-bit mask to specify enabled features */ ++} wl_radar_args_t; ++ ++#define WL_RADAR_ARGS_VERSION 2 ++ ++typedef struct { ++ uint32 version; /* version */ ++ uint16 thresh0_20_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh1_20_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh0_40_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh1_40_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh0_80_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh1_80_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh0_160_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh1_160_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh0_20_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh1_20_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh0_40_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh1_40_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh0_80_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh1_80_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh0_160_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */ ++ uint16 thresh1_160_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */ ++} wl_radar_thr_t; ++ ++#define WL_RADAR_THR_VERSION 2 ++#define WL_THRESHOLD_LO_BAND 70 /* range from 5250MHz - 5350MHz */ ++ ++/* radar iovar SET defines */ ++#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */ ++#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */ ++#define WL_RADAR_SIMULATED 2 /* force radar detector to declare ++ * detection once ++ */ ++#define WL_RSSI_ANT_VERSION 1 /* current version of wl_rssi_ant_t */ ++#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ ++#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ ++#define WL_ANT_IDX_1 0 /* antenna index 1 */ ++#define WL_ANT_IDX_2 1 /* antenna index 2 */ ++ ++#ifndef WL_RSSI_ANT_MAX ++#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ ++#elif WL_RSSI_ANT_MAX != 4 ++#error "WL_RSSI_ANT_MAX does not match" ++#endif ++ ++/* RSSI per antenna */ ++typedef struct { ++ uint32 version; /* version field */ ++ uint32 count; /* number of valid antenna rssi */ ++ int8 rssi_ant[WL_RSSI_ANT_MAX]; /* rssi per antenna */ ++} wl_rssi_ant_t; ++ ++/* dfs_status iovar-related defines */ ++ ++/* cac - channel availability check, ++ * ism - in-service monitoring ++ * csa - channel switching announcement ++ */ ++ ++/* cac state values */ ++#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */ ++#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */ ++#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */ ++#define WL_DFS_CACSTATE_CSA 3 /* csa */ ++#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */ ++#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */ ++#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */ ++#define WL_DFS_CACSTATES 7 /* this many states exist */ ++ ++/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */ ++typedef struct { ++ uint state; /* noted by WL_DFS_CACSTATE_XX. */ ++ uint duration; /* time spent in ms in state. */ ++ /* as dfs enters ISM state, it removes the operational channel from quiet channel ++ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared ++ */ ++ chanspec_t chanspec_cleared; ++ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */ ++ uint16 pad; ++} wl_dfs_status_t; ++ ++#define NUM_PWRCTRL_RATES 12 ++ ++typedef struct { ++ uint8 txpwr_band_max[NUM_PWRCTRL_RATES]; /* User set target */ ++ uint8 txpwr_limit[NUM_PWRCTRL_RATES]; /* reg and local power limit */ ++ uint8 txpwr_local_max; /* local max according to the AP */ ++ uint8 txpwr_local_constraint; /* local constraint according to the AP */ ++ uint8 txpwr_chan_reg_max; /* Regulatory max for this channel */ ++ uint8 txpwr_target[2][NUM_PWRCTRL_RATES]; /* Latest target for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_opo[NUM_PWRCTRL_RATES]; /* On G phy, OFDM power offset */ ++ uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; /* Max CCK power for this band (SROM) */ ++ uint8 txpwr_bphy_ofdm_max; /* Max OFDM power for this band (SROM) */ ++ uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES]; /* Max power for A band (SROM) */ ++ int8 txpwr_antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_power_legacy_t; ++ ++#define WL_TX_POWER_RATES_LEGACY 45 ++#define WL_TX_POWER_MCS20_FIRST 12 ++#define WL_TX_POWER_MCS20_NUM 16 ++#define WL_TX_POWER_MCS40_FIRST 28 ++#define WL_TX_POWER_MCS40_NUM 17 ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF ++ * chain without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */ ++ uint8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */ ++ uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */ ++ uint8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */ ++} tx_power_legacy2_t; ++ ++/* TX Power index defines */ ++#define WL_NUM_RATES_CCK 4 /* 1, 2, 5.5, 11 Mbps */ ++#define WL_NUM_RATES_OFDM 8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */ ++#define WL_NUM_RATES_MCS_1STREAM 8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */ ++#define WL_NUM_RATES_EXTRA_VHT 2 /* Additional VHT 11AC rates */ ++#define WL_NUM_RATES_VHT 10 ++#define WL_NUM_RATES_MCS32 1 ++ ++#define WLC_NUM_RATES_CCK WL_NUM_RATES_CCK ++#define WLC_NUM_RATES_OFDM WL_NUM_RATES_OFDM ++#define WLC_NUM_RATES_MCS_1_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS_2_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS32 WL_NUM_RATES_MCS32 ++#define WL_TX_POWER_CCK_NUM WL_NUM_RATES_CCK ++#define WL_TX_POWER_OFDM_NUM WL_NUM_RATES_OFDM ++#define WL_TX_POWER_MCS_1_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_2_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_32_NUM WL_NUM_RATES_MCS32 ++ ++#define WL_NUM_2x2_ELEMENTS 4 ++#define WL_NUM_3x3_ELEMENTS 6 ++ ++typedef struct txppr { ++ /* start of 20MHz tx power limits */ ++ uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40MHz tx power limits */ ++ uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in40MHz tx power limits */ ++ uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ ++ uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 80MHz tx power limits */ ++ uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in80MHz tx power limits */ ++ uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40in80MHz tx power limits */ ++ uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ ++ uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ ++} txppr_t; ++ ++/* 20MHz */ ++#define WL_TX_POWER_CCK_FIRST OFFSETOF(txppr_t, b20_1x1dsss) ++#define WL_TX_POWER_OFDM20_FIRST OFFSETOF(txppr_t, b20_1x1ofdm) ++#define WL_TX_POWER_MCS20_SISO_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++#define WL_TX_POWER_20_S1x1_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2dsss) ++#define WL_TX_POWER_OFDM20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_20_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS20_STBC_FIRST OFFSETOF(txppr_t, b20_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS20_SDM_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++#define WL_TX_POWER_20_S2x2_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3dsss) ++#define WL_TX_POWER_OFDM20_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_ofdm) ++#define WL_TX_POWER_20_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_mcs0) ++#define WL_TX_POWER_20_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3stbc_mcs0) ++#define WL_TX_POWER_20_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3sdm_mcs8) ++#define WL_TX_POWER_20_S3x3_FIRST OFFSETOF(txppr_t, b20_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20_S1X1_VHT OFFSETOF(txppr_t, b20_1x1vht) ++#define WL_TX_POWER_20_S1X2_CDD_VHT OFFSETOF(txppr_t, b20_1x2cdd_vht) ++#define WL_TX_POWER_20_S2X2_STBC_VHT OFFSETOF(txppr_t, b20_2x2stbc_vht) ++#define WL_TX_POWER_20_S2X2_VHT OFFSETOF(txppr_t, b20_2x2sdm_vht) ++#define WL_TX_POWER_20_S1X3_CDD_VHT OFFSETOF(txppr_t, b20_1x3cdd_vht) ++#define WL_TX_POWER_20_S2X3_STBC_VHT OFFSETOF(txppr_t, b20_2x3stbc_vht) ++#define WL_TX_POWER_20_S2X3_VHT OFFSETOF(txppr_t, b20_2x3sdm_vht) ++#define WL_TX_POWER_20_S3X3_VHT OFFSETOF(txppr_t, b20_3x3sdm_vht) ++ ++/* 40MHz */ ++#define WL_TX_POWER_40_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40_dummy1x1dsss) ++#define WL_TX_POWER_OFDM40_FIRST OFFSETOF(txppr_t, b40_1x1ofdm) ++#define WL_TX_POWER_MCS40_SISO_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++#define WL_TX_POWER_40_S1x1_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40_dummy1x2dsss) ++#define WL_TX_POWER_OFDM40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_40_S1x2_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS40_STBC_FIRST OFFSETOF(txppr_t, b40_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS40_SDM_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++#define WL_TX_POWER_40_S2x2_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_dummy1x3dsss) ++#define WL_TX_POWER_OFDM40_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_ofdm) ++#define WL_TX_POWER_40_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_mcs0) ++#define WL_TX_POWER_40_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3stbc_mcs0) ++#define WL_TX_POWER_40_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3sdm_mcs8) ++#define WL_TX_POWER_40_S3x3_FIRST OFFSETOF(txppr_t, b40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40_S1X1_VHT OFFSETOF(txppr_t, b40_1x1vht) ++#define WL_TX_POWER_40_S1X2_CDD_VHT OFFSETOF(txppr_t, b40_1x2cdd_vht) ++#define WL_TX_POWER_40_S2X2_STBC_VHT OFFSETOF(txppr_t, b40_2x2stbc_vht) ++#define WL_TX_POWER_40_S2X2_VHT OFFSETOF(txppr_t, b40_2x2sdm_vht) ++#define WL_TX_POWER_40_S1X3_CDD_VHT OFFSETOF(txppr_t, b40_1x3cdd_vht) ++#define WL_TX_POWER_40_S2X3_STBC_VHT OFFSETOF(txppr_t, b40_2x3stbc_vht) ++#define WL_TX_POWER_40_S2X3_VHT OFFSETOF(txppr_t, b40_2x3sdm_vht) ++#define WL_TX_POWER_40_S3X3_VHT OFFSETOF(txppr_t, b40_3x3sdm_vht) ++ ++/* 20 in 40MHz */ ++#define WL_TX_POWER_20UL_CCK_FIRST OFFSETOF(txppr_t, b20in40_1x1dsss) ++#define WL_TX_POWER_20UL_OFDM_FIRST OFFSETOF(txppr_t, b20in40_1x1ofdm) ++#define WL_TX_POWER_20UL_S1x1_FIRST OFFSETOF(txppr_t, b20in40_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3sdm_mcs8) ++#define WL_TX_POWER_20UL_S3x3_FIRST OFFSETOF(txppr_t, b20in40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UL_S1X1_VHT OFFSETOF(txppr_t, b20in40_1x1vht) ++#define WL_TX_POWER_20UL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in40_1x2cdd_vht) ++#define WL_TX_POWER_20UL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in40_2x2stbc_vht) ++#define WL_TX_POWER_20UL_S2X2_VHT OFFSETOF(txppr_t, b20in40_2x2sdm_vht) ++#define WL_TX_POWER_20UL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in40_1x3cdd_vht) ++#define WL_TX_POWER_20UL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in40_2x3stbc_vht) ++#define WL_TX_POWER_20UL_S2X3_VHT OFFSETOF(txppr_t, b20in40_2x3sdm_vht) ++#define WL_TX_POWER_20UL_S3X3_VHT OFFSETOF(txppr_t, b20in40_3x3sdm_vht) ++ ++/* 80MHz */ ++#define WL_TX_POWER_80_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b80_dummy1x1dsss) ++#define WL_TX_POWER_OFDM80_FIRST OFFSETOF(txppr_t, b80_1x1ofdm) ++#define WL_TX_POWER_MCS80_SISO_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++#define WL_TX_POWER_80_S1x1_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b80_dummy1x2dsss) ++#define WL_TX_POWER_OFDM80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_80_S1x2_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS80_STBC_FIRST OFFSETOF(txppr_t, b80_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS80_SDM_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++#define WL_TX_POWER_80_S2x2_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_dummy1x3dsss) ++#define WL_TX_POWER_OFDM80_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_ofdm) ++#define WL_TX_POWER_80_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_mcs0) ++#define WL_TX_POWER_80_STBC_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3stbc_mcs0) ++#define WL_TX_POWER_80_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3sdm_mcs8) ++#define WL_TX_POWER_80_S3x3_FIRST OFFSETOF(txppr_t, b80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_80_S1X1_VHT OFFSETOF(txppr_t, b80_1x1vht) ++#define WL_TX_POWER_80_S1X2_CDD_VHT OFFSETOF(txppr_t, b80_1x2cdd_vht) ++#define WL_TX_POWER_80_S2X2_STBC_VHT OFFSETOF(txppr_t, b80_2x2stbc_vht) ++#define WL_TX_POWER_80_S2X2_VHT OFFSETOF(txppr_t, b80_2x2sdm_vht) ++#define WL_TX_POWER_80_S1X3_CDD_VHT OFFSETOF(txppr_t, b80_1x3cdd_vht) ++#define WL_TX_POWER_80_S2X3_STBC_VHT OFFSETOF(txppr_t, b80_2x3stbc_vht) ++#define WL_TX_POWER_80_S2X3_VHT OFFSETOF(txppr_t, b80_2x3sdm_vht) ++#define WL_TX_POWER_80_S3X3_VHT OFFSETOF(txppr_t, b80_3x3sdm_vht) ++ ++/* 20 in 80MHz */ ++#define WL_TX_POWER_20UUL_CCK_FIRST OFFSETOF(txppr_t, b20in80_1x1dsss) ++#define WL_TX_POWER_20UUL_OFDM_FIRST OFFSETOF(txppr_t, b20in80_1x1ofdm) ++#define WL_TX_POWER_20UUL_S1x1_FIRST OFFSETOF(txppr_t, b20in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3sdm_mcs8) ++#define WL_TX_POWER_20UUL_S3x3_FIRST OFFSETOF(txppr_t, b20in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UUL_S1X1_VHT OFFSETOF(txppr_t, b20in80_1x1vht) ++#define WL_TX_POWER_20UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in80_1x2cdd_vht) ++#define WL_TX_POWER_20UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in80_2x2stbc_vht) ++#define WL_TX_POWER_20UUL_S2X2_VHT OFFSETOF(txppr_t, b20in80_2x2sdm_vht) ++#define WL_TX_POWER_20UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in80_1x3cdd_vht) ++#define WL_TX_POWER_20UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in80_2x3stbc_vht) ++#define WL_TX_POWER_20UUL_S2X3_VHT OFFSETOF(txppr_t, b20in80_2x3sdm_vht) ++#define WL_TX_POWER_20UUL_S3X3_VHT OFFSETOF(txppr_t, b20in80_3x3sdm_vht) ++ ++/* 40 in 80MHz */ ++#define WL_TX_POWER_40UUL_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40in80_dummy1x1dsss) ++#define WL_TX_POWER_40UUL_OFDM_FIRST OFFSETOF(txppr_t, b40in80_1x1ofdm) ++#define WL_TX_POWER_40UUL_S1x1_FIRST OFFSETOF(txppr_t, b40in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40in80_dummy1x2dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x2_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_dummy1x3dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3sdm_mcs8) ++#define WL_TX_POWER_40UUL_S3x3_FIRST OFFSETOF(txppr_t, b40in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40UUL_S1X1_VHT OFFSETOF(txppr_t, b40in80_1x1vht) ++#define WL_TX_POWER_40UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b40in80_1x2cdd_vht) ++#define WL_TX_POWER_40UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b40in80_2x2stbc_vht) ++#define WL_TX_POWER_40UUL_S2X2_VHT OFFSETOF(txppr_t, b40in80_2x2sdm_vht) ++#define WL_TX_POWER_40UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b40in80_1x3cdd_vht) ++#define WL_TX_POWER_40UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b40in80_2x3stbc_vht) ++#define WL_TX_POWER_40UUL_S2X3_VHT OFFSETOF(txppr_t, b40in80_2x3sdm_vht) ++#define WL_TX_POWER_40UUL_S3X3_VHT OFFSETOF(txppr_t, b40in80_3x3sdm_vht) ++ ++#define WL_TX_POWER_MCS_32 OFFSETOF(txppr_t, mcs32) /* C_CHECK remove later */ ++ ++#define WL_TX_POWER_RATES sizeof(struct txppr) ++ ++/* sslpnphy specifics */ ++#define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST ++#define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ ++} wl_txppr_t; ++ ++#define WL_TXPPR_VERSION 0 ++#define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) ++#define TX_POWER_T_VERSION 43 ++ ++/* Defines used with channel_bandwidth for curpower */ ++#define WL_BW_20MHZ 0 ++#define WL_BW_40MHZ 1 ++#define WL_BW_80MHZ 2 ++ ++/* tx_power_t.flags bits */ ++#ifdef PPR_API ++#define WL_TX_POWER2_F_ENABLED 1 ++#define WL_TX_POWER2_F_HW 2 ++#define WL_TX_POWER2_F_MIMO 4 ++#define WL_TX_POWER2_F_SISO 8 ++#define WL_TX_POWER2_F_HT 0x10 ++#else ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++#define WL_TX_POWER_F_HT 0x10 ++#endif ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ uint8 user_limit[WL_TX_POWER_RATES]; /* User limit */ ++ int8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */ ++ int8 target[WL_TX_POWER_RATES]; /* Latest target power */ ++ int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ ++ int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ ++ int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ ++ int8 sar; /* SAR limit for display by wl executable */ ++ int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ ++ uint8 version; /* Version of the data format wlu <--> driver */ ++ uint8 display_core; /* Displayed curpower core */ ++#ifdef PPR_API ++} tx_power_new_t; ++#else ++} tx_power_t; ++#endif ++ ++typedef struct tx_inst_power { ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_inst_power_t; ++ ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ txppr_t user_limit; /* User limit */ ++ txppr_t reg_limit; /* Regulatory power limit */ ++ txppr_t board_limit; /* Max power board can support (SROM) */ ++ txppr_t target; /* Latest target power */ ++} wl_txpwr_t; ++ ++#define WL_NUM_TXCHAIN_MAX 4 ++typedef struct wl_txchain_pwr_offsets { ++ int8 offset[WL_NUM_TXCHAIN_MAX]; /* quarter dBm signed offset for each chain */ ++} wl_txchain_pwr_offsets_t; ++ ++/* 802.11h measurement types */ ++#define WLC_MEASURE_TPC 1 ++#define WLC_MEASURE_CHANNEL_BASIC 2 ++#define WLC_MEASURE_CHANNEL_CCA 3 ++#define WLC_MEASURE_CHANNEL_RPI 4 ++ ++/* regulatory enforcement levels */ ++#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */ ++#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */ ++#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */ ++#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */ ++/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE ++ * adoption is done regardless of capability spectrum_management ++ */ ++#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */ ++ ++#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ ++#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */ ++#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ ++#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ ++#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */ ++#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */ ++#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ ++ ++/* BTC mode used by "btc_mode" iovar */ ++#define WL_BTC_DISABLE 0 /* disable BT coexistence */ ++#define WL_BTC_FULLTDM 1 /* full TDM COEX */ ++#define WL_BTC_ENABLE 1 /* full TDM COEX to maintain backward compatiblity */ ++#define WL_BTC_PREMPT 2 /* full TDM COEX with preemption */ ++#define WL_BTC_LITE 3 /* light weight coex for large isolation platform */ ++#define WL_BTC_PARALLEL 4 /* BT and WLAN run in parallel with separate antenna */ ++#define WL_BTC_HYBRID 5 /* hybrid coex, only ack is allowed to transmit in BT slot */ ++#define WL_BTC_DEFAULT 8 /* set the default mode for the device */ ++#define WL_INF_BTC_DISABLE 0 ++#define WL_INF_BTC_ENABLE 1 ++#define WL_INF_BTC_AUTO 3 ++ ++/* BTC wire used by "btc_wire" iovar */ ++#define WL_BTC_DEFWIRE 0 /* use default wire setting */ ++#define WL_BTC_2WIRE 2 /* use 2-wire BTC */ ++#define WL_BTC_3WIRE 3 /* use 3-wire BTC */ ++#define WL_BTC_4WIRE 4 /* use 4-wire BTC */ ++ ++/* BTC flags: BTC configuration that can be set by host */ ++#define WL_BTC_FLAG_PREMPT (1 << 0) ++#define WL_BTC_FLAG_BT_DEF (1 << 1) ++#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2) ++#define WL_BTC_FLAG_SIM_RSP (1 << 3) ++#define WL_BTC_FLAG_PS_PROTECT (1 << 4) ++#define WL_BTC_FLAG_SIM_TX_LP (1 << 5) ++#define WL_BTC_FLAG_ECI (1 << 6) ++#define WL_BTC_FLAG_LIGHT (1 << 7) ++#define WL_BTC_FLAG_PARALLEL (1 << 8) ++#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */ ++ ++/* Message levels */ ++#define WL_ERROR_VAL 0x00000001 ++#define WL_TRACE_VAL 0x00000002 ++#define WL_PRHDRS_VAL 0x00000004 ++#define WL_PRPKT_VAL 0x00000008 ++#define WL_INFORM_VAL 0x00000010 ++#define WL_TMP_VAL 0x00000020 ++#define WL_OID_VAL 0x00000040 ++#define WL_RATE_VAL 0x00000080 ++#define WL_ASSOC_VAL 0x00000100 ++#define WL_PRUSR_VAL 0x00000200 ++#define WL_PS_VAL 0x00000400 ++#define WL_TXPWR_VAL 0x00000800 /* retired in TOT on 6/10/2009 */ ++#define WL_PORT_VAL 0x00001000 ++#define WL_DUAL_VAL 0x00002000 ++#define WL_WSEC_VAL 0x00004000 ++#define WL_WSEC_DUMP_VAL 0x00008000 ++#define WL_LOG_VAL 0x00010000 ++#define WL_NRSSI_VAL 0x00020000 /* retired in TOT on 6/10/2009 */ ++#define WL_LOFT_VAL 0x00040000 /* retired in TOT on 6/10/2009 */ ++#define WL_REGULATORY_VAL 0x00080000 ++#define WL_PHYCAL_VAL 0x00100000 /* retired in TOT on 6/10/2009 */ ++#define WL_RADAR_VAL 0x00200000 /* retired in TOT on 6/10/2009 */ ++#define WL_MPC_VAL 0x00400000 ++#define WL_APSTA_VAL 0x00800000 ++#define WL_DFS_VAL 0x01000000 ++#define WL_BA_VAL 0x02000000 /* retired in TOT on 6/14/2010 */ ++#define WL_ACI_VAL 0x04000000 ++#define WL_MBSS_VAL 0x04000000 ++#define WL_CAC_VAL 0x08000000 ++#define WL_AMSDU_VAL 0x10000000 ++#define WL_AMPDU_VAL 0x20000000 ++#define WL_FFPLD_VAL 0x40000000 ++ ++/* wl_msg_level is full. For new bits take the next one and AND with ++ * wl_msg_level2 in wl_dbg.h ++ */ ++#define WL_DPT_VAL 0x00000001 ++#define WL_SCAN_VAL 0x00000002 ++#define WL_WOWL_VAL 0x00000004 ++#define WL_COEX_VAL 0x00000008 ++#define WL_RTDC_VAL 0x00000010 ++#define WL_PROTO_VAL 0x00000020 ++#define WL_BTA_VAL 0x00000040 ++#define WL_CHANINT_VAL 0x00000080 ++#define WL_THERMAL_VAL 0x00000100 /* retired in TOT on 6/10/2009 */ ++#define WL_P2P_VAL 0x00000200 ++#define WL_ITFR_VAL 0x00000400 ++#define WL_MCHAN_VAL 0x00000800 ++#define WL_TDLS_VAL 0x00001000 ++#define WL_MCNX_VAL 0x00002000 ++#define WL_PROT_VAL 0x00004000 ++#define WL_PSTA_VAL 0x00008000 ++#define WL_TSO_VAL 0x00010000 ++/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier ++ * rather than a message-type of its own ++ */ ++#define WL_TIMESTAMP_VAL 0x80000000 ++ ++/* max # of leds supported by GPIO (gpio pin# == led index#) */ ++#define WL_LED_NUMGPIO 32 /* gpio 0-31 */ ++ ++/* led per-pin behaviors */ ++#define WL_LED_OFF 0 /* always off */ ++#define WL_LED_ON 1 /* always on */ ++#define WL_LED_ACTIVITY 2 /* activity */ ++#define WL_LED_RADIO 3 /* radio enabled */ ++#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */ ++#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */ ++#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */ ++#define WL_LED_WI1 7 ++#define WL_LED_WI2 8 ++#define WL_LED_WI3 9 ++#define WL_LED_ASSOC 10 /* associated state indicator */ ++#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */ ++#define WL_LED_ASSOCACT 12 /* on when associated; blink fast for activity */ ++#define WL_LED_WI4 13 ++#define WL_LED_WI5 14 ++#define WL_LED_BLINKSLOW 15 /* blink slow */ ++#define WL_LED_BLINKMED 16 /* blink med */ ++#define WL_LED_BLINKFAST 17 /* blink fast */ ++#define WL_LED_BLINKCUSTOM 18 /* blink custom */ ++#define WL_LED_BLINKPERIODIC 19 /* blink periodic (custom 1000ms / off 400ms) */ ++#define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ ++ /* keep on for 300 sec */ ++#define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ ++#define WL_LED_NUMBEHAVIOR 22 ++ ++/* led behavior numeric value format */ ++#define WL_LED_BEH_MASK 0x7f /* behavior mask */ ++#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */ ++ ++/* maximum channels returned by the get valid channels iovar */ ++#define WL_NUMCHANNELS 64 ++ ++/* max number of chanspecs (used by the iovar to calc. buf space) */ ++#define WL_NUMCHANSPECS 110 ++ ++/* WDS link local endpoint WPA role */ ++#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ ++#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */ ++#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */ ++ ++/* number of bytes needed to define a 128-bit mask for MAC event reporting */ ++#define WL_EVENTING_MASK_LEN 16 ++ ++/* ++ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type, ++ * a one-byte length, and a variable length value. RSSI type tuple must be present ++ * in the array. ++ * ++ * Types are defined in "join preference types" section. ++ * ++ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple ++ * and must be set to zero. ++ * ++ * Values are defined below. ++ * ++ * 1. RSSI - 2 octets ++ * offset 0: reserved ++ * offset 1: reserved ++ * ++ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below) ++ * offset 0: reserved ++ * offset 1: # of tuples ++ * offset 2: tuple 1 ++ * offset 14: tuple 2 ++ * ... ++ * offset 2 + 12 * (n - 1) octets: tuple n ++ * ++ * struct wpa_cfg_tuple { ++ * uint8 akm[DOT11_OUI_LEN+1]; akm suite ++ * uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite ++ * uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite ++ * }; ++ * ++ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY. ++ * ++ * 3. BAND - 2 octets ++ * offset 0: reserved ++ * offset 1: see "band preference" and "band types" ++ * ++ * 4. BAND RSSI - 2 octets ++ * offset 0: band types ++ * offset 1: +ve RSSI boost balue in dB ++ */ ++ ++/* join preference types */ ++#define WL_JOIN_PREF_RSSI 1 /* by RSSI */ ++#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers */ ++#define WL_JOIN_PREF_BAND 3 /* by 802.11 band */ ++#define WL_JOIN_PREF_RSSI_DELTA 4 /* by 802.11 band only if RSSI delta condition matches */ ++#define WL_JOIN_PREF_TRANS_PREF 5 /* defined by requesting AP */ ++ ++/* band preference */ ++#define WLJP_BAND_ASSOC_PREF 255 /* use what WLC_SET_ASSOC_PREFER ioctl specifies */ ++ ++/* any multicast cipher suite */ ++#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" ++ ++struct tsinfo_arg { ++ uint8 octets[3]; ++}; ++ ++#define NFIFO 6 /* # tx/rx fifopairs */ ++ ++#define WL_CNT_T_VERSION 8 /* current version of wl_cnt_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; /* obsolete */ ++ uint32 frmscons; /* obsolete */ ++ uint32 txnack; /* obsolete */ ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 dma_hang; /* count for dma hang */ ++ uint32 reinit; /* count for reinit */ ++ ++ uint32 pstatxucast; /* count of ucast frames xmitted on all psta assoc */ ++ uint32 pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ ++ uint32 pstarxucast; /* count of ucast frames received on all psta assoc */ ++ uint32 pstarxbcmc; /* count of bcmc frames received on all psta */ ++ uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ ++ ++ uint32 cso_passthrough; /* hw cso required but passthrough */ ++ uint32 cso_normal; /* hw cso hdr for normal process */ ++ uint32 chained; /* number of frames chained */ ++ uint32 chainedsz1; /* number of chain size 1 frames */ ++ uint32 unchained; /* number of frames not chained */ ++ uint32 maxchainsz; /* max chain size so far */ ++ uint32 currchainsz; /* current chain size */ ++} wl_cnt_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; ++ uint32 frmscons; ++ uint32 txnack; ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++} wl_cnt_ver_six_t; ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WL_DELTA_STATS_T_VERSION 1 /* current version of wl_delta_stats_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_DELTA_STATS_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txfail; /* tx failures */ ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++} wl_delta_stats_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */ ++ ++typedef struct { ++ uint32 packets; ++ uint32 bytes; ++} wl_traffic_stats_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_WME_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */ ++ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */ ++ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */ ++ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */ ++ ++ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */ ++ ++ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */ ++ ++} wl_wme_cnt_t; ++ ++struct wl_msglevel2 { ++ uint32 low; ++ uint32 high; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ uint16 version; /* Version for mkeep_alive */ ++ uint16 length; /* length of fixed parameters in the structure */ ++ uint32 period_msec; ++ uint16 len_bytes; ++ uint8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ uint8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#define WL_MKEEP_ALIVE_VERSION 1 ++#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) ++#define WL_MKEEP_ALIVE_PRECISION 500 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#ifdef WLBA ++ ++#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */ ++ ++/* block ack related stats */ ++typedef struct wlc_ba_cnt { ++ uint16 version; /* WLC_BA_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txpdu; /* pdus sent */ ++ uint32 txsdu; /* sdus sent */ ++ uint32 txfc; /* tx side flow controlled packets */ ++ uint32 txfci; /* tx side flow control initiated */ ++ uint32 txretrans; /* retransmitted pdus */ ++ uint32 txbatimer; /* ba resend due to timer */ ++ uint32 txdrop; /* dropped packets */ ++ uint32 txaddbareq; /* addba req sent */ ++ uint32 txaddbaresp; /* addba resp sent */ ++ uint32 txdelba; /* delba sent */ ++ uint32 txba; /* ba sent */ ++ uint32 txbar; /* bar sent */ ++ uint32 txpad[4]; /* future */ ++ ++ /* receive side counters */ ++ uint32 rxpdu; /* pdus recd */ ++ uint32 rxqed; /* pdus buffered before sending up */ ++ uint32 rxdup; /* duplicate pdus */ ++ uint32 rxnobuf; /* pdus discarded due to no buf */ ++ uint32 rxaddbareq; /* addba req recd */ ++ uint32 rxaddbaresp; /* addba resp recd */ ++ uint32 rxdelba; /* delba recd */ ++ uint32 rxba; /* ba recd */ ++ uint32 rxbar; /* bar recd */ ++ uint32 rxinvba; /* invalid ba recd */ ++ uint32 rxbaholes; /* ba recd with holes */ ++ uint32 rxunexp; /* unexpected packets */ ++ uint32 rxpad[4]; /* future */ ++} wlc_ba_cnt_t; ++#endif /* WLBA */ ++ ++/* structure for per-tid ampdu control */ ++struct ampdu_tid_control { ++ uint8 tid; /* tid */ ++ uint8 enable; /* enable/disable */ ++}; ++ ++/* structure for identifying ea/tid for sending addba/delba */ ++struct ampdu_ea_tid { ++ struct ether_addr ea; /* Station address */ ++ uint8 tid; /* tid */ ++}; ++/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */ ++struct ampdu_retry_tid { ++ uint8 tid; /* tid */ ++ uint8 retry; /* retry value */ ++}; ++ ++/* Different discovery modes for dpt */ ++#define DPT_DISCOVERY_MANUAL 0x01 /* manual discovery mode */ ++#define DPT_DISCOVERY_AUTO 0x02 /* auto discovery mode */ ++#define DPT_DISCOVERY_SCAN 0x04 /* scan-based discovery mode */ ++ ++/* different path selection values */ ++#define DPT_PATHSEL_AUTO 0 /* auto mode for path selection */ ++#define DPT_PATHSEL_DIRECT 1 /* always use direct DPT path */ ++#define DPT_PATHSEL_APPATH 2 /* always use AP path */ ++ ++/* different ops for deny list */ ++#define DPT_DENY_LIST_ADD 1 /* add to dpt deny list */ ++#define DPT_DENY_LIST_REMOVE 2 /* remove from dpt deny list */ ++ ++/* different ops for manual end point */ ++#define DPT_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define DPT_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define DPT_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++ ++/* structure for dpt iovars */ ++typedef struct dpt_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ uint32 pad; /* future */ ++} dpt_iovar_t; ++ ++/* flags to indicate DPT status */ ++#define DPT_STATUS_ACTIVE 0x01 /* link active (though may be suspended) */ ++#define DPT_STATUS_AES 0x02 /* link secured through AES encryption */ ++#define DPT_STATUS_FAILED 0x04 /* DPT link failed */ ++ ++#define DPT_FNAME_LEN 48 /* Max length of friendly name */ ++ ++typedef struct dpt_status { ++ uint8 status; /* flags to indicate status */ ++ uint8 fnlen; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++ uint32 rssi; /* RSSI of the link */ ++ sta_info_t sta; /* sta info */ ++} dpt_status_t; ++ ++/* structure for dpt list */ ++typedef struct dpt_list { ++ uint32 num; /* number of entries in struct */ ++ dpt_status_t status[1]; /* per station info */ ++} dpt_list_t; ++ ++/* structure for dpt friendly name */ ++typedef struct dpt_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++} dpt_fname_t; ++ ++#define BDD_FNAME_LEN 32 /* Max length of friendly name */ ++typedef struct bdd_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[BDD_FNAME_LEN]; /* friendly name */ ++} bdd_fname_t; ++ ++/* structure for addts arguments */ ++/* For ioctls that take a list of TSPEC */ ++struct tslist { ++ int count; /* number of tspecs */ ++ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ ++}; ++ ++#ifdef WLTDLS ++/* different ops for manual end point */ ++#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++#define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ ++#define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ ++#define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ ++#define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ ++ ++/* structure for tdls iovars */ ++typedef struct tdls_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ chanspec_t chanspec; ++ uint32 pad; /* future */ ++} tdls_iovar_t; ++#endif /* WLTDLS */ ++ ++/* structure for addts/delts arguments */ ++typedef struct tspec_arg { ++ uint16 version; /* see definition of TSPEC_ARG_VERSION */ ++ uint16 length; /* length of entire structure */ ++ uint flag; /* bit field */ ++ /* TSPEC Arguments */ ++ struct tsinfo_arg tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint min_srv_interval; /* Minimum Service Interval (us) */ ++ uint max_srv_interval; /* Maximum Service Interval (us) */ ++ uint inactivity_interval; /* Inactivity Interval (us) */ ++ uint suspension_interval; /* Suspension Interval (us) */ ++ uint srv_start_time; /* Service Start Time (us) */ ++ uint min_data_rate; /* Minimum Data Rate (bps) */ ++ uint mean_data_rate; /* Mean Data Rate (bps) */ ++ uint peak_data_rate; /* Peak Data Rate (bps) */ ++ uint max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint delay_bound; /* Delay Bound (us) */ ++ uint min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++ uint8 dialog_token; /* dialog token */ ++} tspec_arg_t; ++ ++/* tspec arg for desired station */ ++typedef struct tspec_per_sta_arg { ++ struct ether_addr ea; ++ struct tspec_arg ts; ++} tspec_per_sta_arg_t; ++ ++/* structure for max bandwidth for each access category */ ++typedef struct wme_max_bandwidth { ++ uint32 ac[AC_COUNT]; /* max bandwidth for each access category */ ++} wme_max_bandwidth_t; ++ ++#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t)) ++ ++/* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */ ++#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */ ++#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */ ++ ++ ++#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80 ++#define WLC_WOWL_MAX_KEEPALIVE 2 ++ ++/* define for flag */ ++#define TSPEC_PENDING 0 /* TSPEC pending */ ++#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ ++#define TSPEC_REJECTED 2 /* TSPEC rejected */ ++#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ ++#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ ++ ++ ++/* Software feature flag defines used by wlfeatureflag */ ++#ifdef WLAFTERBURNER ++#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ ++#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ ++#endif /* WLAFTERBURNER */ ++#define WL_SWFL_NOHWRADIO 0x0004 ++#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ ++#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ ++ ++#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ ++ ++/* Packet lifetime configuration per ac */ ++typedef struct wl_lifetime { ++ uint32 ac; /* access class */ ++ uint32 lifetime; /* Packet lifetime value in ms */ ++} wl_lifetime_t; ++ ++/* Channel Switch Announcement param */ ++typedef struct wl_chan_switch { ++ uint8 mode; /* value 0 or 1 */ ++ uint8 count; /* count # of beacons before switching */ ++ chanspec_t chspec; /* chanspec */ ++ uint8 reg; /* regulatory class */ ++} wl_chan_switch_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER. ++ * ++ * (-100 < value < 0) value is used directly as a roaming trigger in dBm ++ * (0 <= value) value specifies a logical roaming trigger level from ++ * the list below ++ * ++ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never ++ * the logical roam trigger value. ++ */ ++#define WLC_ROAM_TRIGGER_DEFAULT 0 /* default roaming trigger */ ++#define WLC_ROAM_TRIGGER_BANDWIDTH 1 /* optimize for bandwidth roaming trigger */ ++#define WLC_ROAM_TRIGGER_DISTANCE 2 /* optimize for distance roaming trigger */ ++#define WLC_ROAM_TRIGGER_AUTO 3 /* auto-detect environment */ ++#define WLC_ROAM_TRIGGER_MAX_VALUE 3 /* max. valid value */ ++ ++#define WLC_ROAM_NEVER_ROAM_TRIGGER (-100) /* Avoid Roaming by setting a large value */ ++ ++/* Preferred Network Offload (PNO, formerly PFN) defines */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++enum { ++ PFN_LIST_ORDER, ++ PFN_RSSI ++}; ++ ++enum { ++ DISABLE, ++ ENABLE ++}; ++ ++enum { ++ OFF_ADAPT, ++ SMART_ADAPT, ++ STRICT_ADAPT, ++ SLOW_ADAPT ++}; ++ ++#define SORT_CRITERIA_BIT 0 ++#define AUTO_NET_SWITCH_BIT 1 ++#define ENABLE_BKGRD_SCAN_BIT 2 ++#define IMMEDIATE_SCAN_BIT 3 ++#define AUTO_CONNECT_BIT 4 ++#define ENABLE_BD_SCAN_BIT 5 ++#define ENABLE_ADAPTSCAN_BIT 6 ++#define IMMEDIATE_EVENT_BIT 8 ++ ++#define SORT_CRITERIA_MASK 0x0001 ++#define AUTO_NET_SWITCH_MASK 0x0002 ++#define ENABLE_BKGRD_SCAN_MASK 0x0004 ++#define IMMEDIATE_SCAN_MASK 0x0008 ++#define AUTO_CONNECT_MASK 0x0010 ++ ++#define ENABLE_BD_SCAN_MASK 0x0020 ++#define ENABLE_ADAPTSCAN_MASK 0x00c0 ++#define IMMEDIATE_EVENT_MASK 0x0100 ++ ++#define PFN_VERSION 2 ++#define PFN_SCANRESULT_VERSION 1 ++#define MAX_PFN_LIST_COUNT 16 ++ ++#define PFN_COMPLETE 1 ++#define PFN_INCOMPLETE 0 ++ ++#define DEFAULT_BESTN 2 ++#define DEFAULT_MSCAN 0 ++#define DEFAULT_REPEAT 10 ++#define DEFAULT_EXP 2 ++ ++/* PFN network info structure */ ++typedef struct wl_pfn_subnet_info { ++ struct ether_addr BSSID; ++ uint8 channel; /* channel number only */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++} wl_pfn_subnet_info_t; ++ ++typedef struct wl_pfn_net_info { ++ wl_pfn_subnet_info_t pfnsubnet; ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ uint16 timestamp; /* age in seconds */ ++} wl_pfn_net_info_t; ++ ++typedef struct wl_pfn_scanresults { ++ uint32 version; ++ uint32 status; ++ uint32 count; ++ wl_pfn_net_info_t netinfo[1]; ++} wl_pfn_scanresults_t; ++ ++/* PFN data structure */ ++typedef struct wl_pfn_param { ++ int32 version; /* PNO parameters version */ ++ int32 scan_freq; /* Scan frequency */ ++ int32 lost_network_timeout; /* Timeout in sec. to declare ++ * discovered network as lost ++ */ ++ int16 flags; /* Bit field to control features ++ * of PFN such as sort criteria auto ++ * enable switch and background scan ++ */ ++ int16 rssi_margin; /* Margin to avoid jitter for choosing a ++ * PFN based on RSSI sort criteria ++ */ ++ uint8 bestn; /* number of best networks in each scan */ ++ uint8 mscan; /* number of scans recorded */ ++ uint8 repeat; /* Minimum number of scan intervals ++ *before scan frequency changes in adaptive scan ++ */ ++ uint8 exp; /* Exponent of 2 for maximum scan interval */ ++#if !defined(WLC_PATCH) || !defined(BCM43362A2) ++ int32 slow_freq; /* slow scan period */ ++#endif /* !WLC_PATCH || !BCM43362A2 */ ++} wl_pfn_param_t; ++ ++typedef struct wl_pfn { ++ wlc_ssid_t ssid; /* ssid name and its length */ ++ int32 bss_type; /* IBSS or infrastructure */ ++ int32 infra; /* BSS Vs IBSS */ ++ int32 auth; /* Open Vs Closed */ ++ int32 wpa_auth; /* WPA type */ ++ int32 wsec; /* wsec value */ ++} wl_pfn_t; ++#define WL_PFN_HIDDEN_BIT 2 ++#define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ ++#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ ++#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ ++#define WL_PFN_HIDDEN_MASK 0x4 ++ ++/* TCP Checksum Offload defines */ ++#define TOE_TX_CSUM_OL 0x00000001 ++#define TOE_RX_CSUM_OL 0x00000002 ++ ++/* TCP Checksum Offload error injection for testing */ ++#define TOE_ERRTEST_TX_CSUM 0x00000001 ++#define TOE_ERRTEST_RX_CSUM 0x00000002 ++#define TOE_ERRTEST_RX_CSUM2 0x00000004 ++ ++struct toe_ol_stats_t { ++ /* Num of tx packets that don't need to be checksummed */ ++ uint32 tx_summed; ++ ++ /* Num of tx packets where checksum is filled by offload engine */ ++ uint32 tx_iph_fill; ++ uint32 tx_tcp_fill; ++ uint32 tx_udp_fill; ++ uint32 tx_icmp_fill; ++ ++ /* Num of rx packets where toe finds out if checksum is good or bad */ ++ uint32 rx_iph_good; ++ uint32 rx_iph_bad; ++ uint32 rx_tcp_good; ++ uint32 rx_tcp_bad; ++ uint32 rx_udp_good; ++ uint32 rx_udp_bad; ++ uint32 rx_icmp_good; ++ uint32 rx_icmp_bad; ++ ++ /* Num of tx packets in which csum error is injected */ ++ uint32 tx_tcp_errinj; ++ uint32 tx_udp_errinj; ++ uint32 tx_icmp_errinj; ++ ++ /* Num of rx packets in which csum error is injected */ ++ uint32 rx_tcp_errinj; ++ uint32 rx_udp_errinj; ++ uint32 rx_icmp_errinj; ++}; ++ ++/* ARP Offload feature flags for arp_ol iovar */ ++#define ARP_OL_AGENT 0x00000001 ++#define ARP_OL_SNOOP 0x00000002 ++#define ARP_OL_HOST_AUTO_REPLY 0x00000004 ++#define ARP_OL_PEER_AUTO_REPLY 0x00000008 ++ ++/* ARP Offload error injection */ ++#define ARP_ERRTEST_REPLY_PEER 0x1 ++#define ARP_ERRTEST_REPLY_HOST 0x2 ++ ++#define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++ ++/* Arp offload statistic counts */ ++struct arp_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ ++ uint32 arp_table_entries; /* ARP table entries */ ++ uint32 arp_table_overflow; /* ARP table additions skipped due to overflow */ ++ ++ uint32 host_request; /* ARP requests from host */ ++ uint32 host_reply; /* ARP replies from host */ ++ uint32 host_service; /* ARP requests from host serviced by ARP Agent */ ++ ++ uint32 peer_request; /* ARP requests received from network */ ++ uint32 peer_request_drop; /* ARP requests from network that were dropped */ ++ uint32 peer_reply; /* ARP replies received from network */ ++ uint32 peer_reply_drop; /* ARP replies from network that were dropped */ ++ uint32 peer_service; /* ARP request from host serviced by ARP Agent */ ++}; ++ ++/* NS offload statistic counts */ ++struct nd_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ uint32 peer_request; /* NS requests received from network */ ++ uint32 peer_request_drop; /* NS requests from network that were dropped */ ++ uint32 peer_reply_drop; /* NA replies from network that were dropped */ ++ uint32 peer_service; /* NS request from host serviced by firmware */ ++}; ++ ++/* ++ * Keep-alive packet offloading. ++ */ ++ ++/* NAT keep-alive packets format: specifies the re-transmission period, the packet ++ * length, and packet contents. ++ */ ++typedef struct wl_keep_alive_pkt { ++ uint32 period_msec; /* Retransmission period (0 to disable packet re-transmits) */ ++ uint16 len_bytes; /* Size of packet to transmit (0 to disable packet re-transmits) */ ++ uint8 data[1]; /* Variable length packet to transmit. Contents should include ++ * entire ethernet packet (enet header, IP header, UDP header, ++ * and UDP payload) in network byte order. ++ */ ++} wl_keep_alive_pkt_t; ++ ++#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data) ++ ++/* ++ * Dongle pattern matching filter. ++ */ ++ ++/* Packet filter types. Currently, only pattern matching is supported. */ ++typedef enum wl_pkt_filter_type { ++ WL_PKT_FILTER_TYPE_PATTERN_MATCH /* Pattern matching filter */ ++} wl_pkt_filter_type_t; ++ ++#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t ++ ++/* Pattern matching filter. Specifies an offset within received packets to ++ * start matching, the pattern to match, the size of the pattern, and a bitmask ++ * that indicates which bits within the pattern should be matched. ++ */ ++typedef struct wl_pkt_filter_pattern { ++ uint32 offset; /* Offset within received packet to start pattern matching. ++ * Offset '0' is the first byte of the ethernet header. ++ */ ++ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ ++ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts ++ * at offset 0. Pattern immediately follows mask. ++ */ ++} wl_pkt_filter_pattern_t; ++ ++/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ ++typedef struct wl_pkt_filter { ++ uint32 id; /* Unique filter id, specified by app. */ ++ uint32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ ++ uint32 negate_match; /* Negate the result of filter matches */ ++ union { /* Filter definitions */ ++ wl_pkt_filter_pattern_t pattern; /* Pattern matching filter */ ++ } u; ++} wl_pkt_filter_t; ++ ++#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u) ++#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern) ++ ++/* IOVAR "pkt_filter_enable" parameter. */ ++typedef struct wl_pkt_filter_enable { ++ uint32 id; /* Unique filter id */ ++ uint32 enable; /* Enable/disable bool */ ++} wl_pkt_filter_enable_t; ++ ++/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ ++typedef struct wl_pkt_filter_list { ++ uint32 num; /* Number of installed packet filters */ ++ wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */ ++} wl_pkt_filter_list_t; ++ ++#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) ++ ++/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */ ++typedef struct wl_pkt_filter_stats { ++ uint32 num_pkts_matched; /* # filter matches for specified filter id */ ++ uint32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */ ++ uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ ++} wl_pkt_filter_stats_t; ++ ++/* Sequential Commands ioctl */ ++typedef struct wl_seq_cmd_ioctl { ++ uint32 cmd; /* common ioctl definition */ ++ uint32 len; /* length of user buffer */ ++} wl_seq_cmd_ioctl_t; ++ ++#define WL_SEQ_CMD_ALIGN_BYTES 4 ++ ++/* These are the set of get IOCTLs that should be allowed when using ++ * IOCTL sequence commands. These are issued implicitly by wl.exe each time ++ * it is invoked. We never want to buffer these, or else wl.exe will stop working. ++ */ ++#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ ++ (((cmd) == WLC_GET_MAGIC) || \ ++ ((cmd) == WLC_GET_VERSION) || \ ++ ((cmd) == WLC_GET_AP) || \ ++ ((cmd) == WLC_GET_INSTANCE)) ++ ++/* ++ * Packet engine interface ++ */ ++ ++#define WL_PKTENG_PER_TX_START 0x01 ++#define WL_PKTENG_PER_TX_STOP 0x02 ++#define WL_PKTENG_PER_RX_START 0x04 ++#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 ++#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 ++#define WL_PKTENG_PER_RX_STOP 0x08 ++#define WL_PKTENG_PER_MASK 0xff ++ ++#define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ ++ ++typedef struct wl_pkteng { ++ uint32 flags; ++ uint32 delay; /* Inter-packet delay */ ++ uint32 nframes; /* Number of frames */ ++ uint32 length; /* Packet length */ ++ uint8 seqno; /* Enable/disable sequence no. */ ++ struct ether_addr dest; /* Destination address */ ++ struct ether_addr src; /* Source address */ ++} wl_pkteng_t; ++ ++#define NUM_80211b_RATES 4 ++#define NUM_80211ag_RATES 8 ++#define NUM_80211n_RATES 32 ++#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) ++typedef struct wl_pkteng_stats { ++ uint32 lostfrmcnt; /* RX PER test: no of frames lost (skip seqno) */ ++ int32 rssi; /* RSSI */ ++ int32 snr; /* signal to noise ratio */ ++ uint16 rxpktcnt[NUM_80211_RATES+1]; ++} wl_pkteng_stats_t; ++ ++typedef struct wl_sslpnphy_papd_debug_data { ++ uint8 psat_pwr; ++ uint8 psat_indx; ++ uint8 final_idx; ++ uint8 start_idx; ++ int32 min_phase; ++ int32 voltage; ++ int8 temperature; ++} wl_sslpnphy_papd_debug_data_t; ++typedef struct wl_sslpnphy_debug_data { ++ int16 papdcompRe [64]; ++ int16 papdcompIm [64]; ++} wl_sslpnphy_debug_data_t; ++typedef struct wl_sslpnphy_spbdump_data { ++ uint16 tbl_length; ++ int16 spbreal[256]; ++ int16 spbimg[256]; ++} wl_sslpnphy_spbdump_data_t; ++typedef struct wl_sslpnphy_percal_debug_data { ++ uint cur_idx; ++ uint tx_drift; ++ uint8 prev_cal_idx; ++ uint percal_ctr; ++ int nxt_cal_idx; ++ uint force_1idxcal; ++ uint onedxacl_req; ++ int32 last_cal_volt; ++ int8 last_cal_temp; ++ uint vbat_ripple; ++ uint exit_route; ++ int32 volt_winner; ++} wl_sslpnphy_percal_debug_data_t; ++ ++#define WL_WOWL_MAGIC (1 << 0) /* Wakeup on Magic packet */ ++#define WL_WOWL_NET (1 << 1) /* Wakeup on Netpattern */ ++#define WL_WOWL_DIS (1 << 2) /* Wakeup on loss-of-link due to Disassoc/Deauth */ ++#define WL_WOWL_RETR (1 << 3) /* Wakeup on retrograde TSF */ ++#define WL_WOWL_BCN (1 << 4) /* Wakeup on loss of beacon */ ++#define WL_WOWL_TST (1 << 5) /* Wakeup after test */ ++#define WL_WOWL_M1 (1 << 6) /* Wakeup after PTK refresh */ ++#define WL_WOWL_EAPID (1 << 7) /* Wakeup after receipt of EAP-Identity Req */ ++#define WL_WOWL_PME_GPIO (1 << 8) /* Wakeind via PME(0) or GPIO(1) */ ++#define WL_WOWL_NEEDTKIP1 (1 << 9) /* need tkip phase 1 key to be updated by the driver */ ++#define WL_WOWL_GTK_FAILURE (1 << 10) /* enable wakeup if GTK fails */ ++#define WL_WOWL_EXTMAGPAT (1 << 11) /* support extended magic packets */ ++#define WL_WOWL_ARPOFFLOAD (1 << 12) /* support ARP/NS/keepalive offloading */ ++#define WL_WOWL_WPA2 (1 << 13) /* read protocol version for EAPOL frames */ ++#define WL_WOWL_KEYROT (1 << 14) /* If the bit is set, use key rotaton */ ++#define WL_WOWL_BCAST (1 << 15) /* If the bit is set, frm received was bcast frame */ ++ ++#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ ++ ++#define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ ++#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ ++ ++typedef struct { ++ uint32 masksize; /* Size of the mask in #of bytes */ ++ uint32 offset; /* Offset to start looking for the packet in # of bytes */ ++ uint32 patternoffset; /* Offset of start of pattern in the structure */ ++ uint32 patternsize; /* Size of the pattern itself in #of bytes */ ++ uint32 id; /* id */ ++ uint32 reasonsize; /* Size of the wakeup reason code */ ++ uint32 flags; /* Flags to tell the pattern type and other properties */ ++ /* Mask follows the structure above */ ++ /* Pattern follows the mask is at 'patternoffset' from the start */ ++} wl_wowl_pattern_t; ++ ++typedef struct { ++ uint count; ++ wl_wowl_pattern_t pattern[1]; ++} wl_wowl_pattern_list_t; ++ ++typedef struct { ++ uint8 pci_wakeind; /* Whether PCI PMECSR PMEStatus bit was set */ ++ uint16 ucode_wakeind; /* What wakeup-event indication was set by ucode */ ++} wl_wowl_wakeind_t; ++ ++ ++/* per AC rate control related data structure */ ++typedef struct wl_txrate_class { ++ uint8 init_rate; ++ uint8 min_rate; ++ uint8 max_rate; ++} wl_txrate_class_t; ++ ++ ++#if defined(DSLCPE_DELAY) ++#define WL_DELAYMODE_DEFER 0 /* defer by scheduler's choice, make this driver default */ ++#define WL_DELAYMODE_FORCE 1 /* force, this is driver default */ ++#define WL_DELAYMODE_AUTO 2 /* defer if no sta associated, force if sta associated */ ++#endif ++ ++/* Overlap BSS Scan parameters default, minimum, maximum */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 /* unit Sec */ ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 /* unit percent */ ++ ++/* structure for Overlap BSS scan arguments */ ++typedef struct wl_obss_scan_arg { ++ int16 passive_dwell; ++ int16 active_dwell; ++ int16 bss_widthscan_interval; ++ int16 passive_total; ++ int16 active_total; ++ int16 chanwidth_transition_delay; ++ int16 activity_threshold; ++} wl_obss_scan_arg_t; ++ ++#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) ++#define WL_MIN_NUM_OBSS_SCAN_ARG 7 /* minimum number of arguments required for OBSS Scan */ ++ ++#define WL_COEX_INFO_MASK 0x07 ++#define WL_COEX_INFO_REQ 0x01 ++#define WL_COEX_40MHZ_INTOLERANT 0x02 ++#define WL_COEX_WIDTH20 0x04 ++ ++#define WLC_RSSI_INVALID 0 /* invalid RSSI value */ ++ ++#define MAX_RSSI_LEVELS 8 ++ ++/* RSSI event notification configuration. */ ++typedef struct wl_rssi_event { ++ uint32 rate_limit_msec; /* # of events posted to application will be limited to ++ * one per specified period (0 to disable rate limit). ++ */ ++ uint8 num_rssi_levels; /* Number of entries in rssi_levels[] below */ ++ int8 rssi_levels[MAX_RSSI_LEVELS]; /* Variable number of RSSI levels. An event ++ * will be posted each time the RSSI of received ++ * beacons/packets crosses a level. ++ */ ++} wl_rssi_event_t; ++ ++typedef struct wl_action_obss_coex_req { ++ uint8 info; ++ uint8 num; ++ uint8 ch_list[1]; ++} wl_action_obss_coex_req_t; ++ ++ ++/* IOVar parameter block for small MAC address array with type indicator */ ++#define WL_IOV_MAC_PARAM_LEN 4 ++ ++#define WL_IOV_PKTQ_LOG_PRECS 16 ++ ++typedef struct { ++ uint32 num_addrs; ++ char addr_type[WL_IOV_MAC_PARAM_LEN]; ++ struct ether_addr ea[WL_IOV_MAC_PARAM_LEN]; ++} wl_iov_mac_params_t; ++ ++ ++/* Parameter block for PKTQ_LOG statistics */ ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_log_counters_v01_t; ++ ++#define sacrified sacrificed ++ ++typedef struct { ++ uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; ++ pktq_log_counters_v01_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; ++ char headings[1]; ++} pktq_log_format_v01_t; ++ ++ ++typedef struct { ++ uint32 version; ++ wl_iov_mac_params_t params; ++ union { ++ pktq_log_format_v01_t v01; ++ } pktq_log; ++} wl_iov_pktq_log_t; ++ ++ ++/* **** EXTLOG **** */ ++#define EXTLOG_CUR_VER 0x0100 ++ ++#define MAX_ARGSTR_LEN 18 /* At least big enough for storing ETHER_ADDR_STR_LEN */ ++ ++/* log modules (bitmap) */ ++#define LOG_MODULE_COMMON 0x0001 ++#define LOG_MODULE_ASSOC 0x0002 ++#define LOG_MODULE_EVENT 0x0004 ++#define LOG_MODULE_MAX 3 /* Update when adding module */ ++ ++/* log levels */ ++#define WL_LOG_LEVEL_DISABLE 0 ++#define WL_LOG_LEVEL_ERR 1 ++#define WL_LOG_LEVEL_WARN 2 ++#define WL_LOG_LEVEL_INFO 3 ++#define WL_LOG_LEVEL_MAX WL_LOG_LEVEL_INFO /* Update when adding level */ ++ ++/* flag */ ++#define LOG_FLAG_EVENT 1 ++ ++/* log arg_type */ ++#define LOG_ARGTYPE_NULL 0 ++#define LOG_ARGTYPE_STR 1 /* %s */ ++#define LOG_ARGTYPE_INT 2 /* %d */ ++#define LOG_ARGTYPE_INT_STR 3 /* %d...%s */ ++#define LOG_ARGTYPE_STR_INT 4 /* %s...%d */ ++ ++typedef struct wlc_extlog_cfg { ++ int max_number; ++ uint16 module; /* bitmap */ ++ uint8 level; ++ uint8 flag; ++ uint16 version; ++} wlc_extlog_cfg_t; ++ ++typedef struct log_record { ++ uint32 time; ++ uint16 module; ++ uint16 id; ++ uint8 level; ++ uint8 sub_unit; ++ uint8 seq_num; ++ int32 arg; ++ char str[MAX_ARGSTR_LEN]; ++} log_record_t; ++ ++typedef struct wlc_extlog_req { ++ uint32 from_last; ++ uint32 num; ++} wlc_extlog_req_t; ++ ++typedef struct wlc_extlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ log_record_t logs[1]; ++} wlc_extlog_results_t; ++ ++typedef struct log_idstr { ++ uint16 id; ++ uint16 flag; ++ uint8 arg_type; ++ const char *fmt_str; ++} log_idstr_t; ++ ++#define FMTSTRF_USER 1 ++ ++/* flat ID definitions ++ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will ++ * affect backward compatibility with pre-existing apps ++ */ ++typedef enum { ++ FMTSTR_DRIVER_UP_ID = 0, ++ FMTSTR_DRIVER_DOWN_ID = 1, ++ FMTSTR_SUSPEND_MAC_FAIL_ID = 2, ++ FMTSTR_NO_PROGRESS_ID = 3, ++ FMTSTR_RFDISABLE_ID = 4, ++ FMTSTR_REG_PRINT_ID = 5, ++ FMTSTR_EXPTIME_ID = 6, ++ FMTSTR_JOIN_START_ID = 7, ++ FMTSTR_JOIN_COMPLETE_ID = 8, ++ FMTSTR_NO_NETWORKS_ID = 9, ++ FMTSTR_SECURITY_MISMATCH_ID = 10, ++ FMTSTR_RATE_MISMATCH_ID = 11, ++ FMTSTR_AP_PRUNED_ID = 12, ++ FMTSTR_KEY_INSERTED_ID = 13, ++ FMTSTR_DEAUTH_ID = 14, ++ FMTSTR_DISASSOC_ID = 15, ++ FMTSTR_LINK_UP_ID = 16, ++ FMTSTR_LINK_DOWN_ID = 17, ++ FMTSTR_RADIO_HW_OFF_ID = 18, ++ FMTSTR_RADIO_HW_ON_ID = 19, ++ FMTSTR_EVENT_DESC_ID = 20, ++ FMTSTR_PNP_SET_POWER_ID = 21, ++ FMTSTR_RADIO_SW_OFF_ID = 22, ++ FMTSTR_RADIO_SW_ON_ID = 23, ++ FMTSTR_PWD_MISMATCH_ID = 24, ++ FMTSTR_FATAL_ERROR_ID = 25, ++ FMTSTR_AUTH_FAIL_ID = 26, ++ FMTSTR_ASSOC_FAIL_ID = 27, ++ FMTSTR_IBSS_FAIL_ID = 28, ++ FMTSTR_EXTAP_FAIL_ID = 29, ++ FMTSTR_MAX_ID ++} log_fmtstr_id_t; ++ ++#ifdef DONGLEOVERLAYS ++typedef struct { ++ uint32 flags_idx; /* lower 8 bits: overlay index; upper 24 bits: flags */ ++ uint32 offset; /* offset into overlay region to write code */ ++ uint32 len; /* overlay code len */ ++ /* overlay code follows this struct */ ++} wl_ioctl_overlay_t; ++ ++#define OVERLAY_IDX_MASK 0x000000ff ++#define OVERLAY_IDX_SHIFT 0 ++#define OVERLAY_FLAGS_MASK 0xffffff00 ++#define OVERLAY_FLAGS_SHIFT 8 ++/* overlay written to device memory immediately after loading the base image */ ++#define OVERLAY_FLAG_POSTLOAD 0x100 ++/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */ ++#define OVERLAY_FLAG_DEFER_DL 0x200 ++/* overlay downloaded prior to the host going to sleep */ ++#define OVERLAY_FLAG_PRESLEEP 0x400 ++ ++#define OVERLAY_DOWNLOAD_CHUNKSIZE 1024 ++#endif /* DONGLEOVERLAYS */ ++ ++/* no default structure packing */ ++#include ++ ++/* require strict packing */ ++#include ++/* Structures and constants used for "vndr_ie" IOVar interface */ ++#define VNDR_IE_CMD_LEN 4 /* length of the set command string: ++ * "add", "del" (+ NUL) ++ */ ++ ++/* 802.11 Mgmt Packet flags */ ++#define VNDR_IE_BEACON_FLAG 0x1 ++#define VNDR_IE_PRBRSP_FLAG 0x2 ++#define VNDR_IE_ASSOCRSP_FLAG 0x4 ++#define VNDR_IE_AUTHRSP_FLAG 0x8 ++#define VNDR_IE_PRBREQ_FLAG 0x10 ++#define VNDR_IE_ASSOCREQ_FLAG 0x20 ++#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ ++#define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ ++ ++#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ vndr_ie_t vndr_ie_data; /* vendor IE data */ ++} BWL_POST_PACKED_STRUCT vndr_ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the vndr_ie_list[] array */ ++ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT vndr_ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NUL */ ++ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ ++} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT tlv_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ tlv_t ie_data; /* IE data */ ++} BWL_POST_PACKED_STRUCT ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the ie_list[] array */ ++ ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */ ++ ie_buf_t ie_buffer; /* buffer containing IE list information */ ++} BWL_POST_PACKED_STRUCT ie_setbuf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ uint8 id; /* IE type */ ++} BWL_POST_PACKED_STRUCT ie_getbuf_t; ++ ++/* structures used to define format of wps ie data from probe requests */ ++/* passed up to applications via iovar "prbreq_wpsie" */ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { ++ struct ether_addr staAddr; ++ uint16 ieLen; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data { ++ sta_prbreq_wps_ie_hdr_t hdr; ++ uint8 ieData[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list { ++ uint32 totLen; ++ uint8 ieDataList[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t; ++ ++ ++#ifdef WLMEDIA_TXFAILEVENT ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char dest[ETHER_ADDR_LEN]; /* destination MAC */ ++ uint8 prio; /* Packet Priority */ ++ uint8 flags; /* Flags */ ++ uint32 tsf_l; /* TSF timer low */ ++ uint32 tsf_h; /* TSF timer high */ ++ uint16 rates; /* Main Rates */ ++ uint16 txstatus; /* TX Status */ ++} BWL_POST_PACKED_STRUCT txfailinfo_t; ++#endif /* WLMEDIA_TXFAILEVENT */ ++ ++/* no strict structure packing */ ++#include ++ ++/* Global ASSERT Logging */ ++#define ASSERTLOG_CUR_VER 0x0100 ++#define MAX_ASSRTSTR_LEN 64 ++ ++typedef struct assert_record { ++ uint32 time; ++ uint8 seq_num; ++ char str[MAX_ASSRTSTR_LEN]; ++} assert_record_t; ++ ++typedef struct assertlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ assert_record_t logs[1]; ++} assertlog_results_t; ++ ++#define LOGRRC_FIX_LEN 8 ++#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) ++ ++ ++/* channel interference measurement (chanim) related defines */ ++ ++/* chanim mode */ ++#define CHANIM_DISABLE 0 /* disabled */ ++#define CHANIM_DETECT 1 /* detection only */ ++#define CHANIM_EXT 2 /* external state machine */ ++#define CHANIM_ACT 3 /* full internal state machine, detect + act */ ++#define CHANIM_MODE_MAX 4 ++ ++/* define for apcs reason code */ ++#define APCS_INIT 0 ++#define APCS_IOCTL 1 ++#define APCS_CHANIM 2 ++#define APCS_CSTIMER 3 ++#define APCS_BTA 4 ++ ++/* number of ACS record entries */ ++#define CHANIM_ACS_RECORD 10 ++ ++/* CHANIM */ ++#define CCASTATS_TXDUR 0 ++#define CCASTATS_INBSS 1 ++#define CCASTATS_OBSS 2 ++#define CCASTATS_NOCTG 3 ++#define CCASTATS_NOPKT 4 ++#define CCASTATS_DOZE 5 ++#define CCASTATS_TXOP 6 ++#define CCASTATS_GDTXDUR 7 ++#define CCASTATS_BDTXDUR 8 ++#define CCASTATS_MAX 9 ++ ++/* chanim acs record */ ++typedef struct { ++ bool valid; ++ uint8 trigger; ++ chanspec_t selected_chspc; ++ int8 bgnoise; ++ uint32 glitch_cnt; ++ uint8 ccastats; ++ uint timestamp; ++} chanim_acs_record_t; ++ ++typedef struct { ++ chanim_acs_record_t acs_record[CHANIM_ACS_RECORD]; ++ uint8 count; ++ uint timestamp; ++} wl_acs_record_t; ++ ++typedef struct chanim_stats { ++ uint32 glitchcnt; /* normalized as per second count */ ++ uint32 badplcp; /* normalized as per second count */ ++ uint8 ccastats[CCASTATS_MAX]; /* normalized as 0-255 */ ++ int8 bgnoise; /* background noise level (in dBm) */ ++ chanspec_t chanspec; ++ uint32 timestamp; ++} chanim_stats_t; ++ ++#define WL_CHANIM_STATS_VERSION 1 ++#define WL_CHANIM_COUNT_ALL 0xff ++#define WL_CHANIM_COUNT_ONE 0x1 ++ ++typedef struct { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ chanim_stats_t stats[1]; ++} wl_chanim_stats_t; ++ ++#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats) ++ ++/* Noise measurement metrics. */ ++#define NOISE_MEASURE_KNOISE 0x1 ++ ++/* scb probe parameter */ ++typedef struct { ++ uint32 scb_timeout; ++ uint32 scb_activity_time; ++ uint32 scb_max_probe; ++} wl_scb_probe_t; ++ ++/* ap tpc modes */ ++#define AP_TPC_OFF 0 ++#define AP_TPC_BSS_PWR 1 /* BSS power control */ ++#define AP_TPC_AP_PWR 2 /* AP power control */ ++#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */ ++#define AP_TPC_MAX_LINK_MARGIN 127 ++ ++/* structure/defines for selective mgmt frame (smf) stats support */ ++ ++#define SMFS_VERSION 1 ++/* selected mgmt frame (smf) stats element */ ++typedef struct wl_smfs_elem { ++ uint32 count; ++ uint16 code; /* SC or RC code */ ++} wl_smfs_elem_t; ++ ++typedef struct wl_smf_stats { ++ uint32 version; ++ uint16 length; /* reserved for future usage */ ++ uint8 type; ++ uint8 codetype; ++ uint32 ignored_cnt; ++ uint32 malformed_cnt; ++ uint32 count_total; /* count included the interested group */ ++ wl_smfs_elem_t elem[1]; ++} wl_smf_stats_t; ++ ++#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem); ++ ++enum { ++ SMFS_CODETYPE_SC, ++ SMFS_CODETYPE_RC ++}; ++ ++/* reuse two number in the sc/rc space */ ++#define SMFS_CODE_MALFORMED 0xFFFE ++#define SMFS_CODE_IGNORED 0xFFFD ++ ++typedef enum smfs_type { ++ SMFS_TYPE_AUTH, ++ SMFS_TYPE_ASSOC, ++ SMFS_TYPE_REASSOC, ++ SMFS_TYPE_DISASSOC_TX, ++ SMFS_TYPE_DISASSOC_RX, ++ SMFS_TYPE_DEAUTH_TX, ++ SMFS_TYPE_DEAUTH_RX, ++ SMFS_TYPE_MAX ++} smfs_type_t; ++ ++#ifdef PHYMON ++ ++#define PHYMON_VERSION 1 ++ ++typedef struct wl_phycal_core_state { ++ /* Tx IQ/LO calibration coeffs */ ++ int16 tx_iqlocal_a; ++ int16 tx_iqlocal_b; ++ int8 tx_iqlocal_ci; ++ int8 tx_iqlocal_cq; ++ int8 tx_iqlocal_di; ++ int8 tx_iqlocal_dq; ++ int8 tx_iqlocal_ei; ++ int8 tx_iqlocal_eq; ++ int8 tx_iqlocal_fi; ++ int8 tx_iqlocal_fq; ++ ++ /* Rx IQ calibration coeffs */ ++ int16 rx_iqcal_a; ++ int16 rx_iqcal_b; ++ ++ uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */ ++ uint32 papd_epsilon_table[64]; /* PAPD epsilon table */ ++ int16 papd_epsilon_offset; /* PAPD epsilon offset */ ++ uint8 curr_tx_pwrindex; /* Tx power index */ ++ int8 idle_tssi; /* Idle TSSI */ ++ int8 est_tx_pwr; /* Estimated Tx Power (dB) */ ++ int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */ ++ uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */ ++ uint16 init_gaincode; /* initgain required for ACI */ ++ int8 estirr_tx; ++ int8 estirr_rx; ++ ++} wl_phycal_core_state_t; ++ ++typedef struct wl_phycal_state { ++ int version; ++ int8 num_phy_cores; /* number of cores */ ++ int8 curr_temperature; /* on-chip temperature sensor reading */ ++ chanspec_t chspec; /* channspec for this state */ ++ bool aci_state; /* ACI state: ON/OFF */ ++ uint16 crsminpower; /* crsminpower required for ACI */ ++ uint16 crsminpowerl; /* crsminpowerl required for ACI */ ++ uint16 crsminpoweru; /* crsminpoweru required for ACI */ ++ wl_phycal_core_state_t phycal_core[1]; ++} wl_phycal_state_t; ++ ++#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) ++#endif /* PHYMON */ ++ ++/* discovery state */ ++typedef struct wl_p2p_disc_st { ++ uint8 state; /* see state */ ++ chanspec_t chspec; /* valid in listen state */ ++ uint16 dwell; /* valid in listen state, in ms */ ++} wl_p2p_disc_st_t; ++ ++/* state */ ++#define WL_P2P_DISC_ST_SCAN 0 ++#define WL_P2P_DISC_ST_LISTEN 1 ++#define WL_P2P_DISC_ST_SEARCH 2 ++ ++/* scan request */ ++typedef struct wl_p2p_scan { ++ uint8 type; /* 'S' for WLC_SCAN, 'E' for "escan" */ ++ uint8 reserved[3]; ++ /* scan or escan parms... */ ++} wl_p2p_scan_t; ++ ++/* i/f request */ ++typedef struct wl_p2p_if { ++ struct ether_addr addr; ++ uint8 type; /* see i/f type */ ++ chanspec_t chspec; /* for p2p_ifadd GO */ ++} wl_p2p_if_t; ++ ++/* i/f type */ ++#define WL_P2P_IF_CLIENT 0 ++#define WL_P2P_IF_GO 1 ++#define WL_P2P_IF_DYNBCN_GO 2 ++#define WL_P2P_IF_DEV 3 ++ ++/* i/f query */ ++typedef struct wl_p2p_ifq { ++ uint bsscfgidx; ++ char ifname[BCM_MSG_IFNAME_MAX]; ++} wl_p2p_ifq_t; ++ ++/* OppPS & CTWindow */ ++typedef struct wl_p2p_ops { ++ uint8 ops; /* 0: disable 1: enable */ ++ uint8 ctw; /* >= 10 */ ++} wl_p2p_ops_t; ++ ++/* absence and presence request */ ++typedef struct wl_p2p_sched_desc { ++ uint32 start; ++ uint32 interval; ++ uint32 duration; ++ uint32 count; /* see count */ ++} wl_p2p_sched_desc_t; ++ ++/* count */ ++#define WL_P2P_SCHED_RSVD 0 ++#define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */ ++ ++typedef struct wl_p2p_sched { ++ uint8 type; /* see schedule type */ ++ uint8 action; /* see schedule action */ ++ uint8 option; /* see schedule option */ ++ wl_p2p_sched_desc_t desc[1]; ++} wl_p2p_sched_t; ++#define WL_P2P_SCHED_FIXED_LEN 3 ++ ++/* schedule type */ ++#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */ ++#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */ ++ ++/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */ ++#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */ ++#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_ACTION_GOOFF 2 /* turn off GO beacon/prbrsp functions */ ++/* schedule option - WL_P2P_SCHED_TYPE_XXX */ ++#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */ ++ ++/* schedule option - WL_P2P_SCHED_TYPE_ABS */ ++#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count */ ++#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_OPTION_TSFOFS 2 /* normal start/internal/duration/count with ++ * start being an offset of the 'current' TSF ++ */ ++ ++/* feature flags */ ++#define WL_P2P_FEAT_GO_CSA (1 << 0) /* GO moves with the STA using CSA method */ ++#define WL_P2P_FEAT_GO_NOLEGACY (1 << 1) /* GO does not probe respond to non-p2p probe ++ * requests ++ */ ++#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2) /* Restrict p2p dev interface from responding */ ++ ++/* RFAWARE def */ ++#define BCM_ACTION_RFAWARE 0x77 ++#define BCM_ACTION_RFAWARE_DCS 0x01 ++ ++/* DCS reason code define */ ++#define BCM_DCS_IOVAR 0x1 ++#define BCM_DCS_UNKNOWN 0xFF ++ ++typedef struct wl_bcmdcs_data { ++ uint reason; ++ chanspec_t chspec; ++} wl_bcmdcs_data_t; ++ ++/* n-mode support capability */ ++/* 2x2 includes both 1x1 & 2x2 devices ++ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and ++ * control it independently ++ */ ++#define WL_11N_2x2 1 ++#define WL_11N_3x3 3 ++#define WL_11N_4x4 4 ++ ++/* define 11n feature disable flags */ ++#define WLFEATURE_DISABLE_11N 0x00000001 ++#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 ++#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 ++#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 ++#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 ++#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 ++#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 ++#define WLFEATURE_DISABLE_11N_GF 0x00000080 ++ ++/* Proxy STA modes */ ++#define PSTA_MODE_DISABLED 0 ++#define PSTA_MODE_PROXY 1 ++#define PSTA_MODE_REPEATER 2 ++ ++ ++/* NAT configuration */ ++typedef struct { ++ uint32 ipaddr; /* interface ip address */ ++ uint32 ipaddr_mask; /* interface ip address mask */ ++ uint32 ipaddr_gateway; /* gateway ip address */ ++ uint8 mac_gateway[6]; /* gateway mac address */ ++ uint32 ipaddr_dns; /* DNS server ip address, valid only for public if */ ++ uint8 mac_dns[6]; /* DNS server mac address, valid only for public if */ ++ uint8 GUID[38]; /* interface GUID */ ++} nat_if_info_t; ++ ++typedef struct { ++ uint op; /* operation code */ ++ bool pub_if; /* set for public if, clear for private if */ ++ nat_if_info_t if_info; /* interface info */ ++} nat_cfg_t; ++ ++/* op code in nat_cfg */ ++#define NAT_OP_ENABLE 1 /* enable NAT on given interface */ ++#define NAT_OP_DISABLE 2 /* disable NAT on given interface */ ++#define NAT_OP_DISABLE_ALL 3 /* disable NAT on all interfaces */ ++ ++/* NAT state */ ++#define NAT_STATE_ENABLED 1 /* NAT is enabled */ ++#define NAT_STATE_DISABLED 2 /* NAT is disabled */ ++ ++typedef struct { ++ int state; /* NAT state returned */ ++} nat_state_t; ++ ++#ifdef PROP_TXSTATUS ++/* Bit definitions for tlv iovar */ ++/* ++ * enable RSSI signals: ++ * WLFC_CTL_TYPE_RSSI ++ */ ++#define WLFC_FLAGS_RSSI_SIGNALS 1 ++ ++/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals: ++ * ++ * WLFC_CTL_TYPE_MAC_OPEN ++ * WLFC_CTL_TYPE_MAC_CLOSE ++ * ++ * WLFC_CTL_TYPE_INTERFACE_OPEN ++ * WLFC_CTL_TYPE_INTERFACE_CLOSE ++ * ++ * WLFC_CTL_TYPE_MACDESC_ADD ++ * WLFC_CTL_TYPE_MACDESC_DEL ++ * ++ */ ++#define WLFC_FLAGS_XONXOFF_SIGNALS 2 ++ ++/* enable (status, fifo_credit, mac_credit) signals ++ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT ++ * WLFC_CTL_TYPE_TXSTATUS ++ * WLFC_CTL_TYPE_FIFO_CREDITBACK ++ */ ++#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS 4 ++ ++#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE 8 ++#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE 16 ++#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE 32 ++#endif /* PROP_TXSTATUS */ ++ ++#define BTA_STATE_LOG_SZ 64 ++ ++/* BTAMP Statemachine states */ ++enum { ++ HCIReset = 1, ++ HCIReadLocalAMPInfo, ++ HCIReadLocalAMPASSOC, ++ HCIWriteRemoteAMPASSOC, ++ HCICreatePhysicalLink, ++ HCIAcceptPhysicalLinkRequest, ++ HCIDisconnectPhysicalLink, ++ HCICreateLogicalLink, ++ HCIAcceptLogicalLink, ++ HCIDisconnectLogicalLink, ++ HCILogicalLinkCancel, ++ HCIAmpStateChange, ++ HCIWriteLogicalLinkAcceptTimeout ++}; ++ ++typedef struct flush_txfifo { ++ uint32 txfifobmp; ++ uint32 hwtxfifoflush; ++ struct ether_addr ea; ++} flush_txfifo_t; ++ ++#define CHANNEL_5G_LOW_START 36 /* 5G low (36..48) CDD enable/disable bit mask */ ++#define CHANNEL_5G_MID_START 52 /* 5G mid (52..64) CDD enable/disable bit mask */ ++#define CHANNEL_5G_HIGH_START 100 /* 5G high (100..140) CDD enable/disable bit mask */ ++#define CHANNEL_5G_UPPER_START 149 /* 5G upper (149..161) CDD enable/disable bit mask */ ++ ++enum { ++ SPATIAL_MODE_2G_IDX = 0, ++ SPATIAL_MODE_5G_LOW_IDX, ++ SPATIAL_MODE_5G_MID_IDX, ++ SPATIAL_MODE_5G_HIGH_IDX, ++ SPATIAL_MODE_5G_UPPER_IDX, ++ SPATIAL_MODE_MAX_IDX ++}; ++ ++/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ ++typedef struct wl_mempool_stats { ++ int num; /* Number of memory pools */ ++ bcm_mp_stats_t s[1]; /* Variable array of memory pool stats. */ ++} wl_mempool_stats_t; ++ ++/* Network Offload Engine */ ++#define NWOE_OL_ENABLE 0x00000001 ++ ++typedef struct { ++ uint32 ipaddr; ++ uint32 ipaddr_netmask; ++ uint32 ipaddr_gateway; ++} nwoe_ifconfig_t; ++ ++/* ++ * Traffic management structures/defines. ++ */ ++ ++/* Traffic management bandwidth parameters */ ++#define TRF_MGMT_MAX_PRIORITIES 3 ++ ++#define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ ++#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ ++ ++ ++/* Traffic management priority classes */ ++typedef enum trf_mgmt_priority_class { ++ trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */ ++ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ ++ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ ++ trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) ++} trf_mgmt_priority_class_t; ++ ++/* Traffic management configuration parameters */ ++typedef struct trf_mgmt_config { ++ uint32 trf_mgmt_enabled; /* 0 - disabled, 1 - enabled */ ++ uint32 flags; /* See TRF_MGMT_FLAG_xxx defines */ ++ uint32 host_ip_addr; ++ uint32 host_subnet_mask; ++ uint32 downlink_bandwidth; /* In units of kbps */ ++ uint32 uplink_bandwidth; /* In units of kbps */ ++ uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; ++ uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_config_t; ++ ++/* Traffic management filter */ ++typedef struct trf_mgmt_filter { ++ uint32 dst_ip_addr; /* His IP address */ ++ uint16 dst_port; /* His L4 port */ ++ uint16 src_port; /* My L4 port */ ++ uint16 prot; /* L4 protocol (only TCP or UDP protocols) */ ++ uint16 flags; /* TBD. For now, this must be zero. */ ++ trf_mgmt_priority_class_t priority; /* 802.1p priority for filtered packets */ ++} trf_mgmt_filter_t; ++ ++/* Traffic management filter list (variable length) */ ++typedef struct trf_mgmt_filter_list { ++ uint32 num_filters; ++ trf_mgmt_filter_t filter[1]; ++} trf_mgmt_filter_list_t; ++ ++/* Traffic management shaping info */ ++typedef struct trf_mgmt_shaping_info { ++ uint32 max_bps; /* Max bytes consumed or produced per second */ ++ uint32 max_bytes_per_sampling_period; /* Max bytes consumed or produced per sample */ ++ uint32 shaping_delay_threshold; /* Theshold for starting traffic delays */ ++ uint32 num_bytes_produced_per_sec; /* Bytes produced over the sampling period */ ++ uint32 num_bytes_consumed_per_sec; /* Bytes consumed over the sampling period */ ++} trf_mgmt_shaping_info_t; ++ ++/* Traffic management shaping info array */ ++typedef struct trf_mgmt_shaping_info_array { ++ trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_shaping_info_array_t; ++ ++ ++/* Traffic management statistical counters */ ++typedef struct trf_mgmt_stats { ++ uint32 num_processed_packets; /* Number of packets processed */ ++ uint32 num_processed_bytes; /* Number of bytes processed */ ++ uint32 num_queued_packets; /* Number of packets in queue */ ++ uint32 num_queued_bytes; /* Number of bytes in queue */ ++ uint32 num_discarded_packets; /* Number of packets discarded from queue */ ++} trf_mgmt_stats_t; ++ ++/* Traffic management statisics array */ ++typedef struct trf_mgmt_stats_array { ++ trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_stats_array_t; ++ ++#endif /* _wlioctl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/aiutils.c b/drivers/bcmdrivers/gmac/src/shared/aiutils.c +new file mode 100755 +index 0000000..eed6a11 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch new file mode 100644 index 00000000..1449a31e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch @@ -0,0 +1,1269 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/aiutils.c +@@ -0,0 +1,1263 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * $Id: aiutils.c 327582 2012-04-14 05:02:37Z $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "siutils_priv.h" ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#include "hx4_erom.h" ++#elif defined(CONFIG_MACH_HR2) ++#include "hr2_erom.h" ++#elif defined(CONFIG_MACH_NSP) ++#include "nsp_erom.h" ++#elif defined(CONFIG_MACH_KT2) ++#include "kt2_erom.h" ++#endif ++ ++#include ++ ++#define BCM47162_DMP() ((CHIPID(sih->chip) == BCM47162_CHIP_ID) && \ ++ (CHIPREV(sih->chiprev) == 0) && \ ++ (sii->coreid[sii->curidx] == MIPS74K_CORE_ID)) ++ ++#define BCM5357_DMP() (((CHIPID(sih->chip) == BCM5357_CHIP_ID) || \ ++ (CHIPID(sih->chip) == BCM4749_CHIP_ID)) && \ ++ (sih->chippkg == BCM5357_PKG_ID) && \ ++ (sii->coreid[sii->curidx] == USB20H_CORE_ID)) ++ ++/* EROM parsing */ ++ ++static uint32 ++get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match) ++{ ++ uint32 ent; ++ uint inv = 0, nom = 0; ++ ++ while (TRUE) { ++#if defined(CONFIG_MACH_NS) ++ ent = R_REG(si_osh(sih), *eromptr); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_HR2) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_NSP) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_KT2) ++ ent = **eromptr; ++#endif ++ ++ (*eromptr)++; ++ ++ if (mask == 0) ++ break; ++ ++ if ((ent & ER_VALID) == 0) { ++ inv++; ++ continue; ++ } ++ ++ if (ent == (ER_END | ER_VALID)) ++ break; ++ ++ if ((ent & mask) == match) ++ break; ++ ++ nom++; ++ } ++ ++ SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent)); ++ if (inv + nom) { ++ SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom)); ++ } ++ return ent; ++} ++ ++static uint32 ++get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh, ++ uint32 *sizel, uint32 *sizeh) ++{ ++ uint32 asd, sz, szd; ++ ++ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); ++ if (((asd & ER_TAG1) != ER_ADD) || ++ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || ++ ((asd & AD_ST_MASK) != st)) { ++ /* This is not what we want, "push" it back */ ++ (*eromptr)--; ++ return 0; ++ } ++ *addrl = asd & AD_ADDR_MASK; ++ if (asd & AD_AG32) ++ *addrh = get_erom_ent(sih, eromptr, 0, 0); ++ else ++ *addrh = 0; ++ *sizeh = 0; ++ sz = asd & AD_SZ_MASK; ++ if (sz == AD_SZ_SZD) { ++ szd = get_erom_ent(sih, eromptr, 0, 0); ++ *sizel = szd & SD_SZ_MASK; ++ if (szd & SD_SG32) ++ *sizeh = get_erom_ent(sih, eromptr, 0, 0); ++ } else ++ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); ++ ++ SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n", ++ sp, ad, st, *sizeh, *sizel, *addrh, *addrl)); ++ ++ return asd; ++} ++ ++static void ++ai_hwfixup(si_info_t *sii) ++{ ++#ifdef _CFE_ ++ /* Fixup the interrupts in 4716 for i2s core so that ai_flag ++ * works without having to look at the core sinking the ++ * interrupt. We should have done this as the hardware default. ++ * ++ * Future chips should allocate interrupt lines in order (meaning ++ * no line should be skipped), without regard for core index. ++ */ ++ if (BUSTYPE(sii->pub.bustype) == SI_BUS && ++ ((CHIPID(sii->pub.chip) == BCM4716_CHIP_ID) || ++ (CHIPID(sii->pub.chip) == BCM4748_CHIP_ID))) { ++ aidmp_t *i2s, *pcie, *cpu; ++ ++ ASSERT(sii->coreid[3] == MIPS74K_CORE_ID); ++ cpu = REG_MAP(sii->wrapba[3], SI_CORE_SIZE); ++ ASSERT(sii->coreid[5] == PCIE_CORE_ID); ++ pcie = REG_MAP(sii->wrapba[5], SI_CORE_SIZE); ++ ASSERT(sii->coreid[8] == I2S_CORE_ID); ++ i2s = REG_MAP(sii->wrapba[8], SI_CORE_SIZE); ++ if ((R_REG(sii->osh, &cpu->oobselina74) != 0x08060504) || ++ (R_REG(sii->osh, &pcie->oobselina74) != 0x08060504) || ++ (R_REG(sii->osh, &i2s->oobselouta30) != 0x88)) { ++ SI_VMSG(("Unexpected oob values, not fixing i2s interrupt\n")); ++ } else { ++ /* Move i2s interrupt to oob line 7 instead of 8 */ ++ W_REG(sii->osh, &cpu->oobselina74, 0x07060504); ++ W_REG(sii->osh, &pcie->oobselina74, 0x07060504); ++ W_REG(sii->osh, &i2s->oobselouta30, 0x87); ++ SI_VMSG(("Changed i2s interrupt to use oob line 7 instead of 8\n")); ++ } ++ } ++#endif /* _CFE_ */ ++} ++ ++struct _corerev_entry { ++ uint corerev; ++ uint corerev_alias; ++}; ++static struct _corerev_entry bcm4706_corerev_cc[] = { ++ { 0x1f, CC_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++static struct _corerev_entry bcm4706_corerev_socsram[] = { ++ { 0x05, SOCRAM_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++static struct _corerev_entry bcm4706_corerev_gmac[] = { ++ { 0x00, GMAC_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++ ++struct _coreid_entry { ++ uint coreid; ++ uint coreid_alias; ++}; ++static struct _coreid_entry bcm4706_coreid_table[] = { ++ { CC_4706_CORE_ID, CC_CORE_ID }, ++ { SOCRAM_4706_CORE_ID, SOCRAM_CORE_ID }, ++ { GMAC_4706_CORE_ID, GMAC_CORE_ID }, ++ { 0, 0 } ++}; ++ ++static uint ++remap_coreid(si_t *sih, uint coreid) ++{ ++ struct _coreid_entry *coreid_table = NULL; ++ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) ++ coreid_table = &bcm4706_coreid_table[0]; ++ ++ if (coreid_table != NULL) { ++ uint i; ++ ++ for (i = 0; coreid_table[i].coreid; i++) { ++ if (coreid_table[i].coreid == coreid) ++ return coreid_table[i].coreid_alias; ++ } ++ } ++ ++ return coreid; ++} ++ ++static uint ++remap_corerev(si_t *sih, uint corerev) ++{ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) { ++ si_info_t *sii = SI_INFO(sih); ++ uint i, coreid = sii->coreid[sii->curidx]; ++ struct _corerev_entry *corerev_table = NULL; ++ ++ if (coreid == CC_CORE_ID) ++ corerev_table = bcm4706_corerev_cc; ++ else if (coreid == GMAC_CORE_ID) ++ corerev_table = bcm4706_corerev_gmac; ++ else if (coreid == SOCRAM_CORE_ID) ++ corerev_table = bcm4706_corerev_socsram; ++ if (corerev_table != NULL) { ++ for (i = 0; corerev_table[i].corerev_alias; i++) ++ if (corerev_table[i].corerev == corerev) ++ return corerev_table[i].corerev_alias; ++ } ++ } ++ ++ return corerev; ++} ++ ++/* parse the enumeration rom to identify all cores */ ++void ++BCMATTACHFN(ai_scan)(si_t *sih, void *regs, uint devid) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = (chipcregs_t *)regs; ++ uint32 erombase, *eromptr, *eromlim; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++#if defined(CONFIG_MACH_NS) ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ eromptr = hx4_erom; ++#elif defined(CONFIG_MACH_HR2) ++ eromptr = hr2_erom; ++#elif defined(CONFIG_MACH_NSP) ++ eromptr = nsp_erom; ++#elif defined(CONFIG_MACH_KT2) ++ eromptr = kt2_erom; ++#endif ++ break; ++ ++ case PCI_BUS: ++ /* Set wrappers address */ ++ sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE); ++ ++ /* Now point the window at the erom */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase); ++ eromptr = regs; ++ break; ++ ++ ++ case PCMCIA_BUS: ++ default: ++ SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype)); ++ ASSERT(0); ++ return; ++ } ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", ++ regs, erombase, eromptr, eromlim)); ++ while (eromptr < eromlim) { ++ uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; ++ uint32 mpd, asd, addrl, addrh, sizel, sizeh; ++ uint i, j, idx; ++ bool br; ++ ++ br = FALSE; ++ ++ /* Grok a component */ ++ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); ++ if (cia == (ER_END | ER_VALID)) { ++ SI_VMSG(("Found END of erom after %d cores\n", sii->numcores)); ++ ai_hwfixup(sii); ++ return; ++ } ++ ++ cib = get_erom_ent(sih, &eromptr, 0, 0); ++ ++ if ((cib & ER_TAG) != ER_CI) { ++ SI_ERROR(("CIA not followed by CIB\n")); ++ goto error; ++ } ++ ++ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; ++ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; ++ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++#ifdef BCMDBG_SI ++ SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " ++ "nsw = %d, nmp = %d & nsp = %d\n", ++ mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp)); ++#else ++ BCM_REFERENCE(crev); ++#endif ++ ++ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) ++ continue; ++ if ((nmw + nsw == 0)) { ++ /* A component which is not a core */ ++ if (cid == OOB_ROUTER_CORE_ID) { ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd != 0) { ++ sii->oob_router = addrl; ++ } ++ } ++ if (cid != GMAC_COMMON_4706_CORE_ID) ++ continue; ++ } ++ ++ idx = sii->numcores; ++ ++ sii->cia[idx] = cia; ++ sii->cib[idx] = cib; ++ sii->coreid[idx] = remap_coreid(sih, cid); ++ ++ for (i = 0; i < nmp; i++) { ++ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ if ((mpd & ER_TAG) != ER_MP) { ++ SI_ERROR(("Not enough MP entries for component 0x%x\n", cid)); ++ goto error; ++ } ++ SI_VMSG((" Master port %d, mp: %d id: %d\n", i, ++ (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT, ++ (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT)); ++ } ++ ++ /* First Slave Address Descriptor should be port 0: ++ * the main register space for the core ++ */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ do { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd != 0) ++ br = TRUE; ++ else { ++ if (br == TRUE) { ++ break; ++ } ++ else if ((addrh != 0) || (sizeh != 0) || ++ (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 =" ++ "0x%x\n", addrh, sizeh, sizel)); ++ SI_ERROR(("First Slave ASD for" ++ "core 0x%04x malformed " ++ "(0x%08x)\n", cid, asd)); ++ goto error; ++ } ++ } ++ } while (1); ++ } ++ sii->coresba[idx] = addrl; ++ sii->coresba_size[idx] = sizel; ++ /* Get any more ASDs in port 0 */ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { ++ sii->coresba2[idx] = addrl; ++ sii->coresba2_size[idx] = sizel; ++ } ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ ++ if (asd == 0) ++ break; ++ j++; ++ } while (1); ++ if (j == 0) { ++ SI_ERROR((" SP %d has no address descriptors\n", i)); ++ goto error; ++ } ++ } ++ ++ /* Now get master wrappers */ ++ for (i = 0; i < nmw; i++) { ++ asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ SI_ERROR(("Missing descriptor for MW %d\n", i)); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("Master wrapper %d is not 4KB\n", i)); ++ goto error; ++ } ++ if (i == 0) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* And finally slave wrappers */ ++ for (i = 0; i < nsw; i++) { ++ uint fwp = (nsp == 1) ? 0 : 1; ++ asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ SI_ERROR(("Missing descriptor for SW %d\n", i)); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("Slave wrapper %d is not 4KB\n", i)); ++ goto error; ++ } ++ if ((nmw == 0) && (i == 0)) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) { ++ /* Check if it's a low cost package */ ++ i = (R_REG(sii->osh, &cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ if (i == BCM4706L_PKG_ID) { ++ /* bcm4706L: only one GMAC */ ++ if (cid == GMAC_4706_CORE_ID) { ++ for (j = 0; j < sii->numcores; j++) { ++ if (sii->coreid[j] == GMAC_CORE_ID) ++ break; ++ } ++ if (j != sii->numcores) { ++ /* Found one GMAC already, ignore this one */ ++ continue; ++ } ++ } ++ } ++ } ++ ++ /* Don't record bridges */ ++ if (br) ++ continue; ++ ++ /* Done with core */ ++ sii->numcores++; ++ } ++ ++ SI_ERROR(("Reached end of erom without finding END")); ++ ++error: ++ sii->numcores = 0; ++ return; ++} ++ ++/* This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. ++ */ ++void * ++ai_setcoreidx(si_t *sih, uint coreidx) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 addr, wrap; ++ void *regs; ++ ++ if (coreidx >= MIN(sii->numcores, SI_MAXCORES)) ++ return (NULL); ++ ++ addr = sii->coresba[coreidx]; ++ wrap = sii->wrapba[coreidx]; ++ ++ /* ++ * If the user has provided an interrupt mask enabled function, ++ * then assert interrupts are disabled before switching the core. ++ */ ++ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ /* map new one */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ sii->curmap = regs = sii->regs[coreidx]; ++ if (!sii->wrappers[coreidx]) { ++ sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->wrappers[coreidx])); ++ } ++ sii->curwrap = sii->wrappers[coreidx]; ++ break; ++ ++ case PCI_BUS: ++ /* point bar0 window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr); ++ regs = sii->curmap; ++ /* point bar0 2nd 4KB window to the primary wrapper */ ++ if (PCIE_GEN2(sii)) ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap); ++ else ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap); ++ break; ++ ++ ++ case PCMCIA_BUS: ++ default: ++ ASSERT(0); ++ regs = NULL; ++ break; ++ } ++ ++ sii->curmap = regs; ++ sii->curidx = coreidx; ++ ++ return regs; ++} ++ ++void ++ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = NULL; ++ uint32 erombase, *eromptr, *eromlim; ++ uint i, j, cidx; ++ uint32 cia, cib, nmp, nsp; ++ uint32 asd, addrl, addrh, sizel, sizeh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ if (sii->coreid[i] == CC_CORE_ID) { ++ cc = (chipcregs_t *)sii->regs[i]; ++ break; ++ } ++ } ++ if (cc == NULL) ++ goto error; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ cidx = sii->curidx; ++ cia = sii->cia[cidx]; ++ cib = sii->cib[cidx]; ++ ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++ /* scan for cores */ ++ while (eromptr < eromlim) { ++ if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) && ++ (get_erom_ent(sih, &eromptr, 0, 0) == cib)) { ++ break; ++ } ++ } ++ ++ /* skip master ports */ ++ for (i = 0; i < nmp; i++) ++ get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ ++ /* Skip ASDs in port 0 */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ } ++ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) ++ break; ++ ++ if (!asidx--) { ++ *addr = addrl; ++ *size = sizel; ++ return; ++ } ++ j++; ++ } while (1); ++ ++ if (j == 0) { ++ SI_ERROR((" SP %d has no address descriptors\n", i)); ++ break; ++ } ++ } ++ ++error: ++ *size = 0; ++ return; ++} ++ ++/* Return the number of address spaces in current core */ ++int ++ai_numaddrspaces(si_t *sih) ++{ ++ return 2; ++} ++ ++/* Return the address of the nth address space in the current core */ ++uint32 ++ai_addrspace(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2[cidx]; ++ else { ++ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx)); ++ return 0; ++ } ++} ++ ++/* Return the size of the nth address space in the current core */ ++uint32 ++ai_addrspacesize(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba_size[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2_size[cidx]; ++ else { ++ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx)); ++ return 0; ++ } ++} ++ ++uint ++ai_flag(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__)); ++ return sii->curidx; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__)); ++ return sii->curidx; ++ } ++ ai = sii->curwrap; ++//printf("ai=%p, oobselouta30=0x%x\n", ai, R_REG(sii->osh, &ai->oobselouta30)); ++ return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); ++} ++ ++void ++ai_setint(si_t *sih, int siflag) ++{ ++} ++ ++uint ++ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 *map = (uint32 *) sii->curwrap; ++ ++ if (mask || val) { ++ uint32 w = R_REG(sii->osh, map+(offset/4)); ++ w &= ~mask; ++ w |= val; ++ W_REG(sii->osh, map+(offset/4), val); ++ } ++ ++ return (R_REG(sii->osh, map+(offset/4))); ++} ++ ++uint ++ai_corevendor(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cia; ++ ++ sii = SI_INFO(sih); ++ cia = sii->cia[sii->curidx]; ++ return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT); ++} ++ ++uint ++ai_corerev(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cib; ++ ++ sii = SI_INFO(sih); ++ cib = sii->cib[sii->curidx]; ++ return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT); ++} ++ ++bool ++ai_iscoreup(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ ++ return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) && ++ ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0)); ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, ++ * switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fiddling with interrupts or core switches is needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers ++ * and (on newer pci cores) chipcommon registers. ++ */ ++uint ++ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ uint origidx = 0; ++ uint32 *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = FALSE; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODIDX(coreidx)); ++ ASSERT(regoff < SI_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) { ++ /* If internal bus, we can always get at everything */ ++ fast = TRUE; ++ /* map if does not exist */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], ++ SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff); ++ } else if (BUSTYPE(sih->bustype) == PCI_BUS) { ++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ ++ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ ++ fast = TRUE; ++ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* pci registers are at either in the last 2KB of an 8KB window ++ * or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = TRUE; ++ if (SI_FAST(sii)) ++ r = (uint32 *)((char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (uint32 *)((char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + ++ regoff); ++ } ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = si_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ASSERT(r != NULL); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_REG(sii->osh, r) & ~mask) | val; ++ W_REG(sii->osh, r, w); ++ } ++ ++ /* readback */ ++ w = R_REG(sii->osh, r); ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return (w); ++} ++ ++void ++ai_core_disable(si_t *sih, uint32 bits) ++{ ++ si_info_t *sii; ++ volatile uint32 dummy; ++ uint32 status; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ /* if core is already in reset, just return */ ++ if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) ++ return; ++ ++ /* ensure there are no pending backplane operations */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); ++ ++ /* if pending backplane ops still, try waiting longer */ ++ if (status != 0) { ++ /* 300usecs was sufficient to allow backplane ops to clear for big hammer */ ++ /* during driver load we may need more time */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000); ++ /* if still pending ops, continue on and try disable anyway */ ++ /* this is in big hammer path, so don't call wl_reinit in this case... */ ++#ifdef BCMDBG ++ if (status != 0) { ++ printf("%s: WARN: resetstatus=%0x on core disable\n", __FUNCTION__, status); ++ } ++#endif ++ } ++ ++ W_REG(sii->osh, &ai->ioctrl, bits); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(10); ++ ++ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ++ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ volatile uint32 dummy; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ bits = resetbits = R_REG(sii->osh, &ai->ioctrl) & 0xFFFFFFFC; ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ ai_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ ++ W_REG(sii->osh, &ai->resetctrl, 0); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++void ++ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__)); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__)); ++ return; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++} ++ ++uint32 ++ai_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__)); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__)); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++ ++ return R_REG(sii->osh, &ai->ioctrl); ++} ++ ++uint32 ++ai_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", ++ __FUNCTION__)); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n", ++ __FUNCTION__)); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SISF_CORE_BITS) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); ++ W_REG(sii->osh, &ai->iostatus, w); ++ } ++ ++ return R_REG(sii->osh, &ai->iostatus); ++} ++ ++#if defined(BCMDBG) ++/* print interesting aidmp registers */ ++void ++ai_dumpregs(si_t *sih, struct bcmstrbuf *b) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ osh = sii->osh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(&sii->pub, i); ++ ai = sii->curwrap; ++ ++ bcm_bprintf(b, "core 0x%x: \n", sii->coreid[i]); ++ if (BCM47162_DMP()) { ++ bcm_bprintf(b, "Skipping mips74k in 47162a0\n"); ++ continue; ++ } ++ if (BCM5357_DMP()) { ++ bcm_bprintf(b, "Skipping usb20h in 5357\n"); ++ continue; ++ } ++ ++ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" ++ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" ++ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n" ++ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" ++ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" ++ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" ++ "intstatus 0x%x config 0x%x itcr 0x%x\n", ++ R_REG(osh, &ai->ioctrlset), ++ R_REG(osh, &ai->ioctrlclear), ++ R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->ioctrlwidth), ++ R_REG(osh, &ai->iostatuswidth), ++ R_REG(osh, &ai->resetctrl), ++ R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), ++ R_REG(osh, &ai->resetwriteid), ++ R_REG(osh, &ai->errlogctrl), ++ R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), ++ R_REG(osh, &ai->errlogaddrlo), ++ R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogid), ++ R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), ++ R_REG(osh, &ai->intstatus), ++ R_REG(osh, &ai->config), ++ R_REG(osh, &ai->itcr)); ++ if ((sih->chip == BCM4331_CHIP_ID) && (sii->coreid[i] == PCIE_CORE_ID)) { ++ /* point bar0 2nd 4KB window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18103000); ++ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" ++ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" ++ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x" ++ " resetwriteid 0x%x\n" ++ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" ++ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" ++ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" ++ "intstatus 0x%x config 0x%x itcr 0x%x\n", ++ R_REG(osh, &ai->ioctrlset), ++ R_REG(osh, &ai->ioctrlclear), ++ R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->ioctrlwidth), ++ R_REG(osh, &ai->iostatuswidth), ++ R_REG(osh, &ai->resetctrl), ++ R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), ++ R_REG(osh, &ai->resetwriteid), ++ R_REG(osh, &ai->errlogctrl), ++ R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), ++ R_REG(osh, &ai->errlogaddrlo), ++ R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogid), ++ R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), ++ R_REG(osh, &ai->intstatus), ++ R_REG(osh, &ai->config), ++ R_REG(osh, &ai->itcr)); ++ /* bar0 2nd 4KB window will be fixed in the next setcore */ ++ } ++ } ++} ++#endif ++ ++#ifdef BCMDBG ++static void ++_ai_view(osl_t *osh, aidmp_t *ai, uint32 cid, uint32 addr, bool verbose) ++{ ++ uint32 config; ++ ++ config = R_REG(osh, &ai->config); ++ SI_ERROR(("\nCore ID: 0x%x, addr 0x%x, config 0x%x\n", cid, addr, config)); ++ ++ if (config & AICFG_RST) ++ SI_ERROR(("resetctrl 0x%x, resetstatus 0x%x, resetreadid 0x%x, resetwriteid 0x%x\n", ++ R_REG(osh, &ai->resetctrl), R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), R_REG(osh, &ai->resetwriteid))); ++ ++ if (config & AICFG_IOC) ++ SI_ERROR(("ioctrl 0x%x, width %d\n", R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->ioctrlwidth))); ++ ++ if (config & AICFG_IOS) ++ SI_ERROR(("iostatus 0x%x, width %d\n", R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->iostatuswidth))); ++ ++ if (config & AICFG_ERRL) { ++ SI_ERROR(("errlogctrl 0x%x, errlogdone 0x%x, errlogstatus 0x%x, intstatus 0x%x\n", ++ R_REG(osh, &ai->errlogctrl), R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), R_REG(osh, &ai->intstatus))); ++ SI_ERROR(("errlogid 0x%x, errloguser 0x%x, errlogflags 0x%x, errlogaddr " ++ "0x%x/0x%x\n", ++ R_REG(osh, &ai->errlogid), R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogaddrlo))); ++ } ++ ++ if (verbose && (config & AICFG_OOB)) { ++ SI_ERROR(("oobselina30 0x%x, oobselina74 0x%x\n", ++ R_REG(osh, &ai->oobselina30), R_REG(osh, &ai->oobselina74))); ++ SI_ERROR(("oobselinb30 0x%x, oobselinb74 0x%x\n", ++ R_REG(osh, &ai->oobselinb30), R_REG(osh, &ai->oobselinb74))); ++ SI_ERROR(("oobselinc30 0x%x, oobselinc74 0x%x\n", ++ R_REG(osh, &ai->oobselinc30), R_REG(osh, &ai->oobselinc74))); ++ SI_ERROR(("oobselind30 0x%x, oobselind74 0x%x\n", ++ R_REG(osh, &ai->oobselind30), R_REG(osh, &ai->oobselind74))); ++ SI_ERROR(("oobselouta30 0x%x, oobselouta74 0x%x\n", ++ R_REG(osh, &ai->oobselouta30), R_REG(osh, &ai->oobselouta74))); ++ SI_ERROR(("oobseloutb30 0x%x, oobseloutb74 0x%x\n", ++ R_REG(osh, &ai->oobseloutb30), R_REG(osh, &ai->oobseloutb74))); ++ SI_ERROR(("oobseloutc30 0x%x, oobseloutc74 0x%x\n", ++ R_REG(osh, &ai->oobseloutc30), R_REG(osh, &ai->oobseloutc74))); ++ SI_ERROR(("oobseloutd30 0x%x, oobseloutd74 0x%x\n", ++ R_REG(osh, &ai->oobseloutd30), R_REG(osh, &ai->oobseloutd74))); ++ SI_ERROR(("oobsynca 0x%x, oobseloutaen 0x%x\n", ++ R_REG(osh, &ai->oobsynca), R_REG(osh, &ai->oobseloutaen))); ++ SI_ERROR(("oobsyncb 0x%x, oobseloutben 0x%x\n", ++ R_REG(osh, &ai->oobsyncb), R_REG(osh, &ai->oobseloutben))); ++ SI_ERROR(("oobsyncc 0x%x, oobseloutcen 0x%x\n", ++ R_REG(osh, &ai->oobsyncc), R_REG(osh, &ai->oobseloutcen))); ++ SI_ERROR(("oobsyncd 0x%x, oobseloutden 0x%x\n", ++ R_REG(osh, &ai->oobsyncd), R_REG(osh, &ai->oobseloutden))); ++ SI_ERROR(("oobaextwidth 0x%x, oobainwidth 0x%x, oobaoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobaextwidth), R_REG(osh, &ai->oobainwidth), ++ R_REG(osh, &ai->oobaoutwidth))); ++ SI_ERROR(("oobbextwidth 0x%x, oobbinwidth 0x%x, oobboutwidth 0x%x\n", ++ R_REG(osh, &ai->oobbextwidth), R_REG(osh, &ai->oobbinwidth), ++ R_REG(osh, &ai->oobboutwidth))); ++ SI_ERROR(("oobcextwidth 0x%x, oobcinwidth 0x%x, oobcoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobcextwidth), R_REG(osh, &ai->oobcinwidth), ++ R_REG(osh, &ai->oobcoutwidth))); ++ SI_ERROR(("oobdextwidth 0x%x, oobdinwidth 0x%x, oobdoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobdextwidth), R_REG(osh, &ai->oobdinwidth), ++ R_REG(osh, &ai->oobdoutwidth))); ++ } ++} ++ ++void ++ai_view(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint32 cid, addr; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ osh = sii->osh; ++ if (BCM47162_DMP()) { ++ SI_ERROR(("Cannot access mips74k DMP in 47162a0\n")); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("Cannot access usb20h DMP in 5357\n")); ++ return; ++ } ++ cid = sii->coreid[sii->curidx]; ++ addr = sii->wrapba[sii->curidx]; ++ _ai_view(osh, ai, cid, addr, verbose); ++} ++ ++void ++ai_viewall(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint32 cid, addr; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ osh = sii->osh; ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(sih, i); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("Skipping mips74k DMP in 47162a0\n")); ++ continue; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("Skipping usb20h DMP in 5357\n")); ++ continue; ++ } ++ ai = sii->curwrap; ++ cid = sii->coreid[sii->curidx]; ++ addr = sii->wrapba[sii->curidx]; ++ _ai_view(osh, ai, cid, addr, verbose); ++ if ((sih->chip == BCM4331_CHIP_ID) && (sii->coreid[i] == PCIE_CORE_ID)) { ++ /* point bar0 2nd 4KB window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18103000); ++ _ai_view(osh, ai, cid, 0x18103000, verbose); ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18104000); ++ _ai_view(osh, ai, 0x135, 0x18104000, verbose); ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18105000); ++ _ai_view(osh, ai, 0x135, 0x18105000, verbose); ++ /* bar0 2nd 4KB window will be fixed in the next setcore */ ++ } ++ } ++} ++#endif /* BCMDBG */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c +new file mode 100755 +index 0000000..58e66fc diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch new file mode 100644 index 00000000..b75529ac --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch @@ -0,0 +1,515 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c +@@ -0,0 +1,509 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "../../../mdio/iproc_mdio.h" ++#include "bcmiproc_phy.h" ++#include "bcmiproc_phy5221.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++ ++/* ==== Public Functions ================================================= */ ++ ++int ++phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ uint16 wr_data=*data; ++ uint16 test_reg; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data)); ++ //printf("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } ++ return SOC_E_NONE; ++} ++ ++ ++int ++phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ uint16 test_reg; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to read phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr)); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ } ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, *data)); ++ //printf("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); ++ return SOC_E_NONE; ++} ++ ++ ++int ++phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask) ++{ ++ uint16 test_reg; ++ uint16 org_data, rd_data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, data, mask)); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ } ++ //printf("%s modified(0x%x to 0x%x) at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); ++ ++ return SOC_E_NONE; ++} ++ ++ ++void ++phy5221_fe_reset(uint eth_num, uint phyaddr) ++{ ++ uint16 ctrl; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ctrl |= MII_CTRL_RESET; ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ++ SPINWAIT( (!phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) ++ && (ctrl & MII_CTRL_RESET)), 100000); ++ /* check if out of reset */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ if (ctrl & MII_CTRL_RESET) { ++ /* timeout */ ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } else { ++ NET_ERROR(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); ++ } ++ ++ return; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_fe_init ++ * Purpose: ++ * Initialize the PHY (MII mode) to a known good state. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * Returns: ++ * SOC_E_XXX ++ ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5221_fe_init(uint eth_num, uint phyaddr) ++{ ++ uint16 mii_ana, mii_ctrl; ++ ++ /* Reset PHY */ ++ phy5221_fe_reset(eth_num, phyaddr); ++ ++ mii_ana = MII_ANA_HD_10 | MII_ANA_FD_10 | MII_ANA_HD_100 | ++ MII_ANA_FD_100 | MII_ANA_ASF_802_3; ++ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_100 | MII_CTRL_AE | MII_CTRL_RAN; ++ ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5221_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_init(uint eth_num, uint phyaddr) ++{ ++ uint16 phyid0, phyid1; ++ uint16 tmp = 0; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); ++ ++ //printf("%s phyaddr(0x%x) Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyaddr, phyid1, phyid0); ++ ++ phy5221_fe_init(eth_num, phyaddr); ++ ++ phy5221_rd_reg(eth_num, phyaddr, 0, 0x16, &tmp); ++ tmp = 2; ++ phy5221_wr_reg(eth_num, phyaddr, 0, 0x16, &tmp); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_link_get ++ * Purpose: ++ * Determine the current link up/down status ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5221_link_get(uint eth_num, uint phyaddr, int *link) ++{ ++ uint16 mii_ctrl, mii_stat; ++ uint32 wait; ++ ++ *link = FALSE; /* Default */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ /* the first read of status register will not show link up, second read will show link up */ ++ if (!(mii_stat & MII_STAT_LA) ) { ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ } ++ ++ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { ++ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ ++ return SOC_E_NONE; ++ } ++ ++ /* Link appears to be up; we are done if autoneg is off. */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ if (!(mii_ctrl & MII_CTRL_AE)) { ++ *link = TRUE; ++ return SOC_E_NONE; ++ } ++ ++ /* ++ * If link appears to be up but autonegotiation is still in ++ * progress, wait for it to complete. For BCM5228, autoneg can ++ * still be busy up to about 200 usec after link is indicated. Also ++ * continue to check link state in case it goes back down. ++ * wait 500ms (500000us/10us = 50000 ) ++ */ ++ for (wait=0; wait<50000; wait++) { ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (!(mii_stat & MII_STAT_LA)) { ++ /* link is down */ ++ return SOC_E_NONE; ++ } ++ ++ if (mii_stat & MII_STAT_AN_DONE) { ++ /* AutoNegotiation done */ ++ break; ++ } ++ ++ OSL_DELAY(10); ++ } ++ if (wait>=50000) { ++ /* timeout */ ++ return SOC_E_BUSY; ++ } ++ ++ /* Return link state at end of polling */ ++ *link = ((mii_stat & MII_STAT_LA) != 0); ++ ++ return SOC_E_NONE; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_enable_set(uint eth_num, uint phyaddr, int enable) ++{ ++ uint16 data; /* New value to write to PHY register */ ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ data = enable ? 0 : MII_ECR_TD; /* Transmitt enable/disable */ ++ phy5221_mod_reg(eth_num, phyaddr, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, data, MII_ECR_TD); ++ ++ data = enable ? 0 : PHY522X_SUPER_ISOLATE_MODE; ++ /* Device needs to be put in super-isolate mode in order to disable ++ * the link in 10BaseT mode ++ */ ++ phy5221_mod_reg(eth_num, phyaddr, PHY_AUX_MULTIPLE_PHYr_BANK, PHY_AUX_MULTIPLE_PHYr_ADDR, ++ data, PHY522X_SUPER_ISOLATE_MODE); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5221_auto_negotiate_gcd (greatest common denominator). ++ * Purpose: ++ * Determine the current greatest common denominator between ++ * two ends of a link ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * speed - (OUT) greatest common speed. ++ * duplex - (OUT) greatest common duplex. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++static int ++phy5221_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int t_speed, t_duplex; ++ uint16 mii_ana, mii_anp, mii_stat; ++ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; ++ ++ mii_gb_stat = 0; /* Start off 0 */ ++ mii_gb_ctrl = 0; /* Start off 0 */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ ++ /* ++ * If the PHY supports extended status, check if it is 1000MB ++ * capable. If it is, check the 1000Base status register to see ++ * if 1000MB negotiated. ++ */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); ++ ++ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | ++ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ } ++ } ++ ++ /* ++ * At this point, if we did not see Gig status, one of mii_gb_stat or ++ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to ++ * fail and fall into the default 10/100 cases. ++ */ ++ ++ mii_ana &= mii_anp; ++ ++ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { ++ t_speed = 1000; ++ t_duplex = 1; ++ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { ++ t_speed = 1000; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ ++ t_speed = 100; ++ t_duplex = 1; ++ } else if (mii_ana & MII_ANA_T4) { /* [b] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ ++ t_speed = 10; ++ t_duplex = 1 ; ++ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ ++ t_speed = 10; ++ t_duplex = 0; ++ } else { ++ return(SOC_E_FAIL); ++ } ++ ++ if (speed) *speed = t_speed; ++ if (duplex) *duplex = t_duplex; ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5221_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int rv; ++ uint16 mii_ctrl, mii_stat; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ *speed = 0; ++ *duplex = 0; ++ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ ++ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ ++ rv = SOC_E_NONE; ++ } else { ++ rv = phy5221_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); ++ } ++ } else { /* Auto-negotiation disabled */ ++ /* ++ * Simply pick up the values we force in CTRL register. ++ */ ++ if (mii_ctrl & MII_CTRL_FD) ++ *duplex = 1; ++ ++ switch(MII_CTRL_SS(mii_ctrl)) { ++ case MII_CTRL_SS_10: ++ *speed = 10; ++ break; ++ case MII_CTRL_SS_100: ++ *speed = 100; ++ break; ++ case MII_CTRL_SS_1000: ++ *speed = 1000; ++ break; ++ default: /* Just pass error back */ ++ return(SOC_E_UNAVAIL); ++ } ++ rv = SOC_E_NONE; ++ } ++ ++ return(rv); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c +new file mode 100755 +index 0000000..6b2391d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch new file mode 100644 index 00000000..c937af31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch @@ -0,0 +1,740 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c +@@ -0,0 +1,734 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "../../../mdio/iproc_mdio.h" ++#include "bcmiproc_phy.h" ++#include "bcmiproc_phy5461s.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++ ++/* ==== Public Functions ================================================= */ ++ ++int ++phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ int rv = SOC_E_NONE; ++ uint16 wr_data=*data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to write phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data)); ++ //printf("%s phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data); ++ ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* write 1000X IEEE register */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else if (flags & _SOC_PHY_REG_DIRECT) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ if (reg_bank == 0x0007) { ++ wr_data |= 0x8000; ++ } ++ wr_data = (wr_data & ~(0x0007)) | reg_bank; ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ wr_data = 0x8000 | (reg_bank << 10) | (wr_data & 0x03FF); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not write to reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } ++ } ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } ++ return rv; ++} ++ ++ ++int ++phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ int rv = SOC_E_NONE; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to read phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr)); ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* Read 1000X IEEE register */ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not read from reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); ++ } ++ } ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } else { ++ //printf("%s phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); ++ } ++ ++ return rv; ++} ++ ++ ++int ++phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask) ++{ ++ int rv = SOC_E_NONE; ++ uint16 org_data, rd_data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, data, mask)); ++ ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* Modify 1000X IEEE register */ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); ++ ++ if (reg_bank == 0x0007) { ++ data |= 0x8000; ++ mask |= 0x8000; ++ } ++ mask &= ~(0x0007); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); ++ data |= 0x8000; ++ mask |= 0x8000; ++ mask &= ~(0x1F << 10); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not write to reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ } ++ } ++ ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } else { ++ //printf("%s modified(0x%x to 0x%x at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); ++ } ++ ++ return rv; ++} ++ ++ ++void ++phy5461_ge_reset(uint eth_num, uint phyaddr) ++{ ++ uint16 ctrl; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ctrl |= MII_CTRL_RESET; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ++ SPINWAIT( (!phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) ++ && (ctrl & MII_CTRL_RESET)), 100000); ++ /* check if out of reset */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ if (ctrl & MII_CTRL_RESET) { ++ /* timeout */ ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } else { ++ NET_TRACE(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); ++ } ++} ++ ++ ++/* ++ * Function: ++ * phy5461_ge_interface_set ++ * Purpose: ++ * Set the current operating mode of the PHY. ++ * (Pertaining to the MAC/PHY interface, not the line interface). ++ * For example: TBI or MII/GMII. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * pif - one of SOC_PORT_IF_* ++ * Returns: ++ * SOC_E_XXX ++ */ ++int ++phy5461_ge_interface_set(uint eth_num, uint phyaddr, soc_port_if_t pif) ++{ ++ uint16 mii_ecr; ++ int mii; /* MII if true, TBI otherwise */ ++ ++ switch (pif) { ++ case SOC_PORT_IF_MII: ++ case SOC_PORT_IF_GMII: ++ case SOC_PORT_IF_SGMII: ++ mii = TRUE; ++ break; ++ case SOC_PORT_IF_NOCXN: ++ return (SOC_E_NONE); ++ case SOC_PORT_IF_TBI: ++ mii = FALSE; ++ break; ++ default: ++ return SOC_E_UNAVAIL; ++ } ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); ++ ++ if (mii) { ++ mii_ecr &= ~MII_ECR_10B; ++ } else { ++ mii_ecr |= MII_ECR_10B; ++ } ++ ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5461_ge_init ++ * Purpose: ++ * Initialize the PHY (MII mode) to a known good state. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * Returns: ++ * SOC_E_XXX ++ ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5461_ge_init(uint eth_num, uint phyaddr) ++{ ++ uint16 mii_ctrl, mii_gb_ctrl; ++ uint16 mii_ana; ++ soc_port_if_t pif; ++ ++ /* Reset PHY */ ++ phy5461_ge_reset(eth_num, phyaddr); ++ ++ /* set advertized bits */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ mii_ana |= MII_ANA_FD_100 | MII_ANA_FD_10; ++ mii_ana |= MII_ANA_HD_100 | MII_ANA_HD_10; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ ++ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE | MII_CTRL_RAN; ++ mii_gb_ctrl = MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT; ++ ++ pif = SOC_PORT_IF_GMII; ++ ++ phy5461_ge_interface_set(eth_num, phyaddr, pif); ++ ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ return(SOC_E_NONE); ++} ++ ++ ++ ++ ++void ++phy5461_reset_setup(uint eth_num, uint phyaddr) ++{ ++ uint16 tmp; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ phy5461_ge_init(eth_num, phyaddr); ++ ++ /* copper regs */ ++ /* remove power down */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, 0, MII_CTRL_PD); ++ /* Disable super-isolate */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_POWER_CTRLr_FLAGS, PHY_MII_POWER_CTRLr_BANK, PHY_MII_POWER_CTRLr_ADDR, 0, 1U<<5); ++ /* Enable extended packet length */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_AUX_CTRLr_FLAGS, PHY_MII_AUX_CTRLr_BANK, PHY_MII_AUX_CTRLr_ADDR, 0x4000, 0x4000); ++ ++ /* Configure interface to MAC */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); ++ /* phy5461_ge_init has reset the phy, powering down the unstrapped interface */ ++ /* make sure enabled interfaces are powered up */ ++ /* SGMII (passthrough fiber) or GMII fiber regs */ ++ tmp &= ~MII_CTRL_PD; /* remove power down */ ++ /* ++ * Enable SGMII autonegotiation on the switch side so that the ++ * link status changes are reflected in the switch. ++ * On Bradley devices, LAG failover feature depends on the SerDes ++ * link staus to activate failover recovery. ++ */ ++ tmp |= MII_CTRL_AE; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); ++ ++ return; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_init(uint eth_num, uint phyaddr) ++{ ++ uint16 phyid0, phyid1; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_FLAGS, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_FLAGS, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); ++ ++ printf("%s Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyid1, phyid0); ++ ++ phy5461_reset_setup(eth_num, phyaddr); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_link_get ++ * Purpose: ++ * Determine the current link up/down status ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5461_link_get(uint eth_num, uint phyaddr, int *link) ++{ ++ uint16 mii_ctrl, mii_stat; ++ uint32 wait; ++ ++ *link = FALSE; /* Default */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ /* the first read of status register will not show link up, second read will show link up */ ++ if (!(mii_stat & MII_STAT_LA) ) { ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ } ++ ++ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { ++ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ ++ return SOC_E_NONE; ++ } ++ ++ /* Link appears to be up; we are done if autoneg is off. */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ if (!(mii_ctrl & MII_CTRL_AE)) { ++ *link = TRUE; ++ return SOC_E_NONE; ++ } ++ ++ /* ++ * If link appears to be up but autonegotiation is still in ++ * progress, wait for it to complete. For BCM5228, autoneg can ++ * still be busy up to about 200 usec after link is indicated. Also ++ * continue to check link state in case it goes back down. ++ */ ++ for (wait=0; wait<50000; wait++) { ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (!(mii_stat & MII_STAT_LA)) { ++ /* link is down */ ++ return SOC_E_NONE; ++ } ++ ++ if (mii_stat & MII_STAT_AN_DONE) { ++ /* AutoNegotiation done */ ++ break; ++ } ++ ++ OSL_DELAY(10); ++ } ++ if (wait>=50000) { ++ /* timeout */ ++ return SOC_E_BUSY; ++ } ++ ++ /* Return link state at end of polling */ ++ *link = ((mii_stat & MII_STAT_LA) != 0); ++ ++ return SOC_E_NONE; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_enable_set(uint eth_num, uint phyaddr, int enable) ++{ ++ uint16 power_down; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ power_down = (enable) ? 0 : MII_CTRL_PD; ++ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, power_down, MII_CTRL_PD); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5461_auto_negotiate_gcd (greatest common denominator). ++ * Purpose: ++ * Determine the current greatest common denominator between ++ * two ends of a link ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * speed - (OUT) greatest common speed. ++ * duplex - (OUT) greatest common duplex. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++static int ++phy5461_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int t_speed, t_duplex; ++ uint16 mii_ana, mii_anp, mii_stat; ++ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; ++ ++ mii_gb_stat = 0; /* Start off 0 */ ++ mii_gb_ctrl = 0; /* Start off 0 */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_FLAGS, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ ++ /* ++ * If the PHY supports extended status, check if it is 1000MB ++ * capable. If it is, check the 1000Base status register to see ++ * if 1000MB negotiated. ++ */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_FLAGS, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); ++ ++ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | ++ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_FLAGS, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ } ++ } ++ ++ /* ++ * At this point, if we did not see Gig status, one of mii_gb_stat or ++ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to ++ * fail and fall into the default 10/100 cases. ++ */ ++ ++ mii_ana &= mii_anp; ++ ++ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { ++ t_speed = 1000; ++ t_duplex = 1; ++ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { ++ t_speed = 1000; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ ++ t_speed = 100; ++ t_duplex = 1; ++ } else if (mii_ana & MII_ANA_T4) { /* [b] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ ++ t_speed = 10; ++ t_duplex = 1 ; ++ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ ++ t_speed = 10; ++ t_duplex = 0; ++ } else { ++ return(SOC_E_FAIL); ++ } ++ ++ if (speed) *speed = t_speed; ++ if (duplex) *duplex = t_duplex; ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5461_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int rv; ++ uint16 mii_ctrl, mii_stat; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ *speed = 0; ++ *duplex = 0; ++ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ ++ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ ++ rv = SOC_E_NONE; ++ } else { ++ rv = phy5461_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); ++ } ++ } else { /* Auto-negotiation disabled */ ++ /* ++ * Simply pick up the values we force in CTRL register. ++ */ ++ if (mii_ctrl & MII_CTRL_FD) ++ *duplex = 1; ++ ++ switch(MII_CTRL_SS(mii_ctrl)) { ++ case MII_CTRL_SS_10: ++ *speed = 10; ++ break; ++ case MII_CTRL_SS_100: ++ *speed = 100; ++ break; ++ case MII_CTRL_SS_1000: ++ *speed = 1000; ++ break; ++ default: /* Just pass error back */ ++ return(SOC_E_UNAVAIL); ++ } ++ rv = SOC_E_NONE; ++ } ++ ++ return(rv); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c +new file mode 100755 +index 0000000..add347f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch new file mode 100644 index 00000000..81e750b4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch @@ -0,0 +1,434 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c +@@ -0,0 +1,428 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include ++#include ++#include "bcmiproc_robo_serdes.h" ++#include "bcmiproc_serdes_def.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++/* ==== Public Functions ================================================= */ ++ ++uint16 ++robo_serdes_get_id(robo_info_t *robo, uint page, uint off) ++{ ++ uint16 data; ++ ++ /* read the id high */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESID_SERDESID0r+off, &data); ++ return data; ++} ++ ++ ++void ++robo_serdes_reset(robo_info_t *robo, uint page) ++{ ++ uint16 ctrl; ++ ++ /* set reset flag */ ++ srab_sgmii_rreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ udelay(100); ++ /* check if out of reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ if (ctrl & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { ++ NET_ERROR(("%s page (0x%x) reset not complete\n", __FUNCTION__, page)); ++ } ++} ++ ++ ++int ++robo_serdes_reset_core(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ uint16 serdes_id2; ++ ++ /* get serdes id */ ++ serdes_id2 = robo_serdes_get_id(robo, page, 2); ++ printf("%s page(0x%x) id2(0x%x)\n", __FUNCTION__, page, serdes_id2); ++ ++ /* unlock lane */ ++ srab_sgmii_rreg(robo, page, 0x833c, &data16); ++ data16 &= ~(0x0040); ++ srab_sgmii_wreg(robo, page, 0x833c, &data16); ++ ++ if ( page == PAGE_P5_SGMII ) { ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ ++ /* Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in ++ * IEEE address space. ++ */ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_MISCCONTROL1r, &data16); ++ if (XGXS16G_2p5G_ID(serdes_id2)) { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ } else { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++ } ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_MISCCONTROL1r, &data16); ++ ++ } ++ return 0; ++} ++ ++ ++int ++robo_serdes_start_pll(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ ++ if ( page == PAGE_P5_SGMII ) { ++ uint32 count=250; ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ ++ /* wait for PLL to lock */ ++ while (count!=0) { ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_XGXSSTATUSr, &data16); ++ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { ++ break; ++ } ++ /* wait 1 usec then dec counter */ ++ udelay(10); ++ count--; ++ } ++ if (count == 0) { ++ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_init(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ uint16 serdes_id0, serdes_id1, serdes_id2; ++ uint locpage=page; ++ ++ if ( page == PAGE_P4_SGMII ) { ++ printf("%s access page4 via page5 lane1\n", __FUNCTION__); ++ locpage = PAGE_P5_SGMII; ++ // try to access p4 registers via lane1 ++ data16 = 1; ++ srab_sgmii_wreg(robo, locpage, 0xffde, &data16); ++ } ++ ++ /* get serdes id */ ++ serdes_id0 = robo_serdes_get_id(robo, locpage, 0); ++ serdes_id1 = robo_serdes_get_id(robo, locpage, 1); ++ serdes_id2 = robo_serdes_get_id(robo, locpage, 2); ++ printf("%s page(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, locpage, serdes_id0, serdes_id1, serdes_id2); ++ ++ /* get more ids */ ++ srab_sgmii_rreg(robo, locpage, 2, &serdes_id0); ++ srab_sgmii_rreg(robo, locpage, 3, &serdes_id1); ++ //printf("%s locpage(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, locpage, serdes_id0, serdes_id1); ++ ++ /* unlock lane */ ++ srab_sgmii_rreg(robo, locpage, 0x833c, &data16); ++ data16 &= ~(0x0040); ++ srab_sgmii_wreg(robo, locpage, 0x833c, &data16); ++ ++ /* Must Enable TX polarity flip */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_TX0_TX_ACONTROL0r, &data16); ++ data16 |= TX0_TX_ACONTROL0_TXPOL_FLIP_MASK; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_TX0_TX_ACONTROL0r, &data16); ++ ++ /* disable CL73 BAM */ ++ srab_sgmii_rreg(robo, locpage, 0x8372, &data16); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ srab_sgmii_wreg(robo, locpage, 0x8372, &data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_COMBO_IEEE0_AUTONEGADVr, &data16); ++ ++ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, &data16); ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, &data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK | ++ SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; ++ ++// data16 |= SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK; ++ /* ++ * Put the Serdes in SGMII mode ++ * bit0 = 0; in SGMII mode ++ */ ++ srab_sgmii_wreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, &data16); ++ ++ /* set autoneg */ ++ data16 = MII_CTRL_AE | MII_CTRL_RAN; ++// data16 = MII_CTRL_SS_MSB | MII_CTRL_FD; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_AN73_PDET_PARDET10GCONTROLr, &data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, &data16); ++ ++ /* Enable lanes */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_XGXSBLK1_LANECTRL0r, &data16); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_XGXSBLK1_LANECTRL0r, &data16); ++ ++ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ srab_sgmii_wreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ /* Enabble LPI passthru' for native mode EEE */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_REMOTEPHY_MISC5r, &data16); ++ data16 |= 0xc000; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_REMOTEPHY_MISC5r, &data16); ++ srab_sgmii_rreg(robo, locpage, XGXS16G_XGXSBLK7_EEECONTROLr, &data16); ++ data16 |= 0x0007; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_XGXSBLK7_EEECONTROLr, &data16); ++ ++ if ( page == PAGE_P4_SGMII ) { ++ printf("%s set back to lane0\n", __FUNCTION__); ++ // set back to lane 0 ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, 0xffde, &data16); ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_enable_set(robo_info_t *robo, uint page, int enable) ++{ ++ uint16 data16, mask16; ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK1_LANECTRL3r, &data16); ++ if (page == PAGE_P5_SGMII) ++ /* lane 0 */ ++ mask16 = 1; /* rx lane */ ++ else ++ /* lane 1 */ ++ mask16 = 2; /* rx lane */ ++ mask16 |= (mask16 << 4); /* add tx lane */ ++ mask16 |= 0x800; ++ if (enable) { ++ data16 &= ~(mask16); ++ } else { ++ data16 &= ~(mask16); ++ data16 |= mask16; ++ } ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK1_LANECTRL3r, &data16); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_speed_set ++ * Purpose: ++ * Set PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_speed_set(robo_info_t *robo, uint page, int speed) ++{ ++ uint16 speed_val, mask; ++ uint16 data16; ++ uint16 speed_mii; ++ ++ if (speed > 1000) { ++ return -1; ++ } ++ ++ speed_val = 0; ++ speed_mii = 0; ++ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | ++ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; ++ ++ switch (speed) { ++ case 0: ++ /* Do not change speed */ ++ return 0; ++ case 10: ++ speed_mii = MII_CTRL_SS_10; ++ break; ++ case 100: ++ speed_mii = MII_CTRL_SS_100; ++ break; ++ case 1000: ++ speed_mii = MII_CTRL_SS_1000; ++ break; ++ default: ++ return -1; ++ } ++ ++ /* Hold rxSeqStart */ ++ srab_sgmii_rreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ ++ /* hold TX FIFO in reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_MISC1r, &data16); ++ data16 &= ~(mask); ++ data16 |= speed_val; ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_MISC1r, &data16); ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ data16 &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); ++ data16 |= speed_mii; ++ srab_sgmii_wreg(robo, page, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ ++ /* release rxSeqStart */ ++ srab_sgmii_rreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); ++ srab_sgmii_wreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ ++ /* release TX FIFO reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_speed_get(robo_info_t *robo, uint page, int *speed) ++{ ++ uint16 data16; ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_STATUS1000X1r, &data16); ++ ++ data16 &= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK; ++ data16 >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT; ++ ++ if (data16 == 3) { ++ *speed= 2500; ++ } else if (data16 == 2) { ++ *speed= 1000; ++ } else if (data16 == 1) { ++ *speed= 100; ++ } else { ++ *speed= 10; ++ } ++ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c +new file mode 100755 +index 0000000..0dda6c6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch new file mode 100644 index 00000000..49a3a6df --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch @@ -0,0 +1,487 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c +@@ -0,0 +1,481 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "bcmiproc_serdes.h" ++#include "bcmiproc_serdes_def.h" ++#include "../../../mdio/iproc_mdio.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++/* ==== Public Functions ================================================= */ ++ ++void ++serdes_set_blk(uint eth_num, uint phyaddr, uint blk) ++{ ++ uint16 blkaddr; ++ uint16 destblk = (uint16)blk; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s phyaddr(0x%x) blk(0x%x)\n", ++ __FUNCTION__, phyaddr, blk)); ++ ++ /* check if need to update blk addr */ ++ ccb_mii_read(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, &blkaddr); ++ if (blkaddr!=destblk) { ++ /* write block address */ ++ ccb_mii_write(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, destblk); ++ } ++} ++ ++ ++void ++serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data) ++{ ++ uint blk = reg&0x7ff0; ++ uint off = reg&0x000f; ++ uint16 tmpdata=(uint16)data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* set block address */ ++ serdes_set_blk(eth_num, phyaddr, blk); ++ ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg, tmpdata)); ++ //printf("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg, tmpdata); ++ /* write register */ ++ ccb_mii_write(MII_DEV_LOCAL, phyaddr, off, tmpdata); ++} ++ ++ ++uint16 ++serdes_rd_reg(uint eth_num, uint phyaddr, uint reg) ++{ ++ uint blk = reg&0x7ff0; ++ uint off = reg&0x000f; ++ uint16 data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* set block address */ ++ serdes_set_blk(eth_num, phyaddr, blk); ++ ++ /* read register */ ++ ccb_mii_read(MII_DEV_LOCAL, phyaddr, off, &data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg, data)); ++ //printf("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg, data); ++ ++ return data; ++} ++ ++ ++uint16 ++serdes_get_id(uint eth_num, uint phyaddr, uint off) ++{ ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return 0; ++ ++ /* read the id high */ ++ return serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID0r+off); ++} ++ ++ ++void ++serdes_reset(uint eth_num, uint phyaddr) ++{ ++ uint ctrl; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ ctrl = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r, ctrl); ++ udelay(100); ++ /* check if out of reset */ ++ if (serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r) & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } ++} ++ ++ ++int ++serdes_reset_core(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint16 serdes_id2; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* get serdes id */ ++ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); ++ printf("et%d %s pbyaddr(0x%x) id2(0x%x)\n", eth_num, __FUNCTION__, phyaddr, serdes_id2); ++ ++ /* unlock lane */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x833c); ++ data16 &= ~(0x0040); ++ serdes_wr_reg(eth_num, phyaddr, 0x833c, data16); ++ ++ if ( phyaddr == 1 ) { ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in ++ * IEEE address space. ++ */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r); ++ if (XGXS16G_2p5G_ID(serdes_id2)) { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ } else { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++#if !defined(CONFIG_MACH_KT2) ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++#endif /* (!defined(CONFIG_MACH_KT2)) */ ++ } ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r, data16); ++ ++ /* disable in-band MDIO. PHY-443 */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8111); ++ /* rx_inBandMdio_rst */ ++ data16 |= 1 << 3; ++ serdes_wr_reg(eth_num, phyaddr, 0x8111, data16); ++ } ++ return 0; ++} ++ ++ ++int ++serdes_start_pll(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ ++ if ( phyaddr == 1 ) { ++ uint32 count=250; ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* wait for PLL to lock */ ++ while (count!=0) { ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSSTATUSr); ++ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { ++ break; ++ } ++ /* wait 1 usec then dec counter */ ++ udelay(10); ++ count--; ++ } ++ if (count == 0) { ++ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * serdes_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++serdes_init(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint16 serdes_id0, serdes_id1, serdes_id2; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* get serdes id */ ++ serdes_id0 = serdes_get_id(eth_num, phyaddr, 0); ++ serdes_id1 = serdes_get_id(eth_num, phyaddr, 1); ++ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); ++ printf("%s pbyaddr(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1, serdes_id2); ++ ++ /* get more ids */ ++ serdes_id0 = serdes_rd_reg(eth_num, phyaddr, 2); ++ serdes_id1 = serdes_rd_reg(eth_num, phyaddr, 3); ++ //printf("%s pbyaddr(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1); ++ ++ /* unlock lane */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x833c); ++ data16 &= ~(0x0040); ++ serdes_wr_reg(eth_num, phyaddr, 0x833c, data16); ++ ++ /* disable CL73 BAM */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8372); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ serdes_wr_reg(eth_num, phyaddr, 0x8372, data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_AUTONEGADVr, data16); ++ ++ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ ++ data16 = 0; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK; ++ /* ++ * Put the Serdes in SGMII mode ++ * bit0 = 0; in SGMII mode ++ */ ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, data16); ++ ++ /* set autoneg */ ++ data16 = MII_CTRL_AE | MII_CTRL_RAN; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_AN73_PDET_PARDET10GCONTROLr, data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); ++ ++ /* Enable lanes */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r, data16); ++ ++ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ /* Enabble LPI passthru' for native mode EEE */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r); ++ data16 |= 0xc000; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r, data16); ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr); ++ data16 |= 0x0007; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr, data16); ++ ++ return 0; ++} ++ ++ ++ ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++/* ++ * Function: ++ * serdes_speeddpx_set ++ * Purpose: ++ * Set serdes speed dpx ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - link speed in Mbps ++ * fulldpx - link dpx ++ * Returns: ++ * 0 ++ */ ++int ++serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx) ++{ ++ uint16 speed_val, mask; ++ uint16 data16; ++ uint16 speed_mii; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ if (speed > 1000) { ++ return -1; ++ } ++ ++ speed_val = 0; ++ speed_mii = 0; ++ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | ++ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; ++ ++ switch (speed) { ++ case 0: ++ /* Do not change speed */ ++ return 0; ++ case 10: ++ speed_mii = MII_CTRL_SS_10; ++ break; ++ case 100: ++ speed_mii = MII_CTRL_SS_100; ++ break; ++ case 1000: ++ speed_mii = MII_CTRL_SS_1000; ++ break; ++ default: ++ return -1; ++ } ++ ++ if (fulldpx) ++ speed_mii |= MII_CTRL_FD; ++ ++ /* Hold rxSeqStart */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); ++ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); ++ ++ /* hold TX FIFO in reset */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); ++ data16 &= ~(mask); ++ data16 |= speed_val; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); ++ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); ++ data16 &= ~(MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_SS_LSB | MII_CTRL_SS_MSB | MII_CTRL_FD); ++ data16 |= speed_mii; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* release rxSeqStart */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); ++ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); ++ ++ /* release TX FIFO reset */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ return 0; ++} ++ ++int ++serdes_set_asym_mode(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint32 txclkctrlreg[] = {0x0000, 0x8065, 0x8075, 0x8085}; ++ uint32 rxclkctrlreg[] = {0x0000, 0x80bc, 0x80cc, 0x80dc}; ++ uint32 spd[] = {0x0000, 0x7120, 0x7120, 0x7110}; ++ uint32 clkctrlmsk[] = {0x0000, 0x0040, 0x0040, 0x0040}; ++ uint32 clkctrlval[] = {0x0000, 0x0040, 0x0040, 0x0000}; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ printk("et%d: %s: setting serdes asymmetrice mode\n", eth_num, __FUNCTION__); ++ ++ /* set speed */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); ++ data16 &= 0x0f00; ++ data16 |= spd[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); ++ ++ /* Enable asymmetric mode */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); ++ data16 |= 0x0100; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); ++ ++ /* set tx clock control bit */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, txclkctrlreg[phyaddr]); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); ++ data16 &= ~(clkctrlmsk[phyaddr]); ++ data16 |= clkctrlval[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, txclkctrlreg[phyaddr], data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); ++ ++ /* set rx clock control bit */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr]); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); ++ data16 &= ~(clkctrlmsk[phyaddr]); ++ data16 |= clkctrlval[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr], data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); ++ ++ data16 = 0xffff; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_XGXSBLK1_LANECTRL1r); ++ ++ return 0; ++} ++ ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmotp.c b/drivers/bcmdrivers/gmac/src/shared/bcmotp.c +new file mode 100755 +index 0000000..a6c41d4 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch new file mode 100644 index 00000000..1d506247 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch @@ -0,0 +1,3797 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmotp.c +@@ -0,0 +1,3791 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OTP support. ++ * ++ * $Id: bcmotp.c 322632 2012-03-21 05:17:48Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * There are two different OTP controllers so far: ++ * 1. new IPX OTP controller: chipc 21, >=23 ++ * 2. older HND OTP controller: chipc 12, 17, 22 ++ * ++ * Define BCMHNDOTP to include support for the HND OTP controller. ++ * Define BCMIPXOTP to include support for the IPX OTP controller. ++ * ++ * NOTE 1: More than one may be defined ++ * NOTE 2: If none are defined, the default is to include them all. ++ */ ++ ++#if !defined(BCMHNDOTP) && !defined(BCMIPXOTP) ++#define BCMHNDOTP 1 ++#define BCMIPXOTP 1 ++#endif ++ ++#define OTPTYPE_HND(ccrev) ((ccrev) < 21 || (ccrev) == 22) ++#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) ++ ++#define OTP_ERR_VAL 0x0001 ++#define OTP_MSG_VAL 0x0002 ++#define OTP_DBG_VAL 0x0004 ++uint32 otp_msg_level = OTP_ERR_VAL; ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) ++#define OTP_ERR(args) do {if (otp_msg_level & OTP_ERR_VAL) printf args;} while (0) ++#else ++#define OTP_ERR(args) ++#endif ++ ++#ifdef BCMDBG ++#define OTP_MSG(args) do {if (otp_msg_level & OTP_MSG_VAL) printf args;} while (0) ++#define OTP_DBG(args) do {if (otp_msg_level & OTP_DBG_VAL) printf args;} while (0) ++#else ++#define OTP_MSG(args) ++#define OTP_DBG(args) ++#endif ++ ++#define OTPP_TRIES 10000000 /* # of tries for OTPP */ ++#define OTP_FUSES_PER_BIT 2 ++#define OTP_WRITE_RETRY 16 ++ ++#ifdef BCMIPXOTP ++#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ ++#endif ++ ++/* OTP common function type */ ++typedef int (*otp_status_t)(void *oh); ++typedef int (*otp_size_t)(void *oh); ++typedef void* (*otp_init_t)(si_t *sih); ++typedef uint16 (*otp_read_bit_t)(void *oh, chipcregs_t *cc, uint off); ++typedef int (*otp_read_region_t)(si_t *sih, int region, uint16 *data, uint *wlen); ++typedef int (*otp_nvread_t)(void *oh, char *data, uint *len); ++typedef int (*otp_write_region_t)(void *oh, int region, uint16 *data, uint wlen); ++typedef int (*otp_cis_append_region_t)(si_t *sih, int region, char *vars, int count); ++typedef int (*otp_lock_t)(si_t *sih); ++typedef int (*otp_nvwrite_t)(void *oh, uint16 *data, uint wlen); ++typedef int (*otp_dump_t)(void *oh, int arg, char *buf, uint size); ++typedef int (*otp_write_word_t)(void *oh, uint wn, uint16 data); ++typedef int (*otp_read_word_t)(void *oh, uint wn, uint16 *data); ++typedef int (*otp_write_bits_t)(void *oh, int bn, int bits, uint8* data); ++ ++/* OTP function struct */ ++typedef struct otp_fn_s { ++ otp_size_t size; ++ otp_read_bit_t read_bit; ++ otp_dump_t dump; ++ otp_status_t status; ++ ++ otp_init_t init; ++ otp_read_region_t read_region; ++ otp_nvread_t nvread; ++ otp_write_region_t write_region; ++ otp_cis_append_region_t cis_append_region; ++ otp_lock_t lock; ++ otp_nvwrite_t nvwrite; ++ otp_write_word_t write_word; ++ otp_read_word_t read_word; ++ ++#if defined(BCMNVRAMW) ++ otp_write_bits_t write_bits; ++#endif ++} otp_fn_t; ++ ++typedef struct { ++ uint ccrev; /* chipc revision */ ++ otp_fn_t *fn; /* OTP functions */ ++ si_t *sih; /* Saved sb handle */ ++ osl_t *osh; ++ ++#ifdef BCMIPXOTP ++ /* IPX OTP section */ ++ uint16 wsize; /* Size of otp in words */ ++ uint16 rows; /* Geometry */ ++ uint16 cols; /* Geometry */ ++ uint32 status; /* Flag bits (lock/prog/rv). ++ * (Reflected only when OTP is power cycled) ++ */ ++ uint16 hwbase; /* hardware subregion offset */ ++ uint16 hwlim; /* hardware subregion boundary */ ++ uint16 swbase; /* software subregion offset */ ++ uint16 swlim; /* software subregion boundary */ ++ uint16 fbase; /* fuse subregion offset */ ++ uint16 flim; /* fuse subregion boundary */ ++ int otpgu_base; /* offset to General Use Region */ ++ uint16 fusebits; /* num of fusebits */ ++ bool buotp; /* Uinified OTP flag */ ++ uint usbmanfid_offset; /* Offset of the usb manfid inside the sdio CIS */ ++ struct { ++ uint8 width; /* entry width in bits */ ++ uint8 val_shift; /* value bit offset in the entry */ ++ uint8 offsets; /* # entries */ ++ uint8 stat_shift; /* valid bit in otpstatus */ ++ uint16 offset[MAXNUMRDES]; /* entry offset in OTP */ ++ } rde_cb; /* OTP redundancy control blocks */ ++ uint16 rde_idx; ++#endif /* BCMIPXOTP */ ++ ++#ifdef BCMHNDOTP ++ /* HND OTP section */ ++ uint size; /* Size of otp in bytes */ ++ uint hwprot; /* Hardware protection bits */ ++ uint signvalid; /* Signature valid bits */ ++ int boundary; /* hw/sw boundary */ ++#endif /* BCMHNDOTP */ ++} otpinfo_t; ++ ++static otpinfo_t otpinfo; ++ ++/* ++ * ROM accessor to avoid struct in shdat ++ */ ++static otpinfo_t * ++get_otpinfo(void) ++{ ++ return (otpinfo_t *)&otpinfo; ++} ++ ++/* ++ * IPX OTP Code ++ * ++ * Exported functions: ++ * ipxotp_status() ++ * ipxotp_size() ++ * ipxotp_init() ++ * ipxotp_read_bit() ++ * ipxotp_read_region() ++ * ipxotp_read_word() ++ * ipxotp_nvread() ++ * ipxotp_write_region() ++ * ipxotp_write_word() ++ * ipxotp_cis_append_region() ++ * ipxotp_lock() ++ * ipxotp_nvwrite() ++ * ipxotp_dump() ++ * ++ * IPX internal functions: ++ * ipxotp_otpr() ++ * _ipxotp_init() ++ * ipxotp_write_bit() ++ * ipxotp_otpwb16() ++ * ipxotp_check_otp_pmu_res() ++ * ipxotp_write_rde() ++ * ipxotp_fix_word16() ++ * ipxotp_check_word16() ++ * ipxotp_max_rgnsz() ++ * ipxotp_otprb16() ++ * ipxotp_uotp_usbmanfid_offset() ++ * ++ */ ++ ++#ifdef BCMIPXOTP ++ ++#define OTPWSIZE 16 /* word size */ ++#define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w") ++ ++/* OTP layout */ ++/* CC revs 21, 24 and 27 OTP General Use Region word offset */ ++#define REVA4_OTPGU_BASE 12 ++ ++/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ ++#define REVB8_OTPGU_BASE 20 ++ ++/* CC rev 36 OTP General Use Region word offset */ ++#define REV36_OTPGU_BASE 12 ++ ++/* Subregion word offsets in General Use region */ ++#define OTPGU_HSB_OFF 0 ++#define OTPGU_SFB_OFF 1 ++#define OTPGU_CI_OFF 2 ++#define OTPGU_P_OFF 3 ++#define OTPGU_SROM_OFF 4 ++ ++/* Flag bit offsets in General Use region */ ++#define OTPGU_NEWCISFORMAT_OFF 59 ++#define OTPGU_HWP_OFF 60 ++#define OTPGU_SWP_OFF 61 ++#define OTPGU_CIP_OFF 62 ++#define OTPGU_FUSEP_OFF 63 ++#define OTPGU_CIP_MSK 0x4000 ++#define OTPGU_P_MSK 0xf000 ++#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) ++ ++/* LOCK but offset */ ++#define OTP_LOCK_ROW1_LOC_OFF 63 /* 1st ROW lock bit */ ++#define OTP_LOCK_ROW2_LOC_OFF 127 /* 2nd ROW lock bit */ ++#define OTP_LOCK_RD_LOC_OFF 128 /* Redundnancy Region lock bit */ ++#define OTP_LOCK_GU_LOC_OFF 129 /* General User Region lock bit */ ++ ++ ++/* OTP Size */ ++#define OTP_SZ_FU_324 ((ROUNDUP(324,8))/8) /* 324 bits */ ++#define OTP_SZ_FU_288 (288/8) /* 288 bits */ ++#define OTP_SZ_FU_216 (216/8) /* 216 bits */ ++#define OTP_SZ_FU_72 (72/8) /* 72 bits */ ++#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ ++#define OTP4315_SWREG_SZ 178 /* 178 bytes */ ++#define OTP_SZ_FU_144 (144/8) /* 144 bits */ ++#define OTP_SZ_FU_180 ((ROUNDUP(180,8))/8) /* 180 bits */ ++ ++/* OTP BT shared region (pre-allocated) */ ++#define OTP_BT_BASE_4330 (1760/OTPWSIZE) ++#define OTP_BT_END_4330 (1888/OTPWSIZE) ++#define OTP_BT_BASE_4324 (2384/OTPWSIZE) ++#define OTP_BT_END_4324 (2640/OTPWSIZE) ++#define OTP_BT_BASE_4334 (2512/OTPWSIZE) ++#define OTP_BT_END_4334 (2768/OTPWSIZE) ++#define OTP_BT_BASE_4314 (4192/OTPWSIZE) ++#define OTP_BT_END_4314 (4960/OTPWSIZE) ++#define OTP_BT_BASE_4335 (4528/OTPWSIZE) ++#define OTP_BT_END_4335 (5552/OTPWSIZE) ++ ++/* OTP unification */ ++#if defined(USBSDIOUNIFIEDOTP) ++/* USB MANIFID tuple offset in the SDIO CIS in (16-bit) words */ ++#define USB_MANIFID_OFFSET_4319 42 ++#endif /* USBSDIOUNIFIEDOTP */ ++ ++#if defined(BCMNVRAMW) ++/* Local */ ++static int ipxotp_check_otp_pmu_res(chipcregs_t *cc); ++static int ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off); ++static int ipxotp40n_read2x(void *oh, chipcregs_t *cc, uint off); ++static int ipxotp_write_rde_nopc(void *oh, chipcregs_t *cc, int rde, uint bit, uint val); ++#endif ++ ++static int ++ipxotp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return (int)(oi->status); ++} ++ ++/* Return size in bytes */ ++static int ++ipxotp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return (int)oi->wsize * 2; ++} ++ ++static uint16 ++ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ ASSERT(wn < oi->wsize); ++ ASSERT(cc != NULL); ++ ++ return R_REG(oi->osh, &cc->sromotp[wn]); ++} ++ ++static uint16 ++ipxotp_read_bit_common(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_READ_40NM : ++ OTPPOC_READ) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x", ++ __FUNCTION__, off, row, col, otpp)); ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return 0xffff; ++ } ++ if (st & OTPP_READERR) { ++ OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, off)); ++ return 0xffff; ++ } ++ st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; ++ ++ OTP_DBG((" => %d\n", st)); ++ return (int)st; ++} ++ ++static uint16 ++ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++/* ++ * OTP BT region size ++ */ ++static void ++ipxotp_bt_region_get(otpinfo_t *oi, uint16 *start, uint16 *end) ++{ ++ *start = *end = 0; ++ switch (CHIPID(oi->sih->chip)) { ++ case BCM4330_CHIP_ID: ++ *start = OTP_BT_BASE_4330; ++ *end = OTP_BT_END_4330; ++ break; ++ case BCM4324_CHIP_ID: ++ *start = OTP_BT_BASE_4324; ++ *end = OTP_BT_END_4324; ++ break; ++ case BCM4334_CHIP_ID: ++ *start = OTP_BT_BASE_4334; ++ *end = OTP_BT_END_4334; ++ break; ++ case BCM4314_CHIP_ID: ++ case BCM43142_CHIP_ID: ++ *start = OTP_BT_BASE_4314; ++ *end = OTP_BT_END_4314; ++ break; ++ case BCM4335_CHIP_ID: ++ *start = OTP_BT_BASE_4335; ++ *end = OTP_BT_END_4335; ++ break; ++ } ++} ++ ++/* Calculate max HW/SW region byte size by substracting fuse region and checksum size, ++ * osizew is oi->wsize (OTP size - GU size) in words ++ */ ++static int ++ipxotp_max_rgnsz(otpinfo_t *oi) ++{ ++ int osizew = oi->wsize; ++ int ret = 0; ++ uint16 checksum; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ checksum = OTP_SZ_CHECKSUM; ++ ++ /* for new chips, fusebit is available from cc register */ ++ if (oi->sih->ccrev >= 35) { ++ oi->fusebits = R_REG(oi->osh, &cc->otplayoutextension) & OTPLAYOUTEXT_FUSE_MASK; ++ oi->fusebits = ROUNDUP(oi->fusebits, 8); ++ oi->fusebits >>= 3; /* bytes */ ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ switch (CHIPID(oi->sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43239_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_288; ++ break; ++ case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: ++ case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID: ++ case BCM43226_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43237_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_324; ++ break; ++ case BCM4325_CHIP_ID: ++ case BCM5356_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_216; ++ break; ++ case BCM4336_CHIP_ID: ++ case BCM43362_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_144; ++ break; ++ case BCM4313_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM4330_CHIP_ID: ++ case BCM4334_CHIP_ID: ++ case BCM4314_CHIP_ID: ++ case BCM43142_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_144; ++ break; ++ case BCM4319_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_180; ++ break; ++ case BCM4331_CHIP_ID: ++ case BCM43431_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ case BCM43428_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ default: ++ if (oi->fusebits == 0) ++ ASSERT(0); /* Don't konw about this chip */ ++ } ++ ++ ret = osizew*2 - oi->fusebits - checksum; ++ ++ if (CHIPID(oi->sih->chip) == BCM4315_CHIP_ID) { ++ ret = OTP4315_SWREG_SZ; ++ } ++ ++ OTP_MSG(("max region size %d bytes\n", ret)); ++ return ret; ++} ++ ++/* ++ * OTP sizes for 65nm and 130nm ++ */ ++static int ++ipxotp_otpsize_set_65nm(otpinfo_t *oi, uint otpsz) ++{ ++ /* Check for otp size */ ++ switch (otpsz) { ++ case 1: /* 32x64 */ ++ oi->rows = 32; ++ oi->cols = 64; ++ oi->wsize = 128; ++ break; ++ case 2: /* 64x64 */ ++ oi->rows = 64; ++ oi->cols = 64; ++ oi->wsize = 256; ++ break; ++ case 5: /* 96x64 */ ++ oi->rows = 96; ++ oi->cols = 64; ++ oi->wsize = 384; ++ break; ++ case 7: /* 16x64 */ /* 1024 bits */ ++ oi->rows = 16; ++ oi->cols = 64; ++ oi->wsize = 64; ++ break; ++ default: ++ /* Don't know the geometry */ ++ OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__)); ++ } ++ ++ return 0; ++} ++ ++/* ++ * OTP sizes for 40nm ++ */ ++static int ++ipxotp_otpsize_set_40nm(otpinfo_t *oi, uint otpsz) ++{ ++ /* Check for otp size */ ++ switch (otpsz) { ++ case 1: /* 64x32: 2048 bits */ ++ oi->rows = 64; ++ oi->cols = 32; ++ break; ++ case 2: /* 96x32: 3072 bits */ ++ oi->rows = 96; ++ oi->cols = 32; ++ break; ++ case 3: /* 128x32: 4096 bits */ ++ oi->rows = 128; ++ oi->cols = 32; ++ break; ++ case 4: /* 160x32: 5120 bits */ ++ oi->rows = 160; ++ oi->cols = 32; ++ break; ++ case 5: /* 192x32: 6144 bits */ ++ oi->rows = 192; ++ oi->cols = 32; ++ break; ++ case 7: /* 256x32: 8192 bits */ ++ oi->rows = 256; ++ oi->cols = 32; ++ break; ++ default: ++ /* Don't know the geometry */ ++ OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__)); ++ } ++ ++ oi->wsize = (oi->cols * oi->rows)/OTPWSIZE; ++ return 0; ++} ++ ++/* OTP unification */ ++#if defined(USBSDIOUNIFIEDOTP) && defined(BCMNVRAMW) ++static void ++ipxotp_uotp_usbmanfid_offset(otpinfo_t *oi) ++{ ++ OTP_DBG(("%s: chip=0x%x\n", __FUNCTION__, CHIPID(oi->sih->chip))); ++ switch (CHIPID(oi->sih->chip)) { ++ /* Add cases for supporting chips */ ++ case BCM4319_CHIP_ID: ++ oi->usbmanfid_offset = USB_MANIFID_OFFSET_4319; ++ oi->buotp = TRUE; ++ break; ++ default: ++ OTP_ERR(("chip=0x%x does not support Unified OTP.\n", ++ CHIPID(oi->sih->chip))); ++ break; ++ } ++} ++#endif /* USBSDIOUNIFIEDOTP && BCMNVRAMW */ ++ ++static void ++BCMNMIATTACHFN(_ipxotp_init)(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint k; ++ uint32 otpp, st; ++ uint16 btsz, btbase = 0, btend = 0; ++ uint otpwt; ++ ++ /* record word offset of General Use Region for various chipcommon revs */ ++ if (oi->sih->ccrev >= 40) { ++ /* FIX: Available in rev >= 23; Verify before applying to others */ ++ oi->otpgu_base = (R_REG(oi->osh, &cc->otplayout) & OTPL_HWRGN_OFF_MASK) ++ >> OTPL_HWRGN_OFF_SHIFT; ++ ASSERT((oi->otpgu_base - (OTPGU_SROM_OFF * OTPWSIZE)) > 0); ++ oi->otpgu_base >>= 4; /* words */ ++ oi->otpgu_base -= OTPGU_SROM_OFF; ++ } else if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) { ++ oi->otpgu_base = REVA4_OTPGU_BASE; ++ } else if ((oi->sih->ccrev == 36) || (oi->sih->ccrev == 39)) { ++ /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */ ++ if (oi->wsize >= 128) ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ else ++ oi->otpgu_base = REV36_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ } else { ++ OTP_ERR(("%s: chipc rev %d not supported\n", __FUNCTION__, oi->sih->ccrev)); ++ } ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt != OTPL_WRAP_TYPE_40NM) { ++ /* First issue an init command so the status is up to date */ ++ otpp = OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); ++ ++ OTP_DBG(("%s: otpp = 0x%x", __FUNCTION__, otpp)); ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return; ++ } ++ } ++ ++ /* Read OTP lock bits and subregion programmed indication bits */ ++ oi->status = R_REG(oi->osh, &cc->otpstatus); ++ ++ if ((CHIPID(oi->sih->chip) == BCM43222_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43111_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43112_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43224_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43421_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43226_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43236_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43235_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43234_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43238_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43237_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43239_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4324_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4335_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43526_CHIP_ID) || ++ 0) { ++ uint32 p_bits; ++ p_bits = (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & OTPGU_P_MSK) ++ >> OTPGU_P_SHIFT; ++ oi->status |= (p_bits << OTPS_GUP_SHIFT); ++ } ++ OTP_DBG(("%s: status 0x%x\n", __FUNCTION__, oi->status)); ++ ++ /* OTP unification */ ++ oi->buotp = FALSE; /* Initialize it to false, until its explicitely set true. */ ++ oi->usbmanfid_offset = 0; ++#if defined(USBSDIOUNIFIEDOTP) && defined(BCMNVRAMW) ++ ipxotp_uotp_usbmanfid_offset(oi); ++#endif /* USBSDIOUNIFIEDOTP && BCMNVRAMW */ ++ if ((oi->status & (OTPS_GUP_HW | OTPS_GUP_SW)) == (OTPS_GUP_HW | OTPS_GUP_SW)) { ++ switch (CHIPID(oi->sih->chip)) { ++ /* Add cases for supporting chips */ ++ case BCM4319_CHIP_ID: ++ oi->buotp = TRUE; ++ break; ++ default: ++ OTP_ERR(("chip=0x%x does not support Unified OTP.\n", ++ CHIPID(oi->sih->chip))); ++ break; ++ } ++ } ++ ++ /* ++ * h/w region base and fuse region limit are fixed to the top and ++ * the bottom of the general use region. Everything else can be flexible. ++ */ ++ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; ++ oi->hwlim = oi->wsize; ++ oi->flim = oi->wsize; ++ ++ ipxotp_bt_region_get(oi, &btbase, &btend); ++ btsz = btend - btbase; ++ if (btsz > 0) { ++ /* default to not exceed BT base */ ++ oi->hwlim = btbase; ++ ++ /* With BT shared region, swlim and fbase are fixed */ ++ oi->swlim = btbase; ++ oi->fbase = btend; ++ } ++ ++ /* Update hwlim and swbase */ ++ if (oi->status & OTPS_GUP_HW) { ++ OTP_DBG(("%s: hw region programmed\n", __FUNCTION__)); ++ oi->hwlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; ++ oi->swbase = oi->hwlim; ++ } else ++ oi->swbase = oi->hwbase; ++ ++ /* Update swlim and fbase only if no BT region */ ++ if (btsz == 0) { ++ /* subtract fuse and checksum from beginning */ ++ oi->swlim = ipxotp_max_rgnsz(oi) / 2; ++ ++ if (oi->status & OTPS_GUP_SW) { ++ OTP_DBG(("%s: sw region programmed\n", __FUNCTION__)); ++ oi->swlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; ++ oi->fbase = oi->swlim; ++ } ++ else ++ oi->fbase = oi->swbase; ++ } ++ ++ OTP_DBG(("%s: OTP limits---\n" ++ "hwbase %d/%d hwlim %d/%d\n" ++ "swbase %d/%d swlim %d/%d\n" ++ "fbase %d/%d flim %d/%d\n", __FUNCTION__, ++ oi->hwbase, oi->hwbase * 16, oi->hwlim, oi->hwlim * 16, ++ oi->swbase, oi->swbase * 16, oi->swlim, oi->swlim * 16, ++ oi->fbase, oi->fbase * 16, oi->flim, oi->flim * 16)); ++} ++ ++static void * ++BCMNMIATTACHFN(ipxotp_init)(si_t *sih) ++{ ++ uint idx, otpsz, otpwt; ++ chipcregs_t *cc; ++ otpinfo_t *oi = NULL; ++ ++ OTP_MSG(("%s: Use IPX OTP controller\n", __FUNCTION__)); ++ ++ /* Make sure we're running IPX OTP */ ++ ASSERT(OTPTYPE_IPX(sih->ccrev)); ++ if (!OTPTYPE_IPX(sih->ccrev)) ++ return NULL; ++ ++ /* Make sure OTP is not disabled */ ++ if (si_is_otp_disabled(sih)) { ++ OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__)); ++#if !defined(WLTEST) ++ return NULL; ++#endif ++ } ++ ++ /* Make sure OTP is powered up */ ++ if (!si_is_otp_powered(sih)) { ++ OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__)); ++ return NULL; ++ } ++ ++ /* Retrieve OTP region info */ ++ idx = si_coreidx(sih); ++ cc = si_setcoreidx(sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpsz = (sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT; ++ if (otpsz == 0) { ++ OTP_ERR(("%s: No OTP\n", __FUNCTION__)); ++ goto exit; ++ } ++ ++ oi = get_otpinfo(); ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ ipxotp_otpsize_set_40nm(oi, otpsz); ++ } else if (otpwt == OTPL_WRAP_TYPE_65NM) { ++ ipxotp_otpsize_set_65nm(oi, otpsz); ++ } else { ++ OTP_ERR(("%s: Unknown wrap type: %d\n", __FUNCTION__, otpwt)); ++ ASSERT(0); ++ } ++ ++ OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__, oi->rows, oi->cols, oi->wsize)); ++ ++#ifdef BCMNVRAMW ++ /* Initialize OTP redundancy control blocks */ ++ if (sih->ccrev >= 40) { ++ uint16 offset[] = {269, 286, 303, 333, 350, 367, 397, 414, 431}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 17; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } else if (sih->ccrev == 36) { ++ uint16 offset[] = {141, 158, 175}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } else if (sih->ccrev == 21 || sih->ccrev == 24) { ++ uint16 offset[] = {64, 79, 94, 109, 128, 143, 158, 173}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 11; ++ oi->rde_cb.stat_shift = 16; ++ } ++ else if (sih->ccrev == 27) { ++ uint16 offset[] = {128, 143, 158, 173}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 11; ++ oi->rde_cb.stat_shift = 20; ++ } ++ else { ++ uint16 offset[] = {141, 158, 175, 205, 222, 239, 269, 286, 303}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 17; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } ++ ASSERT(oi->rde_cb.offsets <= MAXNUMRDES); ++ /* Initialize global rde index */ ++ oi->rde_idx = 0; ++#endif /* BCMNVRAMW */ ++ ++ _ipxotp_init(oi, cc); ++ ++exit: ++ si_setcoreidx(sih, idx); ++ ++ return (void *)oi; ++} ++ ++static int ++ipxotp_read_region(void *oh, int region, uint16 *data, uint *wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint base, i, sz; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ /* OTP unification: For unified OTP sz=flim-hwbase */ ++ if (oi->buotp) ++ sz = (uint)oi->flim - oi->hwbase; ++ else ++ sz = (uint)oi->hwlim - oi->hwbase; ++ if (!(oi->status & OTPS_GUP_HW)) { ++ OTP_ERR(("%s: h/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->hwlim - oi->hwbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ /* OTP unification: For unified OTP sz=flim-swbase */ ++ if (oi->buotp) ++ sz = ((uint)oi->flim - oi->swbase); ++ else ++ sz = ((uint)oi->swlim - oi->swbase); ++ if (!(oi->status & OTPS_GUP_SW)) { ++ OTP_ERR(("%s: s/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small should be at least %u\n", ++ __FUNCTION__, oi->swlim - oi->swbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ sz = OTPGU_CI_SZ; ++ if (!(oi->status & OTPS_GUP_CI)) { ++ OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, OTPGU_CI_SZ)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ sz = (uint)oi->flim - oi->fbase; ++ if (!(oi->status & OTPS_GUP_FUSE)) { ++ OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->flim - oi->fbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->fbase; ++ break; ++ case OTP_ALL_RGN: ++ sz = ((uint)oi->flim - oi->hwbase); ++ if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { ++ OTP_ERR(("%s: h/w & s/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->hwlim - oi->hwbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->hwbase; ++ break; ++ default: ++ OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__, region)); ++ return BCME_BADARG; ++ } ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Read the data */ ++ for (i = 0; i < sz; i ++) ++ data[i] = ipxotp_otpr(oh, cc, base + i); ++ ++ si_setcoreidx(oi->sih, idx); ++ *wlen = sz; ++ return 0; ++} ++ ++static int ++ipxotp_read_word(void *oh, uint wn, uint16 *data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Read the data */ ++ *data = ipxotp_otpr(oh, cc, wn); ++ ++ si_setcoreidx(oi->sih, idx); ++ return 0; ++} ++ ++static int ++ipxotp_nvread(void *oh, char *data, uint *len) ++{ ++ return BCME_UNSUPPORTED; ++} ++ ++#ifdef BCMNVRAMW ++static int ++ipxotp_writable(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ uint i, k, row, col; ++ uint32 otpp, st; ++ uint cols[4] = {15, 4, 8, 13}; ++ ++ row = 0; ++ for (i = 0; i < 4; i++) { ++ col = cols[i]; ++ ++ otpp = OTPP_START_BUSY | ++ ((OTPPOC_PROG_ENABLE_40NM << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && ++ (k < OTPP_TRIES); k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", ++ __FUNCTION__, st, k)); ++ return -1; ++ } ++ } ++ ++ /* wait till OTP Program mode is unlocked */ ++ for (k = 0; ++ (!((st = R_REG(oi->osh, &cc->otpstatus)) & OTPS_PROGOK)) && ++ (k < OTPP_TRIES); k ++) ++ ; ++ OTP_MSG(("\n%s: OTP Program status: %x\n", __FUNCTION__, st)); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: OTP Program mode is still locked, OTP is unwritable\n", ++ __FUNCTION__)); ++ return -1; ++ } ++ } ++ ++ OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN); ++ return 0; ++} ++ ++static int ++ipxotp_unwritable(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ uint k, row, col; ++ uint32 otpp, st; ++ ++ row = 0; ++ col = 0; ++ ++ otpp = OTPP_START_BUSY | ++ ((OTPPOC_PROG_DISABLE_40NM << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ /* wait till OTP Program mode is unlocked */ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpstatus)) & OTPS_PROGOK) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ OTP_MSG(("\n%s: OTP Program status: %x\n", __FUNCTION__, st)); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: OTP Program mode is still unlocked, OTP is writable\n", ++ __FUNCTION__)); ++ return -1; ++ } ++ } ++ ++ AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN); ++ return 0; ++} ++ ++static int ++ipxotp_write_bit_common(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((1 << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_BIT_PROG_40NM : ++ OTPPOC_BIT_PROG) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, off, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ipxotp40n_read2x(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (1 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_R1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_R1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_read1x(void *oh, chipcregs_t *cc, uint off, uint fuse) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_R1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_R1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_verify1x(void *oh, chipcregs_t *cc, uint off, uint fuse) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_V1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_V1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_write_fuse(otpinfo_t *oi, chipcregs_t *cc, uint off, uint fuse) ++{ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_WR << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (0 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_WR << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT) | ++ OTPC_PROGEN); ++ ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_WR << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_write_bit_common(oi, cc, off); ++} ++ ++static int ++ipxotp40n_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint32 oc_orig, oc1_orig; ++ uint8 i, j, err = 0; ++ int verr0, verr1, rerr0, rerr1, retry, val; ++ ++ oc_orig = R_REG(oi->osh, &cc->otpcontrol); ++ oc1_orig = R_REG(oi->osh, &cc->otpcontrol1); ++ ++ for (i = 0; i < OTP_FUSES_PER_BIT; i++) { ++ retry = 0; ++ for (j = 0; j < OTP_WRITE_RETRY; j++) { ++ /* program fuse */ ++ ipxotp40n_write_fuse(oi, cc, off, i); ++ ++ /* verify fuse */ ++ val = ipxotp40n_verify1x(oi, cc, off, i); ++ if (val == 1) ++ break; ++ ++ retry++; ++ } ++ ++ if ((val != 1) && (j == OTP_WRITE_RETRY)) { ++ OTP_ERR(("ERROR: New write failed max attempts fuse:%d @ off:%d\n", ++ i, off)); ++ } else if (retry > 0) ++ OTP_MSG(("Verify1x multi retries:%d fuse:%d @ off:%d\n", ++ retry, i, off)); ++ } ++ ++ /* Post screen */ ++ verr0 = (ipxotp40n_verify1x(oi, cc, off, 0) == 1) ? TRUE : FALSE; ++ verr1 = (ipxotp40n_verify1x(oi, cc, off, 1) == 1) ? TRUE : FALSE; ++ rerr0 = (ipxotp40n_read1x(oi, cc, off, 0) == 1) ? TRUE : FALSE; ++ rerr1 = (ipxotp40n_read1x(oi, cc, off, 1) == 1) ? TRUE : FALSE; ++ ++ if (verr0 && verr1) { ++ OTP_MSG(("V0:%d and V1:%d ok off:%d\n", verr0, verr1, off)); ++ } else if (verr0 && rerr1) { ++ OTP_MSG(("V0:%d and R1:%d ok off:%d\n", verr0, rerr1, off)); ++ } else if (rerr0 && verr1) { ++ OTP_MSG(("R0:%d and V1:%d ok off:%d\n", rerr0, verr1, off)); ++ } else { ++ OTP_ERR(("Bit failed post screen v0:%d v1:%d r0:%d r1:%d off:%d\n", ++ verr0, verr1, rerr0, rerr1, off)); ++ err = -1; ++ } ++ ++ W_REG(oi->osh, &cc->otpcontrol, oc_orig); ++ W_REG(oi->osh, &cc->otpcontrol1, oc1_orig); ++ ++ return err; ++} ++ ++#ifdef OTP_DEBUG ++int ++otp_read1x(void *oh, uint off, uint fuse) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, otpwt; ++ int val = 0; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ if ((otpwt != OTPL_WRAP_TYPE_40NM) || (oi->sih->ccrev < 40)) ++ goto exit; ++ ++ val = ipxotp40n_read1x(oi, cc, off, fuse); ++ ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return val; ++} ++ ++int ++otp_verify1x(void *oh, uint off, uint fuse) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0; ++ chipcregs_t *cc; ++ uint idx, otpwt; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ if ((otpwt != OTPL_WRAP_TYPE_40NM) || (oi->sih->ccrev < 40)) ++ goto exit; ++ ++ err = ipxotp40n_verify1x(oi, cc, off, fuse); ++ if (err != 1) ++ OTP_ERR(("v1x failed fuse:%d @ off:%d\n", fuse, off)); ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return err; ++} ++ ++/* ++ * Repair is to fix damaged bits; not intended to fix programming errors ++ * This is limited and for 4334 only nine repair entries available ++ */ ++int ++otp_repair_bit(void *oh, uint off, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return ipxotp_write_rde(oi, -1, off, val); ++} ++ ++int ++otp_write_ones_old(void *oh, uint off, uint bits) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint32 i; ++ ++ if (off < 0 || off + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; i++) { ++ ipxotp_write_bit_common(oi, cc, off++); ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++int ++otp_write_ones(void *oh, uint off, uint bits) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint32 i; ++ int err; ++ ++ if (off < 0 || off + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; i++) { ++ err = ipxotp_write_bit(oi, cc, off); ++ if (err != 0) { ++ OTP_ERR(("%s: write bit failed: %d\n", __FUNCTION__, off)); ++ ++ err = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), off, 1); ++ if (err != 0) ++ OTP_ERR(("%s: repair bit failed: %d\n", __FUNCTION__, off)); ++ else ++ OTP_ERR(("%s: repair bit ok: %d\n", __FUNCTION__, off)); ++ } ++ ++ off++; ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++#endif /* OTP_DEBUG */ ++ ++static int ++ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint otpwt; ++ int status = 0; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ /* Can damage fuse in 40nm so safeguard against reprogramming */ ++ if (ipxotp40n_read2x(oi, cc, off) != 1) { ++ status = ipxotp40n_write_bit(oi, cc, off); ++ } else { ++ OTP_MSG(("Bit already programmed: %d\n", off)); ++ } ++ } else { ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ status = ipxotp_write_bit_common(oi, cc, off); ++ } ++ ++ return status; ++} ++ ++static int ++ipxotp_write_bits(void *oh, int bn, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int i, j; ++ uint8 temp; ++ int err; ++ ++ if (bn < 0 || bn + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; ) { ++ temp = *data++; ++ for (j = 0; j < 8; j++, i++) { ++ if (i >= bits) ++ break; ++ if (temp & 0x01) ++ { ++ if (ipxotp_write_bit(oi, cc, (uint)(i + bn)) != 0) { ++ OTP_ERR(("%s: write bit failed: %d\n", ++ __FUNCTION__, i + bn)); ++ ++ err = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), i + bn, 1); ++ if (err != 0) { ++ OTP_ERR(("%s: repair bit failed: %d\n", ++ __FUNCTION__, i + bn)); ++ AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN); ++ return -1; ++ } else ++ OTP_ERR(("%s: repair bit ok: %d\n", ++ __FUNCTION__, i + bn)); ++ } ++ } ++ temp >>= 1; ++ } ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++ ++static int ++ipxotp_write_lock_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_ROW_LOCK_40NM : ++ OTPPOC_ROW_LOCK) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, off, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ipxotp_otpwb16(otpinfo_t *oi, chipcregs_t *cc, int wn, uint16 data) ++{ ++ uint base, i; ++ int rc = 0; ++ ++ base = wn * 16; ++ for (i = 0; i < 16; i++) { ++ if (data & (1 << i)) { ++ rc = ipxotp_write_bit(oi, cc, base + i); ++ if (rc != 0) { ++ OTP_ERR(("%s: write bit failed:%d\n", __FUNCTION__, base + i)); ++ ++ rc = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), base + i, 1); ++ if (rc != 0) { ++ OTP_ERR(("%s: repair bit failed:%d\n", ++ __FUNCTION__, base + i)); ++ break; ++ } else ++ OTP_ERR(("%s: repair bit ok:%d\n", __FUNCTION__, base + i)); ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++/* Write OTP redundancy entry: ++ * rde - redundancy entry index (-ve for "next") ++ * bit - bit offset ++ * val - bit value ++ */ ++ ++/* Check if for a particular chip OTP PMU resource is available */ ++static int ++ipxotp_check_otp_pmu_res(chipcregs_t *cc) ++{ ++ switch (cc->chipid & 0x0000ffff) { ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ /* OTP PMU resource not available, hence use global rde index */ ++ return OTP_GLOBAL_RDE_IDX; ++ default: ++ /* OTP PMU resource available, hence calculate rde index */ ++ return -1; ++ } ++ return -1; ++} ++ ++/* Assumes already writable and bypasses power-cycling */ ++static int ++ipxotp_write_rde_nopc(void *oh, chipcregs_t *cc, int rde, uint bit, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint i, temp; ++ int err = BCME_OK; ++ ++#ifdef BCMDBG ++ if ((rde >= (int)oi->rde_cb.offsets) || (bit >= (uint)(oi->rows * oi->cols)) || (val > 1)) ++ return BCME_RANGE; ++#endif ++ ++ if (rde < 0) { ++ for (rde = 0; rde < oi->rde_cb.offsets - 1; rde++) { ++ if ((oi->status & (1 << (oi->rde_cb.stat_shift + rde))) == 0) ++ break; ++ } ++ OTP_ERR(("%s: Auto rde index %d\n", __FUNCTION__, rde)); ++ } ++ else if (rde == OTP_GLOBAL_RDE_IDX) { ++ /* Chips which do not have a OTP PMU res, OTP can't be pwr cycled from the drv. */ ++ /* Hence we need to have a count of the global rde, and populate accordingly. */ ++ ++ /* Find the next available rde location */ ++ while (oi->status & (1 << (oi->rde_cb.stat_shift + oi->rde_idx))) { ++ OTP_MSG(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__, ++ rde, oi->status)); ++ oi->rde_idx++; ++ } ++ rde = oi->rde_idx++; ++ ++ if (rde >= MAXNUMRDES) { ++ OTP_MSG(("%s: No rde location available to fix.\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ } ++ ++ if (oi->status & (1 << (oi->rde_cb.stat_shift + rde))) { ++ OTP_ERR(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__, ++ rde, oi->status)); ++ return BCME_ERROR; ++ } ++ ++ temp = ~(~0 << oi->rde_cb.width) & ++ ((~0 << (oi->rde_cb.val_shift + 1)) | (val << oi->rde_cb.val_shift) | bit); ++ ++ OTP_MSG(("%s: rde %d bit %d val %d bmp 0x%08x\n", __FUNCTION__, rde, bit, val, temp)); ++ ++ for (i = 0; i < oi->rde_cb.width; i ++) { ++ if (!(temp & (1 << i))) ++ continue; ++ if (ipxotp_write_bit(oi, cc, oi->rde_cb.offset[rde] + i) != 0) ++ err = BCME_ERROR; ++ } ++ ++ /* no power-cyclying to just set status */ ++ oi->status |= (1 << (oi->rde_cb.stat_shift + rde)); ++ ++ return err; ++} ++ ++int ++ipxotp_write_rde(void *oh, int rde, uint bit, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int err; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ err = ipxotp_write_rde_nopc(oh, cc, rde, bit, val); ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return err; ++} ++ ++/* Set up redundancy entries for the specified bits */ ++static int ++ipxotp_fix_word16(void *oh, uint wn, uint16 mask, uint16 val, chipcregs_t *cc) ++{ ++ otpinfo_t *oi; ++ uint bit; ++ int rc = 0; ++ ++ oi = (otpinfo_t *)oh; ++ ++ ASSERT(oi != NULL); ++ ASSERT(wn < oi->wsize); ++ ++ for (bit = wn * 16; mask; bit++, mask >>= 1, val >>= 1) { ++ if (mask & 1) { ++ if ((rc = ipxotp_write_rde(oi, ipxotp_check_otp_pmu_res(cc), bit, val & 1))) ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++static int ++ipxotp_check_word16(void *oh, chipcregs_t *cc, uint wn, uint16 val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint16 word = ipxotp_otpr(oi, cc, wn); ++ int rc = 0; ++ ++ if ((word ^= val)) { ++ OTP_MSG(("%s: word %d is 0x%04x, wanted 0x%04x, fixing...\n", ++ __FUNCTION__, wn, (word ^ val), val)); ++ ++ if ((rc = ipxotp_fix_word16(oi, wn, word, val, cc))) { ++ OTP_ERR(("FAILED, ipxotp_fix_word16 returns %d\n", rc)); ++ /* Fatal error, unfixable. MFGC will have to fail. Board ++ * needs to be discarded!! ++ */ ++ return BCME_NORESOURCE; ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++ipxotp_write_region(void *oh, int region, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint base, i; ++ int otpgu_bit_base; ++ bool rewrite = FALSE; ++ int rc = 0; ++#if defined(DONGLEBUILD) ++ uint16 *origdata = NULL; ++#endif /* DONGLEBUILD */ ++ ++ otpgu_bit_base = oi->otpgu_base * 16; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ if (wlen > (uint)(oi->hwlim - oi->hwbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP h/w region limit %u\n", ++ __FUNCTION__, wlen, oi->hwlim - oi->hwbase)); ++ return BCME_BUFTOOLONG; ++ } ++ rewrite = !!(oi->status & OTPS_GUP_HW); ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ if (wlen > (uint)(oi->swlim - oi->swbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP s/w region limit %u\n", ++ __FUNCTION__, wlen, oi->swlim - oi->swbase)); ++ return BCME_BUFTOOLONG; ++ } ++ rewrite = !!(oi->status & OTPS_GUP_SW); ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ if (oi->status & OTPS_GUP_CI) { ++ OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (wlen > OTPGU_CI_SZ) { ++ OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n", ++ __FUNCTION__, wlen, OTPGU_CI_SZ)); ++ return BCME_BUFTOOLONG; ++ } ++ if ((wlen == OTPGU_CI_SZ) && (data[OTPGU_CI_SZ - 1] & OTPGU_P_MSK) != 0) { ++ OTP_ERR(("%s: subregion programmed bits not zero\n", __FUNCTION__)); ++ return BCME_BADARG; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ if (oi->status & OTPS_GUP_FUSE) { ++ OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (wlen > (uint)(oi->flim - oi->fbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n", ++ __FUNCTION__, wlen, oi->flim - oi->fbase)); ++ return BCME_BUFTOOLONG; ++ } ++ base = oi->flim - wlen; ++ break; ++ default: ++ OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__, region)); ++ return BCME_ERROR; ++ } ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++#if defined(DONGLEBUILD) ++ /* Check for conflict; Since some bits might be programmed at ATE time, we need to ++ * avoid redundancy by clearing already written bits, but copy original for verification. ++ */ ++ if ((origdata = (uint16*)MALLOC(oi->osh, wlen * 2)) == NULL) { ++ rc = BCME_NOMEM; ++ goto exit; ++ } ++ for (i = 0; i < wlen; i++) { ++ origdata[i] = data[i]; ++ data[i] = ipxotp_otpr(oi, cc, base + i); ++ if (data[i] & ~origdata[i]) { ++ OTP_ERR(("%s: %s region: word %d incompatible (0x%04x->0x%04x)\n", ++ __FUNCTION__, HWSW_RGN(region), i, data[i], origdata[i])); ++ rc = BCME_BADARG; ++ goto exit; ++ } ++ data[i] ^= origdata[i]; ++ } ++#endif /* DONGLEBUILD */ ++ ++ OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__, HWSW_RGN(region))); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ /* Write the data */ ++ for (i = 0; i < wlen; i++) { ++ rc = ipxotp_otpwb16(oi, cc, base + i, data[i]); ++ if (rc != 0) { ++ OTP_ERR(("%s: otpwb16 failed: %d 0x%x\n", __FUNCTION__, base + i, data[i])); ++ ipxotp_unwritable(oi, cc); ++ goto exit; ++ } ++ } ++ ++ /* One time set region flag: Update boundary/flag in memory and in OTP */ ++ if (!rewrite) { ++ switch (region) { ++ case OTP_HW_RGN: ++ /* OTP unification */ ++ if (oi->buotp) { ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ ((base + oi->usbmanfid_offset) * 16)); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF); ++ } else ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ (base + i) * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_HWP_OFF); ++ if (CHIPID(oi->sih->chip) == BCM4336_CHIP_ID || ++ CHIPID(oi->sih->chip) == BCM43362_CHIP_ID || ++ CHIPID(oi->sih->chip) == BCM4324_CHIP_ID) ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_NEWCISFORMAT_OFF); ++ break; ++ case OTP_SW_RGN: ++ /* Write HW region limit as well */ ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, base * 16); ++ /* write max swlim(covert to bits) to the sw/fuse boundary */ ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, oi->swlim * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF); ++ break; ++ case OTP_CI_RGN: ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_CIP_OFF); ++ /* Also set the OTPGU_CIP_MSK bit in the input so verification ++ * doesn't fail ++ */ ++ if (wlen >= OTPGU_CI_SZ) ++ data[OTPGU_CI_SZ - 1] |= OTPGU_CIP_MSK; ++ break; ++ case OTP_FUSE_RGN: ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, base * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_FUSEP_OFF); ++ break; ++ } ++ } ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ ++ /* Check and fix for region size and region programmed bits */ ++ if (!rewrite) { ++ uint16 boundary_off = 0, boundary_val = 0; ++ uint16 programmed_off = 0; ++ uint16 bit = 0; ++ ++ switch (region) { ++ case OTP_HW_RGN: ++ boundary_off = OTPGU_HSB_OFF; ++ /* OTP unification */ ++ if (oi->buotp) { ++ boundary_val = ((base + oi->usbmanfid_offset) * 16); ++ } else ++ boundary_val = (base + i) * 16; ++ programmed_off = OTPGU_HWP_OFF; ++ break; ++ case OTP_SW_RGN: ++ /* Also write 0 to HW region boundary */ ++ if ((rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ base * 16))) ++ goto exit; ++ boundary_off = OTPGU_SFB_OFF; ++ boundary_val = oi->swlim * 16; ++ programmed_off = OTPGU_SWP_OFF; ++ break; ++ case OTP_CI_RGN: ++ /* No CI region boundary */ ++ programmed_off = OTPGU_CIP_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ boundary_off = OTPGU_SFB_OFF; ++ boundary_val = base * 16; ++ programmed_off = OTPGU_FUSEP_OFF; ++ break; ++ } ++ ++ /* Do the actual checking and return BCME_NORESOURCE if we cannot fix */ ++ if ((region != OTP_CI_RGN) && ++ (rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + boundary_off, ++ boundary_val))) { ++ goto exit; ++ } ++ ++ if ((bit = ipxotp_read_bit(oh, cc, otpgu_bit_base + programmed_off)) == 0xffff) { ++ OTP_ERR(("\n%s: FAILED bit %d reads %d\n", __FUNCTION__, otpgu_bit_base + ++ programmed_off, bit)); ++ goto exit; ++ } else if (bit == 0) { /* error detected, fix it */ ++ OTP_ERR(("\n%s: FAILED bit %d reads %d, fixing\n", __FUNCTION__, ++ otpgu_bit_base + programmed_off, bit)); ++ if ((rc = ipxotp_write_rde(oi, ipxotp_check_otp_pmu_res(cc), ++ otpgu_bit_base + programmed_off, 1))) { ++ OTP_ERR(("\n%s: cannot fix, ipxotp_write_rde returns %d\n", ++ __FUNCTION__, rc)); ++ goto exit; ++ } ++ } ++ } ++ ++ /* Update status, apply WAR */ ++ _ipxotp_init(oi, cc); ++ ++#if defined(DONGLEBUILD) ++ /* Recover original data... */ ++ if (origdata) ++ bcopy(origdata, data, wlen * 2); ++#endif /* DONGLEBUILD */ ++ ++ /* ...Check again so we can verify and fix where possible */ ++ for (i = 0; i < wlen; i++) { ++ if ((rc = ipxotp_check_word16(oi, cc, base + i, data[i]))) ++ goto exit; ++ } ++ ++exit: ++#if defined(DONGLEBUILD) ++ if (origdata) ++ MFREE(oi->osh, origdata, wlen * 2); ++#endif /* DONGLEBUILD */ ++ si_setcoreidx(oi->sih, idx); ++ return rc; ++} ++ ++static int ++ipxotp_write_word(void *oh, uint wn, uint16 data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int rc = 0; ++ uint16 origdata; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Check for conflict */ ++ origdata = data; ++ data = ipxotp_otpr(oi, cc, wn); ++ if (data & ~origdata) { ++ OTP_ERR(("%s: word %d incompatible (0x%04x->0x%04x)\n", ++ __FUNCTION__, wn, data, origdata)); ++ rc = BCME_BADARG; ++ goto exit; ++ } ++ data ^= origdata; ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ rc = ipxotp_otpwb16(oi, cc, wn, data); ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ data = origdata; ++ if ((rc = ipxotp_check_word16(oi, cc, wn, data))) ++ goto exit; ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return rc; ++} ++ ++static int ++ipxotp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ uint8 *cis; ++ osl_t *osh; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int rc = 0; ++ bool newchip = FALSE; ++ uint overwrite = 0; ++ ++ ASSERT(region == OTP_HW_RGN || region == OTP_SW_RGN); ++ ++ osh = si_osh(sih); ++ if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return BCME_ERROR; ++ } ++ ++ bzero(cis, OTP_SZ_MAX); ++ ++ rc = otp_read_region(sih, region, (uint16 *)cis, &sz); ++ newchip = (rc == BCME_NOTFOUND) ? TRUE : FALSE; ++ if ((rc != 0) && (rc != BCME_NOTFOUND)) { ++ return BCME_ERROR; ++ } ++ rc = 0; ++ ++ /* zero count for read, non-zero count for write */ ++ if (count) { ++ int i = 0, newlen = 0; ++ ++ if (newchip) { ++ int termw_len = 0; /* length of termination word */ ++ ++ /* convert halfwords to bytes offset */ ++ newlen = sz * 2; ++ ++ if ((CHIPID(sih->chip) == BCM4322_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43231_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4315_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4319_CHIP_ID)) { ++ /* bootloader WAR, refer to above twiki link */ ++ cis[newlen-1] = 0x00; ++ cis[newlen-2] = 0xff; ++ cis[newlen-3] = 0x00; ++ cis[newlen-4] = 0xff; ++ cis[newlen-5] = 0xff; ++ cis[newlen-6] = 0x1; ++ cis[newlen-7] = 0x2; ++ termw_len = 7; ++ } else { ++ cis[newlen-1] = 0xff; ++ cis[newlen-2] = 0xff; ++ termw_len = 2; ++ } ++ ++ if (count >= newlen - termw_len) { ++ OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen, count)); ++ rc = BCME_BUFTOOLONG; ++ } ++ } else { ++ int end = 0; ++ if (region == OTP_SW_RGN) { ++ /* Walk through the leading zeros (could be 0 or 8 bytes for now) */ ++ for (i = 0; i < (int)sz*2; i++) ++ if (cis[i] != 0) ++ break; ++ } else { ++ /* move pass the hardware header */ ++ if (sih->ccrev >= 36) { ++ uint32 otp_layout; ++ otp_layout = si_corereg(sih, SI_CC_IDX, ++ OFFSETOF(chipcregs_t, otplayout), 0, 0); ++ if (otp_layout & OTP_CISFORMAT_NEW) { ++ i += 4; /* new sdio header format, 2 half words */ ++ } else { ++ i += 8; /* old sdio header format */ ++ } ++ } else { ++ return BCME_ERROR; /* old chip, not suppported */ ++ } ++ } ++ ++ /* Find the place to append */ ++ for (; i < (int)sz*2; i++) { ++ int j; ++ if (cis[i] == 0) ++ break; ++ /* If the tuple exist, check if it can be overwritten */ ++ if (cis[i + 2] == vars[2]) { ++ if (cis[i+1] == vars[1]) { ++ /* found, check if it is compiatable for fix */ ++ for (j = 0; j < cis[i+1] + 2; j++) { ++ if ((cis[i+j] ^ vars[j]) & cis[i+j]) { ++ break; ++ } ++ } ++ if (j == cis[i+1] + 2) { ++ overwrite = i; ++ } ++ } ++ } ++ i += ((int)cis[i+1] + 1); ++ } ++ for (end = i; end < (int)sz*2; end++) { ++ if (cis[end] != 0) ++ break; ++ } ++ if (overwrite) ++ i = overwrite; ++ ++ newlen = i + count; ++ if (newlen & 1) /* make it even-sized buffer */ ++ newlen++; ++ ++ if (newlen >= (end - 1)) { ++ OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", end-i, count)); ++ rc = BCME_BUFTOOLONG; ++ } ++ } ++ ++ /* copy the buffer */ ++ memcpy(&cis[i], vars, count); ++#ifdef BCMNVRAMW ++ /* Write the buffer back */ ++ if (!rc) ++ rc = otp_write_region(sih, region, (uint16*)cis, newlen/2); ++ ++ /* Print the buffer */ ++ OTP_MSG(("Buffer of size %d bytes to write:\n", newlen)); ++ for (i = 0; i < newlen; i++) { ++ OTP_DBG(("%02x ", cis[i] & 0xff)); ++ if ((i % 16) == 15) { ++ OTP_DBG(("\n")); ++ } ++ } ++ OTP_MSG(("\n")); ++#endif /* BCMNVRAMW */ ++ } ++ if (cis) ++ MFREE(osh, cis, OTP_SZ_MAX); ++ ++ return (rc); ++} ++ ++/* No need to lock for IPXOTP */ ++static int ++ipxotp_lock(void *oh) ++{ ++ uint idx; ++ chipcregs_t *cc; ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0, rc = 0; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW1_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock ROW1\n")); ++ rc = -1; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW2_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock ROW2\n")); ++ rc = -2; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_RD_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock RD\n")); ++ rc = -3; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_GU_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock GU\n")); ++ rc = -4; ++ } ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ ++ /* Update status, apply WAR */ ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return rc; ++} ++ ++static int ++ipxotp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ return -1; ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++static uint16 ++ipxotp_otprb16(void *oh, chipcregs_t *cc, uint wn) ++{ ++ uint base, i; ++ uint16 val; ++ uint16 bit; ++ ++ base = wn * 16; ++ ++ val = 0; ++ for (i = 0; i < 16; i++) { ++ if ((bit = ipxotp_read_bit(oh, cc, base + i)) == 0xffff) ++ break; ++ val = val | (bit << i); ++ } ++ if (i < 16) ++ val = 0xffff; ++ ++ return val; ++} ++ ++static int ++ipxotp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, i, count; ++ uint16 val; ++ struct bcmstrbuf b; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ count = ipxotp_size(oh); ++ ++ bcm_binit(&b, buf, size); ++ for (i = 0; i < count / 2; i++) { ++ if (!(i % 4)) ++ bcm_bprintf(&b, "\n0x%04x:", 2 * i); ++ if (arg == 0) ++ val = ipxotp_otpr(oh, cc, i); ++ else ++ val = ipxotp_otprb16(oi, cc, i); ++ bcm_bprintf(&b, " 0x%04x", val); ++ } ++ bcm_bprintf(&b, "\n"); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ((int)(b.buf - b.origbuf)); ++} ++#endif ++ ++static otp_fn_t ipxotp_fn = { ++ (otp_size_t)ipxotp_size, ++ (otp_read_bit_t)ipxotp_read_bit, ++ (otp_dump_t)NULL, /* Assigned in otp_init */ ++ (otp_status_t)ipxotp_status, ++ ++ (otp_init_t)ipxotp_init, ++ (otp_read_region_t)ipxotp_read_region, ++ (otp_nvread_t)ipxotp_nvread, ++#ifdef BCMNVRAMW ++ (otp_write_region_t)ipxotp_write_region, ++ (otp_cis_append_region_t)ipxotp_cis_append_region, ++ (otp_lock_t)ipxotp_lock, ++ (otp_nvwrite_t)ipxotp_nvwrite, ++ (otp_write_word_t)ipxotp_write_word, ++#else /* BCMNVRAMW */ ++ (otp_write_region_t)NULL, ++ (otp_cis_append_region_t)NULL, ++ (otp_lock_t)NULL, ++ (otp_nvwrite_t)NULL, ++ (otp_write_word_t)NULL, ++#endif /* BCMNVRAMW */ ++ (otp_read_word_t)ipxotp_read_word, ++#if defined(BCMNVRAMW) ++ (otp_write_bits_t)ipxotp_write_bits ++#endif ++}; ++ ++#endif /* BCMIPXOTP */ ++ ++ ++/* ++ * HND OTP Code ++ * ++ * Exported functions: ++ * hndotp_status() ++ * hndotp_size() ++ * hndotp_init() ++ * hndotp_read_bit() ++ * hndotp_read_region() ++ * hndotp_read_word() ++ * hndotp_nvread() ++ * hndotp_write_region() ++ * hndotp_cis_append_region() ++ * hndotp_lock() ++ * hndotp_nvwrite() ++ * hndotp_dump() ++ * ++ * HND internal functions: ++ * hndotp_otpr() ++ * hndotp_otproff() ++ * hndotp_write_bit() ++ * hndotp_write_word() ++ * hndotp_valid_rce() ++ * hndotp_write_rce() ++ * hndotp_write_row() ++ * hndotp_otprb16() ++ * ++ */ ++ ++#ifdef BCMHNDOTP ++ ++/* Fields in otpstatus */ ++#define OTPS_PROGFAIL 0x80000000 ++#define OTPS_PROTECT 0x00000007 ++#define OTPS_HW_PROTECT 0x00000001 ++#define OTPS_SW_PROTECT 0x00000002 ++#define OTPS_CID_PROTECT 0x00000004 ++#define OTPS_RCEV_MSK 0x00003f00 ++#define OTPS_RCEV_SHIFT 8 ++ ++/* Fields in the otpcontrol register */ ++#define OTPC_RECWAIT 0xff000000 ++#define OTPC_PROGWAIT 0x00ffff00 ++#define OTPC_PRW_SHIFT 8 ++#define OTPC_MAXFAIL 0x00000038 ++#define OTPC_VSEL 0x00000006 ++#define OTPC_SELVL 0x00000001 ++ ++/* OTP regions (Word offsets from otp size) */ ++#define OTP_SWLIM_OFF (-4) ++#define OTP_CIDBASE_OFF 0 ++#define OTP_CIDLIM_OFF 4 ++ ++/* Predefined OTP words (Word offset from otp size) */ ++#define OTP_BOUNDARY_OFF (-4) ++#define OTP_HWSIGN_OFF (-3) ++#define OTP_SWSIGN_OFF (-2) ++#define OTP_CIDSIGN_OFF (-1) ++#define OTP_CID_OFF 0 ++#define OTP_PKG_OFF 1 ++#define OTP_FID_OFF 2 ++#define OTP_RSV_OFF 3 ++#define OTP_LIM_OFF 4 ++#define OTP_RD_OFF 4 /* Redundancy row starts here */ ++#define OTP_RC0_OFF 28 /* Redundancy control word 1 */ ++#define OTP_RC1_OFF 32 /* Redundancy control word 2 */ ++#define OTP_RC_LIM_OFF 36 /* Redundancy control word end */ ++ ++#define OTP_HW_REGION OTPS_HW_PROTECT ++#define OTP_SW_REGION OTPS_SW_PROTECT ++#define OTP_CID_REGION OTPS_CID_PROTECT ++ ++#if OTP_HW_REGION != OTP_HW_RGN ++#error "incompatible OTP_HW_RGN" ++#endif ++#if OTP_SW_REGION != OTP_SW_RGN ++#error "incompatible OTP_SW_RGN" ++#endif ++#if OTP_CID_REGION != OTP_CI_RGN ++#error "incompatible OTP_CI_RGN" ++#endif ++ ++/* Redundancy entry definitions */ ++#define OTP_RCE_ROW_SZ 6 ++#define OTP_RCE_SIGN_MASK 0x7fff ++#define OTP_RCE_ROW_MASK 0x3f ++#define OTP_RCE_BITS 21 ++#define OTP_RCE_SIGN_SZ 15 ++#define OTP_RCE_BIT0 1 ++ ++#define OTP_WPR 4 ++#define OTP_SIGNATURE 0x578a ++#define OTP_MAGIC 0x4e56 ++ ++static int ++hndotp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return ((int)(oi->hwprot | oi->signvalid)); ++} ++ ++static int ++hndotp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return ((int)(oi->size)); ++} ++ ++static uint16 ++hndotp_otpr(void *oh, chipcregs_t *cc, uint wn) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ volatile uint16 *ptr; ++ ++ ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF)); ++ ASSERT(cc != NULL); ++ ++ osh = si_osh(oi->sih); ++ ++ ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP); ++ return (R_REG(osh, &ptr[wn])); ++} ++ ++static uint16 ++hndotp_otproff(void *oh, chipcregs_t *cc, int woff) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ volatile uint16 *ptr; ++ ++ ASSERT(woff >= (-((int)oi->size / 2))); ++ ASSERT(woff < OTP_LIM_OFF); ++ ASSERT(cc != NULL); ++ ++ osh = si_osh(oi->sih); ++ ++ ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP); ++ ++ return (R_REG(osh, &ptr[(oi->size / 2) + woff])); ++} ++ ++static uint16 ++hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint k, row, col; ++ uint32 otpp, st; ++ osl_t *osh; ++ ++ osh = si_osh(oi->sih); ++ row = idx / 65; ++ col = idx % 65; ++ ++ otpp = OTPP_START_BUSY | OTPP_READ | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ (col & OTPP_COL_MASK); ++ ++ OTP_DBG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__, ++ idx, row, col, otpp)); ++ ++ W_REG(osh, &cc->otpprog, otpp); ++ st = R_REG(osh, &cc->otpprog); ++ for (k = 0; ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ++ st = R_REG(osh, &cc->otpprog); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return 0xffff; ++ } ++ if (st & OTPP_READERR) { ++ OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, idx)); ++ return 0xffff; ++ } ++ st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; ++ OTP_DBG((" => %d\n", st)); ++ return (uint16)st; ++} ++ ++static void * ++BCMNMIATTACHFN(hndotp_init)(si_t *sih) ++{ ++ uint idx; ++ chipcregs_t *cc; ++ otpinfo_t *oi; ++ uint32 cap = 0, clkdiv, otpdiv = 0; ++ void *ret = NULL; ++ osl_t *osh; ++ ++ OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__)); ++ ++ oi = get_otpinfo(); ++ ++ idx = si_coreidx(sih); ++ osh = si_osh(oi->sih); ++ ++ /* Check for otp */ ++ if ((cc = si_setcoreidx(sih, SI_CC_IDX)) != NULL) { ++ cap = R_REG(osh, &cc->capabilities); ++ if ((cap & CC_CAP_OTPSIZE) == 0) { ++ /* Nothing there */ ++ goto out; ++ } ++ ++ /* As of right now, support only 4320a2, 4311a1 and 4312 */ ++ ASSERT((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22)); ++ if (!((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22))) ++ return NULL; ++ ++ /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is ++ * 8 row (64 bytes) smaller ++ */ ++ oi->size = 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) ++ + CC_CAP_OTPSIZE_BASE); ++ if (oi->ccrev >= 18) { ++ oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2); ++ } else { ++ OTP_ERR(("Negative otp size, shouldn't happen for programmed chip.")); ++ oi->size = 0; ++ } ++ ++ oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT); ++ oi->boundary = -1; ++ ++ /* Check the region signature */ ++ if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) { ++ oi->signvalid |= OTP_HW_REGION; ++ oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF); ++ } ++ ++ if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE) ++ oi->signvalid |= OTP_SW_REGION; ++ ++ if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE) ++ oi->signvalid |= OTP_CID_REGION; ++ ++ /* Set OTP clkdiv for stability */ ++ if (oi->ccrev == 22) ++ otpdiv = 12; ++ ++ if (otpdiv) { ++ clkdiv = R_REG(osh, &cc->clkdiv); ++ clkdiv = (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT); ++ W_REG(osh, &cc->clkdiv, clkdiv); ++ OTP_MSG(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv)); ++ } ++ OSL_DELAY(10); ++ ++ ret = (void *)oi; ++ } ++ ++ OTP_MSG(("%s: ccrev %d\tsize %d bytes\thwprot %x\tsignvalid %x\tboundary %x\n", ++ __FUNCTION__, oi->ccrev, oi->size, oi->hwprot, oi->signvalid, ++ oi->boundary)); ++ ++out: /* All done */ ++ si_setcoreidx(sih, idx); ++ ++ return ret; ++} ++ ++static int ++hndotp_read_region(void *oh, int region, uint16 *data, uint *wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 idx, st; ++ chipcregs_t *cc; ++ int i; ++ ++ /* Only support HW region (no active chips use HND OTP SW region) */ ++ ASSERT(region == OTP_HW_REGION); ++ ++ OTP_MSG(("%s: region %x wlen %d\n", __FUNCTION__, region, *wlen)); ++ ++ /* Region empty? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & region) == 0) ++ return BCME_NOTFOUND; ++ ++ *wlen = ((int)*wlen < oi->boundary/2) ? *wlen : (uint)oi->boundary/2; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ for (i = 0; i < (int)*wlen; i++) ++ data[i] = hndotp_otpr(oh, cc, i); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return 0; ++} ++ ++static int ++hndotp_read_word(void *oh, uint wn, uint16 *data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ *data = hndotp_otpr(oh, cc, wn); ++ ++ si_setcoreidx(oi->sih, idx); ++ return 0; ++} ++ ++static int ++hndotp_nvread(void *oh, char *data, uint *len) ++{ ++ int rc = 0; ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 base, bound, lim = 0, st; ++ int i, chunk, gchunks, tsz = 0; ++ uint32 idx; ++ chipcregs_t *cc; ++ uint offset; ++ uint16 *rawotp = NULL; ++ ++ /* save the orig core */ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ st = hndotp_status(oh); ++ if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) { ++ OTP_ERR(("OTP not programmed\n")); ++ rc = -1; ++ goto out; ++ } ++ ++ /* Read the whole otp so we can easily manipulate it */ ++ lim = hndotp_size(oh); ++ if (lim == 0) { ++ OTP_ERR(("OTP size is 0\n")); ++ rc = -1; ++ goto out; ++ } ++ if ((rawotp = MALLOC(si_osh(oi->sih), lim)) == NULL) { ++ OTP_ERR(("Out of memory for rawotp\n")); ++ rc = -2; ++ goto out; ++ } ++ for (i = 0; i < (int)(lim / 2); i++) ++ rawotp[i] = hndotp_otpr(oh, cc, i); ++ ++ if ((st & OTP_HW_REGION) == 0) { ++ OTP_ERR(("otp: hw region not written (0x%x)\n", st)); ++ ++ /* This could be a programming failure in the first ++ * chunk followed by one or more good chunks ++ */ ++ for (i = 0; i < (int)(lim / 2); i++) ++ if (rawotp[i] == OTP_MAGIC) ++ break; ++ ++ if (i < (int)(lim / 2)) { ++ base = i; ++ bound = (i * 2) + rawotp[i + 1]; ++ OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i * 2, bound)); ++ } else { ++ OTP_MSG(("otp: unprogrammed\n")); ++ rc = -3; ++ goto out; ++ } ++ } else { ++ bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF]; ++ ++ /* There are two cases: 1) The whole otp is used as nvram ++ * and 2) There is a hardware header followed by nvram. ++ */ ++ if (rawotp[0] == OTP_MAGIC) { ++ base = 0; ++ if (bound != rawotp[1]) ++ OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound, ++ rawotp[1])); ++ } else ++ base = bound; ++ } ++ ++ /* Find and copy the data */ ++ ++ chunk = 0; ++ gchunks = 0; ++ i = base / 2; ++ offset = 0; ++ while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) { ++ int dsz, rsz = rawotp[i + 1]; ++ ++ if (((i * 2) + rsz) >= (int)lim) { ++ OTP_MSG((" bad chunk size, chunk %d, base 0x%x, size 0x%x\n", ++ chunk, i * 2, rsz)); ++ /* Bad length, try to find another chunk anyway */ ++ rsz = 6; ++ } ++ if (hndcrc16((uint8 *)&rawotp[i], rsz, ++ CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) { ++ /* Good crc, copy the vars */ ++ OTP_MSG((" good chunk %d, base 0x%x, size 0x%x\n", ++ chunk, i * 2, rsz)); ++ gchunks++; ++ dsz = rsz - 6; ++ tsz += dsz; ++ if (offset + dsz >= *len) { ++ OTP_MSG(("Out of memory for otp\n")); ++ goto out; ++ } ++ bcopy((char *)&rawotp[i + 2], &data[offset], dsz); ++ offset += dsz; ++ /* Remove extra null characters at the end */ ++ while (offset > 1 && ++ data[offset - 1] == 0 && data[offset - 2] == 0) ++ offset --; ++ i += rsz / 2; ++ } else { ++ /* bad length or crc didn't check, try to find the next set */ ++ OTP_MSG((" chunk %d @ 0x%x size 0x%x: bad crc, ", ++ chunk, i * 2, rsz)); ++ if (rawotp[i + (rsz / 2)] == OTP_MAGIC) { ++ /* Assume length is good */ ++ i += rsz / 2; ++ } else { ++ while (++i < (int)(lim / 2)) ++ if (rawotp[i] == OTP_MAGIC) ++ break; ++ } ++ if (i < (int)(lim / 2)) ++ OTP_MSG(("trying next base 0x%x\n", i * 2)); ++ else ++ OTP_MSG(("no more chunks\n")); ++ } ++ chunk++; ++ } ++ ++ OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim, bound, base)); ++ if (tsz != 0) { ++ OTP_MSG((" Found %d bytes in %d good chunks out of %d\n", tsz, gchunks, chunk)); ++ } else { ++ OTP_MSG((" No good chunks found out of %d\n", chunk)); ++ } ++ ++ *len = offset; ++ ++out: ++ if (rawotp) ++ MFREE(si_osh(oi->sih), rawotp, lim); ++ si_setcoreidx(oi->sih, idx); ++ ++ return rc; ++} ++ ++#ifdef BCMNVRAMW ++#if defined(BCMDBG) || defined(WLTEST) ++static uint st_n, st_s, st_hwm, pp_hwm; ++#ifdef OTP_FORCEFAIL ++static uint forcefail_bitcount = 0; ++#endif /* OTP_FORCEFAIL */ ++#endif /* BCMDBG || WLTEST */ ++ ++static int ++hndotp_write_bit(void *oh, chipcregs_t *cc, int bn, bool bit, int no_retry) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint row, col, j, k; ++ uint32 pwait, init_pwait, otpc, otpp, pst, st; ++ osl_t *osh; ++ ++ osh = si_osh(oi->sih); ++ ASSERT((bit >> 1) == 0); ++ ++#ifdef OTP_FORCEFAIL ++ OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__, wn * 2, data)); ++#endif ++ ++ /* This is bit-at-a-time writing, future cores may do word-at-a-time */ ++ if (oi->ccrev == 12) { ++ otpc = 0x20000001; ++ init_pwait = 0x00000200; ++ } else if (oi->ccrev == 22) { ++ otpc = 0x20000001; ++ init_pwait = 0x00000400; ++ } else { ++ otpc = 0x20000001; ++ init_pwait = 0x00004000; ++ } ++ ++ pwait = init_pwait; ++ row = bn / 65; ++ col = bn % 65; ++ otpp = OTPP_START_BUSY | ++ ((bit << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ (col & OTPP_COL_MASK); ++ j = 0; ++ while (1) { ++ j++; ++ if (j > 1) { ++ OTP_DBG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n", ++ row, col, bit, (otpc | pwait), otpp)); ++ } ++ W_REG(osh, &cc->otpcontrol, otpc | pwait); ++ W_REG(osh, &cc->otpprog, otpp); ++ pst = R_REG(osh, &cc->otpprog); ++ for (k = 0; ((pst & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ++ pst = R_REG(osh, &cc->otpprog); ++#if defined(BCMDBG) || defined(WLTEST) ++ if (k > pp_hwm) ++ pp_hwm = k; ++#endif /* BCMDBG || WLTEST */ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst, k)); ++ st = OTPS_PROGFAIL; ++ break; ++ } ++ st = R_REG(osh, &cc->otpstatus); ++ if (((st & OTPS_PROGFAIL) == 0) || (pwait == OTPC_PROGWAIT) || (no_retry)) { ++ break; ++ } else { ++ if ((oi->ccrev == 12) || (oi->ccrev == 22)) ++ pwait = (pwait << 3) & OTPC_PROGWAIT; ++ else ++ pwait = (pwait << 1) & OTPC_PROGWAIT; ++ if (pwait == 0) ++ pwait = OTPC_PROGWAIT; ++ } ++ } ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n++; ++ st_s += j; ++ if (j > st_hwm) ++ st_hwm = j; ++#ifdef OTP_FORCEFAIL ++ if (forcefail_bitcount++ == OTP_FORCEFAIL * 16) { ++ OTP_DBG(("Forcing PROGFAIL on bit %d (FORCEFAIL = %d/0x%x)\n", ++ forcefail_bitcount, OTP_FORCEFAIL, OTP_FORCEFAIL)); ++ st = OTPS_PROGFAIL; ++ } ++#endif ++#endif /* BCMDBG || WLTEST */ ++ if (st & OTPS_PROGFAIL) { ++ OTP_ERR(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n", ++ j, otpc | pwait, otpp, pst, st)); ++ OTP_ERR(("otp prog failed. bit=%d, ppret=%d, ret=%d\n", bit, k, j)); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++hndotp_write_bits(void *oh, int bn, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int i, j; ++ uint8 temp; ++ ++ if (bn < 0 || bn + bits >= oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ for (i = 0; i < bits; ) { ++ temp = *data++; ++ for (j = 0; j < 8; j++, i++) { ++ if (i >= bits) ++ break; ++ if (hndotp_write_bit(oh, cc, i + bn, (temp & 0x01), 0) != 0) { ++ return -1; ++ } ++ temp >>= 1; ++ } ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++static int ++hndotp_write_word(void *oh, chipcregs_t *cc, int wn, uint16 data) ++{ ++ uint base, i; ++ int err = 0; ++ ++ OTP_MSG(("%s: wn %d data %x\n", __FUNCTION__, wn, data)); ++ ++ /* There is one test bit for each row */ ++ base = (wn * 16) + (wn / 4); ++ ++ for (i = 0; i < 16; i++) { ++ err += hndotp_write_bit(oh, cc, base + i, data & 1, 0); ++ data >>= 1; ++ /* abort write after first error to avoid stress the charge-pump */ ++ if (err) { ++ OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__, wn, i)); ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++static int ++hndotp_valid_rce(void *oh, chipcregs_t *cc, int i) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ uint32 hwv, fw, rce, e, sign, row, st; ++ ++ ASSERT(oi->ccrev >= 18); ++ ++ /* HW valid bit */ ++ osh = si_osh(oi->sih); ++ st = R_REG(osh, &cc->otpstatus); ++ hwv = (st & OTPS_RCEV_MSK) & (1 << (OTPS_RCEV_SHIFT + i)); ++ BCM_REFERENCE(hwv); ++ ++ if (i < 3) { ++ e = i; ++ fw = hndotp_size(oh)/2 + OTP_RC0_OFF + e; ++ } else { ++ e = i - 3; ++ fw = hndotp_size(oh)/2 + OTP_RC1_OFF + e; ++ } ++ ++ rce = hndotp_otpr(oh, cc, fw+1) << 16 | hndotp_otpr(oh, cc, fw); ++ rce >>= ((e * OTP_RCE_BITS) + OTP_RCE_BIT0 - (e * 16)); ++ row = rce & OTP_RCE_ROW_MASK; ++ sign = (rce >> OTP_RCE_ROW_SZ) & OTP_RCE_SIGN_MASK; ++ ++ OTP_MSG(("rce %d sign %x row %d hwv %x\n", i, sign, row, hwv)); ++ ++ return (sign == OTP_SIGNATURE) ? row : -1; ++} ++ ++static int ++hndotp_write_rce(void *oh, chipcregs_t *cc, int r, uint16* data) ++{ ++ int i, rce = -1; ++ uint32 sign; ++ ++ ASSERT(((otpinfo_t *)oh)->ccrev >= 18); ++ ASSERT(r >= 0 && r < hndotp_size(oh)/(2*OTP_WPR)); ++ ASSERT(data); ++ ++ for (rce = OTP_RCE_ROW_SZ -1; rce >= 0; rce--) { ++ int e, rt, rcr, bit, err = 0; ++ ++ int rr = hndotp_valid_rce(oh, cc, rce); ++ /* redundancy row in use already */ ++ if (rr != -1) { ++ if (rr == r) { ++ OTP_MSG(("%s: row %d already replaced by RCE %d", ++ __FUNCTION__, r, rce)); ++ return 0; ++ } ++ ++ continue; /* If row used, go for the next row */ ++ } ++ ++ /* ++ * previously used bad rce entry maybe treaed as valid rce and used again, abort on ++ * first bit error to avoid stress the charge pump ++ */ ++ ++ /* Write the data to the redundant row */ ++ for (i = 0; i < OTP_WPR; i++) { ++ err += hndotp_write_word(oh, cc, hndotp_size(oh)/2+OTP_RD_OFF+rce*4+i, ++ data[i]); ++ if (err) { ++ OTP_MSG(("fail to write redundant row %d\n", rce)); ++ break; ++ } ++ } ++ ++ /* Now write the redundant row index */ ++ if (rce < 3) { ++ e = rce; ++ rcr = hndotp_size(oh)/2 + OTP_RC0_OFF; ++ } else { ++ e = rce - 3; ++ rcr = hndotp_size(oh)/2 + OTP_RC1_OFF; ++ } ++ ++ /* Write row numer bit-by-bit */ ++ bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0; ++ rt = r; ++ for (i = 0; i < OTP_RCE_ROW_SZ; i++) { ++ /* If any timeout happened, invalidate the subsequent bits with 0 */ ++ if (hndotp_write_bit(oh, cc, bit, (rt & (err ? 0 : 1)), err)) { ++ OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row" ++ " number bit %x\n", __FUNCTION__, r, rce, i)); ++ err++; ++ } ++ rt >>= 1; ++ bit ++; ++ } ++ ++ /* Write the RCE signature bit-by-bit */ ++ sign = OTP_SIGNATURE; ++ for (i = 0; i < OTP_RCE_SIGN_SZ; i++) { ++ /* If any timeout happened, invalidate the subsequent bits with 0 */ ++ if (hndotp_write_bit(oh, cc, bit, (sign & (err ? 0 : 1)), err)) { ++ OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row" ++ " number bit %x\n", __FUNCTION__, r, rce, i)); ++ err++; ++ } ++ sign >>= 1; ++ bit ++; ++ } ++ ++ if (err) { ++ OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next" ++ " RCE\n", __FUNCTION__, r, rce, err)); ++ continue; ++ } else { ++ OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__, r, rce)); ++ return BCME_OK; ++ } ++ } ++ ++ OTP_ERR(("All RCE's are in use. Failed fixing OTP.\n")); ++ /* Fatal error, unfixable. MFGC will have to fail. Board needs to be discarded!! */ ++ return BCME_NORESOURCE; ++} ++ ++/* Write a row and fix it with RCE if any error detected */ ++static int ++hndotp_write_row(void *oh, chipcregs_t *cc, int wn, uint16* data, bool rewrite) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0, i; ++ ++ ASSERT(wn % OTP_WPR == 0); ++ ++ /* Write the data */ ++ for (i = 0; i < OTP_WPR; i++) { ++ if (rewrite && (data[i] == hndotp_otpr(oh, cc, wn+i))) ++ continue; ++ ++ err += hndotp_write_word(oh, cc, wn + i, data[i]); ++ } ++ ++ /* Fix this row if any error */ ++ if (err && (oi->ccrev >= 18)) { ++ OTP_DBG(("%s: %d write errors in row %d. Fixing...\n", __FUNCTION__, err, wn/4)); ++ if ((err = hndotp_write_rce(oh, cc, wn / OTP_WPR, data))) ++ OTP_MSG(("%s: failed to fix row %d\n", __FUNCTION__, wn/4)); ++ } ++ ++ return err; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++hndotp_write_region(void *oh, int region, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 st; ++ uint wn, base = 0, lim; ++ int ret = BCME_OK; ++ uint idx; ++ chipcregs_t *cc; ++ bool rewrite = FALSE; ++ uint32 save_clk; ++ ++ ASSERT(wlen % OTP_WPR == 0); ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Check valid region */ ++ if ((region != OTP_HW_REGION) && ++ (region != OTP_SW_REGION) && ++ (region != OTP_CID_REGION)) { ++ ret = BCME_BADARG; ++ goto out; ++ } ++ ++ /* Region already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & region) != 0) ++ rewrite = TRUE; ++ ++ /* HW and CID have to be written before SW */ ++ if ((((st & (OTP_HW_REGION | OTP_CID_REGION)) == 0) && ++ (st & OTP_SW_REGION) != 0)) { ++ OTP_ERR(("%s: HW/CID region should be programmed first\n", __FUNCTION__)); ++ ret = BCME_BADARG; ++ goto out; ++ } ++ ++ /* Bounds for the region */ ++ lim = (oi->size / 2) + OTP_SWLIM_OFF; ++ if (region == OTP_HW_REGION) { ++ base = 0; ++ } else if (region == OTP_SW_REGION) { ++ base = oi->boundary / 2; ++ } else if (region == OTP_CID_REGION) { ++ base = (oi->size / 2) + OTP_CID_OFF; ++ lim = (oi->size / 2) + OTP_LIM_OFF; ++ } ++ ++ if (wlen > (lim - base)) { ++ ret = BCME_BUFTOOLONG; ++ goto out; ++ } ++ lim = base + wlen; ++ ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n = st_s = st_hwm = pp_hwm = 0; ++#endif /* BCMDBG || WLTEST */ ++ ++ /* force ALP for progrramming stability */ ++ save_clk = R_REG(oi->osh, &cc->clk_ctl_st); ++ OR_REG(oi->osh, &cc->clk_ctl_st, CCS_FORCEALP); ++ OSL_DELAY(10); ++ ++ /* Write the data row by row */ ++ for (wn = base; wn < lim; wn += OTP_WPR, data += OTP_WPR) { ++ if ((ret = hndotp_write_row(oh, cc, wn, data, rewrite)) != 0) { ++ if (ret == BCME_NORESOURCE) { ++ OTP_ERR(("%s: Abort at word %x\n", __FUNCTION__, wn)); ++ break; ++ } ++ } ++ } ++ ++ /* Don't need to update signature & boundary if rewrite */ ++ if (rewrite) ++ goto out_rclk; ++ ++ /* Done with the data, write the signature & boundary if needed */ ++ if (region == OTP_HW_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, lim * 2) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->boundary = lim * 2; ++ oi->signvalid |= OTP_HW_REGION; ++ } else if (region == OTP_SW_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_SWSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->signvalid |= OTP_SW_REGION; ++ } else if (region == OTP_CID_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_CIDSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->signvalid |= OTP_CID_REGION; ++ } ++ ++out_rclk: ++ /* Restore clock */ ++ W_REG(oi->osh, &cc->clk_ctl_st, save_clk); ++ ++out: ++#if defined(BCMDBG) || defined(WLTEST) ++ OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n", ++ st_n, st_s, st_n, st_n?(st_s / st_n):0, st_hwm, pp_hwm)); ++#endif ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ret; ++} ++ ++/* For HND OTP, there's no space for appending after filling in SROM image */ ++static int ++hndotp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ return otp_write_region(sih, region, (uint16*)vars, count/2); ++} ++ ++/* ++ * Fill all unwritten RCE signature with 0 and return the number of them. ++ * HNDOTP needs lock due to the randomness of unprogrammed content. ++ */ ++static int ++hndotp_lock(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int i, j, e, rcr, bit, ret = 0; ++ uint32 st, idx; ++ chipcregs_t *cc; ++ ++ ASSERT(oi->ccrev >= 18); ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Region already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == 0) { ++ si_setcoreidx(oi->sih, idx); ++ return BCME_NOTREADY; /* Don't lock unprogrammed OTP */ ++ } ++ ++ /* Find the highest valid RCE */ ++ for (i = 0; i < OTP_RCE_ROW_SZ -1; i++) { ++ if ((hndotp_valid_rce(oh, cc, i) != -1)) ++ break; ++ } ++ i--; /* Start invalidating from the next RCE */ ++ ++ for (; i >= 0; i--) { ++ if ((hndotp_valid_rce(oh, cc, i) == -1)) { ++ ++ ret++; /* This is a unprogrammed row */ ++ ++ /* Invalidate the row with 0 */ ++ if (i < 3) { ++ e = i; ++ rcr = hndotp_size(oh)/2 + OTP_RC0_OFF; ++ } else { ++ e = i - 3; ++ rcr = hndotp_size(oh)/2 + OTP_RC1_OFF; ++ } ++ ++ /* Fill row numer and signature with 0 bit-by-bit */ ++ bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0; ++ for (j = 0; j < (OTP_RCE_ROW_SZ + OTP_RCE_SIGN_SZ); j++) { ++ hndotp_write_bit(oh, cc, bit, 0, 1); ++ bit ++; ++ } ++ ++ OTP_MSG(("locking rce %d\n", i)); ++ } ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ret; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++hndotp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 st; ++ uint16 crc, clen, *p, hdr[2]; ++ uint wn, base = 0, lim; ++ int err, gerr = 0; ++ uint idx; ++ chipcregs_t *cc; ++ ++ /* otp already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == (OTP_HW_REGION | OTP_SW_REGION)) ++ return BCME_EPERM; ++ ++ /* save the orig core */ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Bounds for the region */ ++ lim = (oi->size / 2) + OTP_SWLIM_OFF; ++ base = 0; ++ ++ /* Look for possible chunks from the end down */ ++ wn = lim; ++ while (wn > 0) { ++ wn--; ++ if (hndotp_otpr(oh, cc, wn) == OTP_MAGIC) { ++ base = wn + (hndotp_otpr(oh, cc, wn + 1) / 2); ++ break; ++ } ++ } ++ if (base == 0) { ++ OTP_MSG(("Unprogrammed otp\n")); ++ } else { ++ OTP_MSG(("Found some chunks, skipping to 0x%x\n", base * 2)); ++ } ++ if ((wlen + 3) > (lim - base)) { ++ err = BCME_NORESOURCE; ++ goto out; ++ } ++ ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n = st_s = st_hwm = pp_hwm = 0; ++#endif /* BCMDBG || WLTEST */ ++ ++ /* Prepare the header and crc */ ++ hdr[0] = OTP_MAGIC; ++ hdr[1] = (wlen + 3) * 2; ++ crc = hndcrc16((uint8 *)hdr, sizeof(hdr), CRC16_INIT_VALUE); ++ crc = hndcrc16((uint8 *)data, wlen * 2, crc); ++ crc = ~crc; ++ ++ do { ++ p = data; ++ wn = base + 2; ++ lim = base + wlen + 2; ++ ++ OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen * 2, ++ base * 2, (lim + 1) * 2)); ++ ++ /* Write the header */ ++ err = hndotp_write_word(oh, cc, base, hdr[0]); ++ ++ /* Write the data */ ++ while (wn < lim) { ++ err += hndotp_write_word(oh, cc, wn++, *p++); ++ ++ /* If there has been an error, close this chunk */ ++ if (err != 0) { ++ OTP_MSG(("closing early @ 0x%x\n", wn * 2)); ++ break; ++ } ++ } ++ ++ /* If we wrote the whole chunk, write the crc */ ++ if (wn == lim) { ++ OTP_MSG((" whole chunk written, crc = 0x%x\n", crc)); ++ err += hndotp_write_word(oh, cc, wn++, crc); ++ clen = hdr[1]; ++ } else { ++ /* If there was an error adjust the count to point to ++ * the word after the error so we can start the next ++ * chunk there. ++ */ ++ clen = (wn - base) * 2; ++ OTP_MSG((" partial chunk written, chunk len = 0x%x\n", clen)); ++ } ++ /* And now write the chunk length */ ++ err += hndotp_write_word(oh, cc, base + 1, clen); ++ ++ if (base == 0) { ++ /* Write the signature and boundary if this is the HW region, ++ * but don't report failure if either of these 2 writes fail. ++ */ ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, ++ wn * 2) == 0) ++ gerr += hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF, ++ OTP_SIGNATURE); ++ else ++ gerr++; ++ oi->boundary = wn * 2; ++ oi->signvalid |= OTP_HW_REGION; ++ } ++ ++ if (err != 0) { ++ gerr += err; ++ /* Errors, do it all over again if there is space left */ ++ if ((wlen + 3) <= ((oi->size / 2) + OTP_SWLIM_OFF - wn)) { ++ base = wn; ++ lim = base + wlen + 2; ++ OTP_ERR(("Programming errors, retry @ 0x%x\n", wn * 2)); ++ } else { ++ OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn * 2)); ++ break; ++ } ++ } ++ } while (err != 0); ++ ++ OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n", ++ st_n, st_s, st_n, st_s / st_n, st_hwm, pp_hwm)); ++ ++ if (gerr != 0) ++ OTP_MSG(("programming %s after %d errors\n", (err == 0) ? "succedded" : "failed", ++ gerr)); ++out: ++ /* done */ ++ si_setcoreidx(oi->sih, idx); ++ ++ if (err) ++ return BCME_ERROR; ++ else ++ return 0; ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++static uint16 ++hndotp_otprb16(void *oh, chipcregs_t *cc, uint wn) ++{ ++ uint base, i; ++ uint16 val, bit; ++ ++ base = (wn * 16) + (wn / 4); ++ val = 0; ++ for (i = 0; i < 16; i++) { ++ if ((bit = hndotp_read_bit(oh, cc, base + i)) == 0xffff) ++ break; ++ val = val | (bit << i); ++ } ++ if (i < 16) ++ val = 0xaaaa; ++ return val; ++} ++ ++static int ++hndotp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, i, count, lil; ++ uint16 val; ++ struct bcmstrbuf b; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ if (arg >= 16) ++ arg -= 16; ++ ++ if (arg == 2) { ++ count = 66 * 4; ++ lil = 3; ++ } else { ++ count = (oi->size / 2) + OTP_RC_LIM_OFF; ++ lil = 7; ++ } ++ ++ OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__, arg, size, count)); ++ bcm_binit(&b, buf, size); ++ for (i = 0; i < count; i++) { ++ if ((i & lil) == 0) ++ bcm_bprintf(&b, "0x%04x:", 2 * i); ++ ++ if (arg == 0) ++ val = hndotp_otpr(oh, cc, i); ++ else ++ val = hndotp_otprb16(oi, cc, i); ++ bcm_bprintf(&b, " 0x%04x", val); ++ if ((i & lil) == lil) { ++ if (arg == 2) { ++ bcm_bprintf(&b, " %d\n", ++ hndotp_read_bit(oh, cc, ((i / 4) * 65) + 64) & 1); ++ } else { ++ bcm_bprintf(&b, "\n"); ++ } ++ } ++ } ++ if ((i & lil) != lil) ++ bcm_bprintf(&b, "\n"); ++ ++ OTP_MSG(("%s: returning %d, left %d, wn %d\n", ++ __FUNCTION__, (int)(b.buf - b.origbuf), b.size, i)); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ((int)(b.buf - b.origbuf)); ++} ++#endif ++ ++static otp_fn_t hndotp_fn = { ++ (otp_size_t)hndotp_size, ++ (otp_read_bit_t)hndotp_read_bit, ++ (otp_dump_t)NULL, /* Assigned in otp_init */ ++ (otp_status_t)hndotp_status, ++ ++ (otp_init_t)hndotp_init, ++ (otp_read_region_t)hndotp_read_region, ++ (otp_nvread_t)hndotp_nvread, ++#ifdef BCMNVRAMW ++ (otp_write_region_t)hndotp_write_region, ++ (otp_cis_append_region_t)hndotp_cis_append_region, ++ (otp_lock_t)hndotp_lock, ++ (otp_nvwrite_t)hndotp_nvwrite, ++ (otp_write_word_t)NULL, ++#else /* BCMNVRAMW */ ++ (otp_write_region_t)NULL, ++ (otp_cis_append_region_t)NULL, ++ (otp_lock_t)NULL, ++ (otp_nvwrite_t)NULL, ++ (otp_write_word_t)NULL, ++#endif /* BCMNVRAMW */ ++ (otp_read_word_t)hndotp_read_word, ++#if defined(BCMNVRAMW) ++ (otp_write_bits_t)hndotp_write_bits ++#endif ++}; ++ ++#endif /* BCMHNDOTP */ ++ ++/* ++ * Common Code: Compiled for IPX / HND / AUTO ++ * otp_status() ++ * otp_size() ++ * otp_read_bit() ++ * otp_init() ++ * otp_read_region() ++ * otp_read_word() ++ * otp_nvread() ++ * otp_write_region() ++ * otp_write_word() ++ * otp_cis_append_region() ++ * otp_lock() ++ * otp_nvwrite() ++ * otp_dump() ++ */ ++ ++int ++otp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->status(oh); ++} ++ ++int ++otp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->size(oh); ++} ++ ++uint16 ++otp_read_bit(void *oh, uint offset) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx = si_coreidx(oi->sih); ++ chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ uint16 readBit = (uint16)oi->fn->read_bit(oh, cc, offset); ++ si_setcoreidx(oi->sih, idx); ++ return readBit; ++} ++ ++#if defined(BCMNVRAMW) ++int ++otp_write_bits(void *oh, uint offset, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return oi->fn->write_bits(oh, offset, bits, data); ++} ++#endif ++ ++void * ++BCMNMIATTACHFN(otp_init)(si_t *sih) ++{ ++ otpinfo_t *oi; ++ void *ret = NULL; ++ bool wasup = FALSE; ++ ++ oi = get_otpinfo(); ++ bzero(oi, sizeof(otpinfo_t)); ++ ++ oi->ccrev = sih->ccrev; ++ ++#ifdef BCMIPXOTP ++ if (OTPTYPE_IPX(oi->ccrev)) { ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++ /* Dump function is excluded from ROM */ ++ ipxotp_fn.dump = ipxotp_dump; ++#endif ++ oi->fn = &ipxotp_fn; ++ } ++#endif /* BCMIPXOTP */ ++ ++#ifdef BCMHNDOTP ++ if (OTPTYPE_HND(oi->ccrev)) { ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++ /* Dump function is excluded from ROM */ ++ hndotp_fn.dump = hndotp_dump; ++#endif ++ oi->fn = &hndotp_fn; ++ } ++#endif /* BCMHNDOTP */ ++ ++ if (oi->fn == NULL) { ++ OTP_ERR(("otp_init: unsupported OTP type\n")); ++ return NULL; ++ } ++ ++ oi->sih = sih; ++ oi->osh = si_osh(oi->sih); ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ ret = (oi->fn->init)(sih); ++ ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return ret; ++} ++ ++int ++BCMNMIATTACHFN(otp_read_region)(si_t *sih, int region, uint16 *data, uint *wlen) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ err = (((otpinfo_t*)oh)->fn->read_region)(oh, region, data, wlen); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_read_word(si_t *sih, uint wn, uint16 *data) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ if (((otpinfo_t*)oh)->fn->read_word == NULL) { ++ err = BCME_UNSUPPORTED; ++ goto out; ++ } ++ err = (((otpinfo_t*)oh)->fn->read_word)(oh, wn, data); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_nvread(void *oh, char *data, uint *len) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->nvread(oh, data, len); ++} ++ ++#ifdef BCMNVRAMW ++int ++BCMNMIATTACHFN(otp_write_region)(si_t *sih, int region, uint16 *data, uint wlen) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ err = (((otpinfo_t*)oh)->fn->write_region)(oh, region, data, wlen); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_write_word(si_t *sih, uint wn, uint16 data) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ if (((otpinfo_t*)oh)->fn->write_word == NULL) { ++ err = BCME_UNSUPPORTED; ++ goto out; ++ } ++ err = (((otpinfo_t*)oh)->fn->write_word)(oh, wn, data); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ void *oh = otp_init(sih); ++ ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ return -1; ++ } ++ return (((otpinfo_t*)oh)->fn->cis_append_region)(sih, region, vars, count); ++} ++ ++int ++otp_lock(si_t *sih) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int ret = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ ret = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ ret = BCME_ERROR; ++ goto out; ++ } ++ ++ ret = (((otpinfo_t*)oh)->fn->lock)(oh); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return ret; ++} ++ ++int ++otp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->nvwrite(oh, data, wlen); ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) ++int ++otp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ if (oi->fn->dump == NULL) ++ return BCME_UNSUPPORTED; ++ else ++ return oi->fn->dump(oh, arg, buf, size); ++} ++ ++int ++otp_dumpstats(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ struct bcmstrbuf b; ++ ++ bcm_binit(&b, buf, size); ++ ++ bcm_bprintf(&b, "\nOTP, ccrev 0x%04x\n", oi->ccrev); ++#if defined(BCMIPXOTP) ++ bcm_bprintf(&b, "wsize %d rows %d cols %d\n", oi->wsize, oi->rows, oi->cols); ++ bcm_bprintf(&b, "hwbase %d hwlim %d swbase %d swlim %d fusebits %d\n", ++ oi->hwbase, oi->hwlim, oi->swbase, oi->swlim, oi->fbase, oi->flim, oi->fusebits); ++ bcm_bprintf(&b, "otpgu_base %d status %d\n", oi->otpgu_base, oi->status); ++#endif ++#if defined(BCMHNDOTP) ++ bcm_bprintf(&b, "OLD OTP, size %d hwprot 0x%x signvalid 0x%x boundary %d\n", ++ oi->size, oi->hwprot, oi->signvalid, oi->boundary); ++#endif ++ bcm_bprintf(&b, "\n"); ++ ++ return 200; /* real buf length, pick one to cover above print */ ++} ++ ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c b/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c +new file mode 100755 +index 0000000..df74e4b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch new file mode 100644 index 00000000..db8ff971 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch @@ -0,0 +1,1554 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c +@@ -0,0 +1,1548 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom 53xx RoboSwitch device driver. ++ * ++ * $Id: bcmrobo.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_IPROC_OTP) ++#include "bcm5301x_otp.h" ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++#ifdef BCMDBG ++#define ET_ERROR(args) printf args ++#else /* BCMDBG */ ++#define ET_ERROR(args) ++#endif /* BCMDBG */ ++#define ET_MSG(args) ++ ++#define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \ ++ ((len) == 2) ? *((uint16 *)(var)) : \ ++ *((uint32 *)(var))) ++ ++//#define BRCM_TAG true ++ ++/* Page numbers */ ++#define PAGE_CTRL 0x00 /* Control page */ ++#define PAGE_STATUS 0x01 /* Status page */ ++#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */ ++#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */ ++#define PAGE_GPHYP0 0x10 /* Port0 internal GPHY registers page */ ++#define PAGE_VLAN 0x34 /* VLAN page */ ++ ++/* Control page registers */ ++#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */ ++#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */ ++#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */ ++#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */ ++#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */ ++#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */ ++#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */ ++#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */ ++#define REG_CTRL_IMP 0x08 /* IMP port traffic control register */ ++#define REG_CTRL_MODE 0x0B /* Switch Mode register */ ++#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */ ++#define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */ ++#define REG_CTRL_PPORT 0x24 /* Protected port register */ ++#define REG_CTRL_PHY_PWR 0x4a /* phy power down register */ ++#define REG_CTRL_SRST 0x79 /* Software reset control register */ ++ ++/* Status Page Registers */ ++#define REG_STATUS_LINK 0x00 /* Link Status Summary */ ++#define REG_STATUS_REV 0x50 /* Revision Register */ ++ ++#define REG_MGMT_CFG 0x00 /* Global Management Configuration */ ++#define REG_BRCM_HDR 0x03 /* BRCM Header Control */ ++#define REG_DEVICE_ID 0x30 /* 539x Device id: */ ++ ++/* VLAN page registers */ ++#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */ ++#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */ ++#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */ ++#define REG_VLAN_CTRL5 0x06 /* VLAN Control 5 register */ ++#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */ ++#define REG_VLAN_WRITE 0x08 /* VLAN Write register */ ++#define REG_VLAN_READ 0x0C /* VLAN Read register */ ++#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */ ++#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */ ++#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */ ++#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */ ++#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */ ++#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */ ++#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */ ++#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */ ++#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */ ++#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */ ++ ++/* Port0 internal GPHY registers page */ ++#define PAGE_GPHYP0_DSP_COEF 0x2a /* dsp coefficient */ ++#define PAGE_GPHYP0_DSP_COEF_ADDR 0x2e /* dsp coefficient address */ ++ ++#define VLAN_NUMVLANS 16 /* # of VLANs */ ++ ++ ++/* ARL/VLAN Table Access page registers */ ++#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */ ++#define REG_VTBL_MINDX 0x02 /* MAC Address Index */ ++#define REG_VTBL_VINDX 0x08 /* VID Table Index */ ++#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */ ++#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */ ++#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */ ++#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */ ++#define REG_VTBL_SADDR 0x22 /* ARL Search Address */ ++#define REG_VTBL_SRES 0x24 /* ARL Search Result */ ++#define REG_VTBL_SREXT 0x2c /* ARL Search Result */ ++#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */ ++#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */ ++#define REG_VTBL_PREG 0xFF /* Page Register */ ++#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */ ++#define REG_VTBL_INDX 0x61 /* VLAN table address index register */ ++#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */ ++#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */ ++#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */ ++#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */ ++ ++#define SRAB_MAX_RETRY 1000 ++ ++#if defined(CONFIG_IPROC_OTP) ++void * (*bcm5301x_otp_init_fptr )(void) = NULL; ++int (*bcm5301x_otp_read_dword_fptr)(void *oh, uint wn, u32 *data) = NULL; ++int (*bcm5301x_otp_exit_fptr)(void) = NULL; ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++static int ++srab_request_grant(robo_info_t *robo) ++{ ++ int i, ret = 0; ++ uint32 val32; ++ ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ val32 |= CFG_F_rcareq_MASK; ++ W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); ++ ++ /* Wait for command complete */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ if ((val32 & CFG_F_rcagnt_MASK)) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_request_grant: timeout")); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static void ++srab_release_grant(robo_info_t *robo) ++{ ++ uint32 val32; ++ ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ val32 &= ~CFG_F_rcareq_MASK; ++ W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); ++} ++ ++static int ++srab_interface_reset(robo_info_t *robo) ++{ ++ int i, ret = 0; ++ uint32 val32; ++ ++ /* Wait for switch initialization complete */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ if ((val32 & CFG_F_sw_init_done_MASK)) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_interface_reset: timeout sw_init_done")); ++ ret = -1; ++ } ++ ++ /* Set the SRAU reset bit */ ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, CFG_F_sra_rst_MASK); ++ ++ /* Wait for it to auto-clear */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_rst_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_interface_reset: timeout sra_rst")); ++ ret |= -2; ++ } ++ ++ return ret; ++} ++ ++static int ++srab_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) ++{ ++ uint16 val16; ++ uint32 val32; ++ uint32 val_h = 0, val_l = 0; ++ int i, ret = 0; ++ uint8 *ptr = (uint8 *)val; ++ ++ /* validate value length and buffer address */ ++ ASSERT(len == 1 || len == 6 || len == 8 || ++ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); ++ ++ ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg, ++ VARG(val, len), len)); ++ ++ srab_request_grant(robo); ++ ++ /* Load the value to write */ ++ switch (len) { ++ case 8: ++ val16 = ptr[7]; ++ val16 = ((val16 << 8) | ptr[6]); ++ val_h = val16 << 16; ++ /* FALLTHRU */ ++ ++ case 6: ++ val16 = ptr[5]; ++ val16 = ((val16 << 8) | ptr[4]); ++ val_h |= val16; ++ ++ val16 = ptr[3]; ++ val16 = ((val16 << 8) | ptr[2]); ++ val_l = val16 << 16; ++ val16 = ptr[1]; ++ val16 = ((val16 << 8) | ptr[0]); ++ val_l |= val16; ++ break; ++ ++ case 4: ++ val_l = *(uint32 *)val; ++ break; ++ ++ case 2: ++ val_l = *(uint16 *)val; ++ break; ++ ++ case 1: ++ val_l = *(uint8 *)val; ++ break; ++ } ++ W_REG(si_osh(robo->sih), &robo->srabregs->wd_h, val_h); ++ W_REG(si_osh(robo->sih), &robo->srabregs->wd_l, val_l); ++ ++ /* We don't need this variable */ ++ if (robo->page != page) ++ robo->page = page; ++ ++ /* Issue the write command */ ++ val32 = ((page << CFG_F_sra_page_R) ++ | (reg << CFG_F_sra_offset_R) ++ | CFG_F_sra_gordyn_MASK ++ | CFG_F_sra_write_MASK); ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); ++ ++ /* Wait for command complete */ ++ for (i = SRAB_MAX_RETRY; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_gordyn_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_wreg: timeout")); ++ srab_interface_reset(robo); ++ ret = -1; ++ } ++ ++ srab_release_grant(robo); ++ ++ return ret; ++} ++ ++static int ++srab_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) ++{ ++ uint32 val32; ++ uint32 val_h = 0, val_l = 0; ++ int i, ret = 0; ++ uint8 *ptr = (uint8 *)val; ++ ++ /* validate value length and buffer address */ ++ ASSERT(len == 1 || len == 6 || len == 8 || ++ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); ++ ++ srab_request_grant(robo); ++ ++ /* We don't need this variable */ ++ if (robo->page != page) ++ robo->page = page; ++ ++ /* Assemble read command */ ++ srab_request_grant(robo); ++ ++ val32 = ((page << CFG_F_sra_page_R) ++ | (reg << CFG_F_sra_offset_R) ++ | CFG_F_sra_gordyn_MASK); ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); ++ ++ /* is operation finished? */ ++ for (i = SRAB_MAX_RETRY; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_gordyn_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_read: timeout")); ++ srab_interface_reset(robo); ++ ret = -1; ++ goto err; ++ } ++ ++ /* Didn't time out, read and return the value */ ++ val_h = R_REG(si_osh(robo->sih), &robo->srabregs->rd_h); ++ val_l = R_REG(si_osh(robo->sih), &robo->srabregs->rd_l); ++ ++ switch (len) { ++ case 8: ++ ptr[7] = (val_h >> 24); ++ ptr[6] = ((val_h >> 16) & 0xff); ++ /* FALLTHRU */ ++ ++ case 6: ++ ptr[5] = ((val_h >> 8) & 0xff); ++ ptr[4] = (val_h & 0xff); ++ ptr[3] = (val_l >> 24); ++ ptr[2] = ((val_l >> 16) & 0xff); ++ ptr[1] = ((val_l >> 8) & 0xff); ++ ptr[0] = (val_l & 0xff); ++ break; ++ ++ case 4: ++ *(uint32 *)val = val_l; ++ break; ++ ++ case 2: ++ *(uint16 *)val = (uint16)(val_l & 0xffff); ++ break; ++ ++ case 1: ++ *(uint8 *)val = (uint8)(val_l & 0xff); ++ break; ++ } ++ ++ ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, ++ VARG(val, len), len)); ++ ++err: ++ srab_release_grant(robo); ++ ++ return ret; ++} ++ ++/* SRAB interface functions */ ++static dev_ops_t srab = { ++ NULL, ++ NULL, ++ srab_wreg, ++ srab_rreg, ++ "SRAB" ++}; ++ ++#if defined(CONFIG_MACH_NSP) ++void ++srab_sgmii_set_blk(robo_info_t *robo, uint page, uint blk) ++{ ++ uint16 blkaddr; ++ uint16 destblk = (uint16)blk; ++ ++ /* printf("%s page(0x%x) blk(0x%x)\n", __FUNCTION__, page, blk); */ ++ /* check if need to update blk addr */ ++ robo->ops->read_reg(robo, page, REG_SGMII_BLK_ADDR, &blkaddr, sizeof(blkaddr)); ++ if (blkaddr!=destblk) { ++ /* write block address */ ++ robo->ops->write_reg(robo, page, REG_SGMII_BLK_ADDR, &destblk, sizeof(destblk)); ++ } ++} ++ ++int ++srab_sgmii_rreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val) ++{ ++ uint blk = reg&0xfff0; ++ uint8 off = reg&0x000f; ++ uint16 data; ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* spi offset is only even (multiple of 2) */ ++ off = off*2; ++ ++ /* check block addr */ ++ srab_sgmii_set_blk(robo, page, blk); ++ ++ /* read offset register */ ++ robo->ops->read_reg(robo, page, off, &data, sizeof(data)); ++ //printf("%s page(0x%x) blk(0x%x) offset(0x%x) value(0x%x)\n", __FUNCTION__, page, blk, off, data); ++ *val = data; ++ ++ return 0; ++} ++ ++int ++srab_sgmii_wreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val) ++{ ++ uint blk = reg&0xfff0; ++ uint8 off = reg&0x000f; ++ uint16 data=*val; ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* spi offset is only even (multiple of 2) */ ++ off = off*2; ++ ++ /* check block addr */ ++ srab_sgmii_set_blk(robo, page, blk); ++ ++ /* write offset register */ ++ robo->ops->write_reg(robo, page, off, &data, sizeof(data)); ++ //printf("%s page(0x%x) blk(0x%x) offset(0x%x) value(0x%x)\n", __FUNCTION__, page, blk, off, data); ++ ++ return 0; ++} ++#endif /* defined(CONFIG_MACH_NSP) */ ++ ++/* High level switch configuration functions. */ ++ ++/* Get access to the RoboSwitch */ ++robo_info_t * ++bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr) ++{ ++ robo_info_t *robo; ++ uint32 reset, idx; ++#ifndef _CFE_ ++// const char *et1port, *et1phyaddr; ++ int mdcport = 0, phyaddr = 0; ++#endif /* _CFE_ */ ++ int lan_portenable = 0; ++ ++ /* Allocate and init private state */ ++ if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) { ++ ET_ERROR(("robo_attach: out of memory, malloced %d bytes", ++ MALLOCED(si_osh(sih)))); ++ return NULL; ++ } ++ bzero(robo, sizeof(robo_info_t)); ++ ++ robo->h = h; ++ robo->sih = sih; ++ robo->vars = vars; ++ robo->miird = miird; ++ robo->miiwr = miiwr; ++ robo->page = -1; ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ robo->miird = NULL; ++ robo->miiwr = NULL; ++ robo->srabregs = (srabregs_t *)REG_MAP(SI_NS_CHIPCB_SRAB, SI_CORE_SIZE); ++ } ++ ++ /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when ++ * romboot CFE loads linux over WAN port and Linux enables LAN ports later ++ */ ++ if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ lan_portenable = 1 << lan_portenable; ++ si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); ++ si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); ++ bcm_mdelay(5); ++ } ++ ++ /* Trigger external reset by nvram variable existance */ ++ if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ /* ++ * Reset sequence: RESET low(50ms)->high(20ms) ++ * ++ * We have to perform a full sequence for we don't know how long ++ * it has been from power on till now. ++ */ ++ ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset)); ++ reset = 1 << reset; ++ ++ /* Keep RESET low for 50 ms */ ++ si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY); ++ si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY); ++ bcm_mdelay(50); ++ ++ /* Keep RESET high for at least 20 ms */ ++ si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY); ++ bcm_mdelay(20); ++ } else { ++ /* In case we need it */ ++ idx = si_coreidx(sih); ++ ++ if (si_setcore(sih, ROBO_CORE_ID, 0)) { ++ /* If we have an internal robo core, reset it using si_core_reset */ ++ ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__)); ++ si_core_reset(sih, 0, 0); ++ robo->corerev = si_corerev(sih); ++ } ++ else if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ srab_interface_reset(robo); ++ srab_rreg(robo, PAGE_MMR, REG_VERSION_ID, &robo->corerev, 1); ++ } ++ else { ++ ET_ERROR(("%s: unknown switch\n", __FUNCTION__)); ++ } ++ si_setcoreidx(sih, idx); ++ ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev)); ++ } ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ int rc; ++ ++ rc = srab_rreg(robo, PAGE_MMR, REG_DEVICE_ID, &robo->devid32, sizeof(uint32)); ++ ++ ET_MSG(("%s: devid read %ssuccesfully via srab: 0x%x\n", ++ __FUNCTION__, rc ? "un" : "", robo->devid32)); ++ ++ robo->ops = &srab; ++ if ((rc != 0) || (robo->devid32 == 0)) { ++ ET_ERROR(("%s: error reading devid\n", __FUNCTION__)); ++ MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); ++ return NULL; ++ } ++ ET_MSG(("%s: devid32: 0x%x\n", __FUNCTION__, robo->devid32)); ++ printf("%s: devid32: 0x%x\n", __FUNCTION__, robo->devid32); ++ } ++ ++#ifndef _CFE_ ++ if (!robo->ops) { ++ ET_ERROR(("%s: unknown switch", __FUNCTION__)); ++ goto error; ++ } ++#endif /* _CFE_ */ ++ ++ /* sanity check */ ++ ASSERT(robo->ops); ++ ASSERT(robo->ops->write_reg); ++ ASSERT(robo->ops->read_reg); ++ ASSERT(ROBO_IS_BCM5301X(robo->devid32)); ++ ++#ifndef _CFE_ ++ /* nvram variable switch_mode controls the power save mode on the switch ++ * set the default value in the beginning ++ */ ++ robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual"); ++ robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto"); ++ ++ /* Determining what all phys need to be included in ++ * power save operation ++ */ ++ //et1port = getvar(vars, "et1mdcport"); ++ //if (et1port) ++ // mdcport = bcm_atoi(et1port); ++ ++ //et1phyaddr = getvar(vars, "et1phyaddr"); ++ //if (et1phyaddr) ++ // phyaddr = bcm_atoi(et1phyaddr); ++ ++ if ((mdcport == 0) && (phyaddr == 4)) ++ /* For 5325F switch we need to do only phys 0-3 */ ++ robo->pwrsave_phys = 0xf; ++ else ++ /* By default all 5 phys are put into power save if there is no link */ ++ robo->pwrsave_phys = 0x1f; ++#endif /* _CFE_ */ ++ ++ return robo; ++ ++#ifndef _CFE_ ++error: ++ bcm_robo_detach(robo); ++ return NULL; ++#endif /* _CFE_ */ ++} ++ ++/* Release access to the RoboSwitch */ ++void ++bcm_robo_detach(robo_info_t *robo) ++{ ++ if (robo->srabregs) ++ REG_UNMAP(robo->srabregs); ++ ++ MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); ++} ++ ++/* Enable the device and set it to a known good state */ ++int ++bcm_robo_enable_device(robo_info_t *robo) ++{ ++ int ret = 0; ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return ret; ++} ++ ++/* Port flags */ ++#define FLAG_TAGGED 't' /* output tagged (external ports only) */ ++#define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */ ++#define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */ ++ ++/* port descriptor */ ++typedef struct { ++ uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */ ++ uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */ ++ uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */ ++ uint8 cpu; /* is this cpu port? */ ++} pdesc_t; ++ ++pdesc_t pdesc97[] = { ++ /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */ ++ /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0}, ++ /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0}, ++ /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0}, ++ /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0}, ++ /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0}, ++#ifdef GMAC3 ++ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0}, ++ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0}, ++ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0}, ++#else /* !GMAC3 */ ++ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 1}, ++ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 1}, ++ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 1}, ++#endif /* !GMAC3 */ ++ /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1}, ++}; ++ ++/* Configure the VLANs */ ++int ++bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr) ++{ ++ uint8 val8; ++ uint16 val16; ++ uint32 val32; ++ pdesc_t *pdesc; ++ int pdescsz; ++ uint16 vid; ++ uint8 arl_entry[8] = { 0 }; ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* setup global vlan configuration */ ++ /* VLAN Control 0 Register (Page 0x34, Address 0) */ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ val8 |= ((1 << 7) | /* enable 802.1Q VLAN */ ++ (3 << 5)); /* individual VLAN learning mode */ ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ /* VLAN Control 1 Register (Page 0x34, Address 1) */ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */ ++ (1 << 3)); /* enable RSV multicast V Untagmap */ ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ ++ arl_entry[0] = mac_addr[5]; ++ arl_entry[1] = mac_addr[4]; ++ arl_entry[2] = mac_addr[3]; ++ arl_entry[3] = mac_addr[2]; ++ arl_entry[4] = mac_addr[1]; ++ arl_entry[5] = mac_addr[0]; ++ ++ /* Initialize the MAC Addr Index Register */ ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, ++ arl_entry, ETHER_ADDR_LEN); ++ ++ pdesc = pdesc97; ++ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); ++ ++ /* check if p5 is not CPU port */ ++ if (!robo_is_port5_cpu()) { ++ pdesc[5].cpu = 0; ++ } ++ ++ /* setup each vlan. max. 16 vlans. */ ++ /* force vlan id to be equal to vlan number */ ++ for (vid = 0; vid < VLAN_NUMVLANS; vid ++) { ++ char vlanports[] = "vlanXXXXports"; ++ char port[] = "XXXX", *next; ++ const char *ports, *cur; ++ uint32 untag = 0; ++ uint32 member = 0; ++ int pid, len; ++ int cpuport=0; ++ ++ /* no members if VLAN id is out of limitation */ ++ if (vid > VLAN_MAXVID) ++ goto vlan_setup; ++ ++ /* get vlan member ports from nvram */ ++ sprintf(vlanports, "vlan%dports", vid); ++ ports = getvar(robo->vars, vlanports); ++ ++ ET_MSG(("%s: getvar(%s) port %s \n", ++ __FUNCTION__, vlanports, ports)); ++ /* vid == 0 is invalid?? */ ++ if (vid == 0) { ++ if (ports) ++ ET_ERROR(("VID 0 is set in nvram, Ignoring\n")); ++ continue; ++ } ++ ++ /* disable this vlan if not defined */ ++ if (!ports) ++ goto vlan_setup; ++ ++ /* ++ * setup each port in the vlan. cpu port needs special handing ++ * (with or without output tagging) to support linux/pmon/cfe. ++ */ ++ for (cur = ports; cur; cur = next) { ++ /* tokenize the port list */ ++ while (*cur == ' ') ++ cur ++; ++ next = bcmstrstr(cur, " "); ++ len = next ? next - cur : strlen(cur); ++ if (!len) ++ break; ++ if (len > sizeof(port) - 1) ++ len = sizeof(port) - 1; ++ strncpy(port, cur, len); ++ port[len] = 0; ++ ++ /* make sure port # is within the range */ ++ pid = bcm_atoi(port); ++ if (pid >= pdescsz) { ++ ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out " ++ "of range[0-%d]\n", pid, vid, pdescsz)); ++ continue; ++ } ++ if (pid == 6) { ++ ET_ERROR(("robo_config_vlan: port %d in vlan%dports is not valid\n", pid, vid)); ++ continue; ++ } ++ ++ /* build VLAN registers values */ ++#ifndef _CFE_ ++ if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) || ++ (pdesc[pid].cpu && strchr(port, FLAG_UNTAG))) ++#endif ++ untag |= pdesc[pid].untag; ++ ++ member |= pdesc[pid].member; ++ ++ /* set port tag - applies to untagged ingress frames */ ++ /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */ ++#ifdef _CFE_ ++#define FL FLAG_LAN ++#else ++#define FL FLAG_UNTAG ++#endif /* _CFE_ */ ++ if (!pdesc[pid].cpu || strchr(port, FL)) { ++ val16 = ((0 << 13) | /* priority - always 0 */ ++ vid); /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr, ++ &val16, sizeof(val16)); ++ } ++ if (pdesc[pid].cpu) ++ cpuport=pid; ++ } ++ ++ /* Add static ARL entries */ ++ /* Set the VLAN Id in VLAN ID Index Register */ ++ val8 = vid; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, ++ &val8, sizeof(val8)); ++ ++ /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0 ++ * Register. ++ */ ++ arl_entry[6] = vid; ++ arl_entry[7] = 0x0; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, ++ arl_entry, sizeof(arl_entry)); ++ ++ /* Set the Static bit , Valid bit and Port ID fields in ++ * ARL Table Data Entry 0 Register ++ */ ++ //val16 = 0xc100; //0xc020; ++ val32 = 0x08000 + (1<ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, ++ &val32, sizeof(val32)); ++ ++ /* Clear the ARL_R/W bit and set the START/DONE bit in ++ * the ARL Read/Write Control Register. ++ */ ++ val8 = 0x80; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, ++ &val8, sizeof(val8)); ++ /* Wait for write to complete */ ++ SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, ++ &val8, sizeof(val8)), ((val8 & 0x80) != 0)), ++ 100 /* usec */); ++ ++vlan_setup: ++ /* setup VLAN ID and VLAN memberships */ ++ ++ val32 = (untag | /* untag enable */ ++ member); /* vlan members */ ++ { ++ uint8 vtble, vtbli, vtbla; ++ ++ vtble = REG_VTBL_ENTRY_5395; ++ vtbli = REG_VTBL_INDX_5395; ++ vtbla = REG_VTBL_ACCESS_5395; ++ ++ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32, ++ sizeof(val32)); ++ /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */ ++ val16 = vid; /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, ++ sizeof(val16)); ++ ++ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ ++ val8 = ((1 << 7) | /* start command */ ++ 0); /* write */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, ++ sizeof(val8)); ++ } ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return 0; ++} ++ ++/* Enable switching/forwarding */ ++int ++bcm_robo_enable_switch(robo_info_t *robo) ++{ ++ int i, max_port_ind, ret = 0; ++ uint8 val8; ++ uint16 val16; ++ bool bcm_tag_on=false; ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ char *var; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ uint32_t val32; ++#if defined(CONFIG_IPROC_OTP) ++ void *oh; ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ uint32_t skuid=0; ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ /* check if brcm tag is turned off */ ++ bcm_tag_on=true; ++ var = getvar(NULL, "brcmtag"); ++ if (var) { ++ int tag = bcm_strtoul(var, NULL, 0); ++ if (tag==0) { ++ ET_ERROR(("BRCM TAG disabled\n")); ++ /* if brcm tag == 0 tag disabled */ ++ bcm_tag_on = false; ++ } ++ } ++#elif defined(CONFIG_MACH_NSP) ++ bcm_tag_on=true; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Switch Mode register (Page 0, Address 0x0B) */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ ++ /* Bit 1 enables switching/forwarding */ ++ if (!(val8 & (1 << 1))) { ++ /* Set unmanaged mode */ ++ val8 &= (~(1 << 0)); ++ ++ /* Enable forwarding */ ++ val8 |= (1 << 1); ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ ++ /* Read back */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ if (!(val8 & (1 << 1))) { ++ ET_ERROR(("robo_enable_switch: enabling forwarding failed\n")); ++ ret = -1; ++ } ++ ++ /* No spanning tree for unmanaged mode */ ++ val8 = 0; ++ if (ROBO_IS_BCM5301X(robo->devid32)) ++ max_port_ind = REG_CTRL_PORT7; ++ else ++ max_port_ind = REG_CTRL_PORT4; ++ ++ for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) { ++ if (ROBO_IS_BCM5301X(robo->devid32) && i == REG_CTRL_PORT6) ++ continue; ++ robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); ++ } ++ ++ /* No spanning tree on IMP port too */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ } ++ else { ++ /* Set managed mode */ ++ val8 |= 1; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ } ++ ++ if (ROBO_IS_BCM5301X(robo->devid32)) { ++ /* ++ * Port N GMII Port States Override Register (Page 0x00 , address Offset: 0x0e , 0x58-0x5d and 0x5f ) ++ * SPEED/ DUPLEX_MODE/ LINK_STS ++ */ ++ ++ /* check if p5 is CPU port */ ++ if (robo_is_port5_cpu()) { ++ /* Over ride GMAC0 Port5 status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); ++ } ++ ++ /* Over ride GMAC1 Port7 status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); ++ ++ /* Over ride GMAC2 IMP(Port8) status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: ++ * Page :0x00 ++ * ( Offset: 0xe ) IMP Port States Override Register ++ * [6]: GMII SPEED UP 2G ++ */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) config BRCM tag */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); ++ if (bcm_tag_on) ++ val8 |= 0x01; ++ else ++ val8 &= 0xfe; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) Enable receive all packets */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ val8 |= 0x1c; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) IMP port Enable */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ val8 |= 0x80; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ } ++ ++ if (bcm_tag_on) { ++ /* GMAC2 IMP(Port8) enable ignore crc check */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); ++ val8 |= 0x01; ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ /* make sure external ports are not in protected mode (Page 0, Address 0x24) */ ++ val16 = 0; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PPORT, &val16, sizeof(val16)); ++ ++ ++#if defined(CONFIG_IPROC_OTP) ++ /* check if need to turn off unused ports */ ++ /* Check for Vega chip - get OTP skuid */ ++ bcm5301x_otp_init_fptr = symbol_get(bcm5301x_otp_init); ++ bcm5301x_otp_read_dword_fptr = symbol_get(bcm5301x_otp_read_dword); ++ bcm5301x_otp_exit_fptr = symbol_get(bcm5301x_otp_exit); ++ ++ ++ if ( (bcm5301x_otp_init_fptr != NULL) ++ && ( bcm5301x_otp_read_dword_fptr != NULL) ++ && (bcm5301x_otp_exit_fptr != NULL)) { ++ ++ oh = (*bcm5301x_otp_init_fptr)(); ++ (*bcm5301x_otp_read_dword_fptr)(oh, 0x0f, &skuid); ++ (*bcm5301x_otp_exit_fptr)(); ++ } ++ printf("%s OTP: offset 0x0f = 0x%x\n", __FUNCTION__, skuid); ++#else /* defined(CONFIG_IPROC_OTP) */ ++ printf("%s IPROC OTP is not configured, can not determine skuid\n", __FUNCTION__); ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ printf("%s Northstar Family chip\n", __FUNCTION__); ++ if ( (robo->devid32==DEVID53010 && skuid==OTP_SKU_ID_53014) ++ || (robo->devid32==DEVID53011 && skuid==OTP_SKU_ID_53015) ++ || (robo->devid32==DEVID53012 && skuid==OTP_SKU_ID_53016) ) { ++ /* check for VEGA */ ++ printf("%s Vega chip\n", __FUNCTION__); ++ /* only have ports 0-1, power down phy of ports 2-4 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x1c; /* power down ports 2-4. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ } ++ else if ( robo->devid32 == DEVID53025 ) { ++ /* for nsp, skuid is actually gphy_ext_pwrdown[4-0] bits, ++ mask off other bits */ ++ skuid &= 0x1f; ++ printf("%s Checking powered down port (0x%x)\n", __FUNCTION__, skuid); ++ if (skuid == 0x1c) { ++ printf("%s Powering down ports 2-4\n", __FUNCTION__); ++ /* only have ports 0-1, power down phy of ports 2-4 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x1c; /* power down ports 2-4. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ } else if ((skuid == 0x07) || (skuid == 0x06)) { ++ printf("%s Powering down ports 0-2\n", __FUNCTION__); ++ /* only have ports 3-4, power down phy of ports 1-2 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x6; /* power down ports 1-2. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ /* power down port 0 */ ++ val32 = 0xfff; ++ robo->ops->write_reg(robo, PAGE_GPHYP0, PAGE_GPHYP0_DSP_COEF_ADDR, &val32, sizeof(val32)); ++ val32 = 0x7fff; ++ robo->ops->write_reg(robo, PAGE_GPHYP0, PAGE_GPHYP0_DSP_COEF, &val32, sizeof(val32)); ++ } ++ } ++ } ++ ++#if defined(CONFIG_MACH_NSP) ++ if ( robo_is_port_cfg(PORTCFG_5, PORTCFG_SGMII) ++ || robo_is_port_cfg(PORTCFG_4, PORTCFG_SGMII) ) { ++ /* either port5 or port4 SGMII enabled */ ++ /* enable serdes */ ++ robo_serdes_reset_core(robo, PAGE_P5_SGMII); ++ if (robo_is_port_cfg(PORTCFG_5, PORTCFG_SGMII)) { ++ /* enable port5 sgmii */ ++ robo_serdes_init(robo, PAGE_P5_SGMII); ++ } ++ if (robo_is_port_cfg(PORTCFG_4, PORTCFG_SGMII)) { ++ /* enable port4 sgmii */ ++ robo_serdes_init(robo, PAGE_P4_SGMII); ++ } ++ /* start serdes pll */ ++ robo_serdes_start_pll(robo, PAGE_P5_SGMII); ++ } ++#endif /* defined(CONFIG_MACH_NSP) */ ++ ++ return ret; ++} ++ ++void ++robo_reset_mib(robo_info_t *robo) ++{ ++ uint8 val8; ++ ++ robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ /* set clear mib bit */ ++ val8 |= 0x01; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ /* clear clear mib bit */ ++ val8 &= 0xfe; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++} ++ ++void ++robo_dump_mib(robo_info_t *robo) ++{ ++ uint32 tx32, rx32; ++ int port; ++ ++ for (port=0x20; port<=0x28; port++) { ++ if (port==0x26) ++ continue; ++ robo->ops->read_reg(robo, port, 0x00, &tx32, sizeof(tx32)); ++ robo->ops->read_reg(robo, port, 0x50, &rx32, sizeof(rx32)); ++ printf("port%d: TX Octets: 0x%x; RX Octets: 0x%x\n", port-0x20, tx32, rx32); ++ } ++} ++ ++void ++robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b) ++{ ++ uint32 tx32, txdrp32, txbcst32, txmcst32, txcol32, ucst32, txpause32; ++ uint32 rx32, rxusz32, rxosz32, rxale32, rxfcs32, rxdrp32, rxsachg32, rxfrag32, rxsym32, irec32, orec32, rxdis32; ++ int port; ++ ++ for (port=0x20; port<=0x28; port++) { ++ if (port==0x26) ++ continue; ++ robo->ops->read_reg(robo, port, 0x00, &tx32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x08, &txdrp32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x10, &txbcst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x14, &txmcst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x18, &ucst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x1c, &txcol32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x38, &txpause32, sizeof(uint32)); ++ bcm_bprintf(b, "port%d TX: Octs(%x); Drp(%x) Bcst(%x) Mcst(%x) Ucst(%x) Col(%x) Pause(%x)\n", ++ port-0x20, tx32, txdrp32, txbcst32, txmcst32, ucst32, txcol32, txpause32); ++ robo->ops->read_reg(robo, port, 0x50, &rx32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x58, &rxusz32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x78, &rxosz32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x80, &rxale32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x84, &rxfcs32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x90, &rxdrp32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x94, &ucst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xa0, &rxsachg32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xa4, &rxfrag32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xac, &rxsym32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xb0, &irec32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xb4, &orec32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xc0, &rxdis32, sizeof(uint32)); ++ bcm_bprintf(b, "port%d RX: Octs(%x); USz(%x) OSz(%x) AlgnEr(%x) FcsEr(%x) Drp(%x) Ucst(%x); SacCh(%x); Frag(%x) SymEr(%x) IRngEr(%x) ORngEr(%x) Dis(%x)\n", ++ port-0x20, rx32, rxusz32, rxosz32, rxale32, rxfcs32, rxdrp32, ++ ucst32, rxsachg32, rxfrag32, rxsym32, irec32, orec32, rxdis32); ++ } ++ robo_reset_mib(robo); ++} ++ ++ ++void ++robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b) ++{ ++ uint8 val8; ++ uint16 val16; ++ uint32 val32; ++ pdesc_t *pdesc; ++ int pdescsz; ++ int i; ++ ++ bcm_bprintf(b, "%s:\n", robo->ops->desc); ++ if (robo->miird == NULL && !strcmp(robo->ops->desc, "SPI (GPIO)")) ++ bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n", ++ robo->ss, robo->sck, robo->mosi, robo->miso); ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Dump registers interested */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8); ++ ++ pdesc = pdesc97; ++ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); ++ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8); ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8); ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8)); ++ { ++ uint8 vtble, vtbli, vtbla; ++ ++ vtble = REG_VTBL_ENTRY_5395; ++ vtbli = REG_VTBL_INDX_5395; ++ vtbla = REG_VTBL_ACCESS_5395; ++ ++ for (i = 0; i <= VLAN_MAXVID; i++) { ++ /* VLAN Table Address Index Register (Page 0x05, Address 0x61-0x62/0x81-0x82) */ ++ val16 = i; /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, ++ sizeof(val16)); ++ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ ++ val8 = ((1 << 7) | /* start command */ ++ 1); /* read */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, ++ sizeof(val8)); ++ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ ++ robo->ops->read_reg(robo, PAGE_VTBL, vtble, &val32, ++ sizeof(val32)); ++ bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n", ++ i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff)); ++ } ++ } ++ for (i = 0; i < pdescsz; i++) { ++ robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16)); ++ bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16); ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++} ++ ++#ifndef _CFE_ ++/* ++ * Update the power save configuration for ports that changed link status. ++ */ ++void ++robo_power_save_mode_update(robo_info_t *robo) ++{ ++ uint phy; ++ ++ for (phy = 0; phy < MAX_NO_PHYS; phy++) { ++ if (robo->pwrsave_mode_auto & (1 << phy)) { ++ ET_MSG(("%s: set port %d to auto mode\n", ++ __FUNCTION__, phy)); ++ robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy); ++ } ++ } ++ ++ return; ++} ++ ++static int32 ++robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++} ++ ++static int32 ++robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++ ++} ++ ++/* ++ * Function which periodically checks the power save mode on the switch ++ */ ++int32 ++robo_power_save_toggle(robo_info_t *robo, int32 normal) ++{ ++ int32 phy; ++ uint16 link_status; ++ ++ ++ /* read the link status of all ports */ ++ robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, ++ &link_status, sizeof(uint16)); ++ link_status &= 0x1f; ++ ++ /* Take the phys out of the manual mode first so that link status ++ * can be checked. Once out of that mode check the link status ++ * and if any of the link is up do not put that phy into ++ * manual power save mode ++ */ ++ for (phy = 0; phy < MAX_NO_PHYS; phy++) { ++ /* When auto+manual modes are enabled we toggle between ++ * manual and auto modes. When only manual mode is enabled ++ * we toggle between manual and normal modes. When only ++ * auto mode is enabled there is no need to do anything ++ * here since auto mode is one time config. ++ */ ++ if ((robo->pwrsave_phys & (1 << phy)) && ++ (robo->pwrsave_mode_manual & (1 << phy))) { ++ if (!normal) { ++ /* Take the port out of the manual mode */ ++ robo_power_save_mode_clear_manual(robo, phy); ++ } else { ++ /* If the link is down put it back to manual else ++ * remain in the current state ++ */ ++ if (!(link_status & (1 << phy))) { ++ ET_MSG(("%s: link down, set port %d to man mode\n", ++ __FUNCTION__, phy)); ++ robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy); ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Switch the ports to normal mode. ++ */ ++static int32 ++robo_power_save_mode_normal(robo_info_t *robo, int32 phy) ++{ ++ int32 error = 0; ++ ++ /* If the phy in the power save mode come out of it */ ++ switch (robo->pwrsave_mode_phys[phy]) { ++ case ROBO_PWRSAVE_AUTO_MANUAL: ++ case ROBO_PWRSAVE_AUTO: ++ error = robo_power_save_mode_clear_auto(robo, phy); ++ if ((error == -1) || ++ (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO)) ++ break; ++ ++ case ROBO_PWRSAVE_MANUAL: ++ error = robo_power_save_mode_clear_manual(robo, phy); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return error; ++} ++ ++/* ++ * Switch all the inactive ports to auto power down mode. ++ */ ++static int32 ++robo_power_save_mode_auto(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++} ++ ++/* ++ * Switch all the inactive ports to manual power down mode. ++ */ ++static int32 ++robo_power_save_mode_manual(robo_info_t *robo, int32 phy) ++{ ++ uint16 val16; ++ ++ /* For both 5325 and 53115 the link status register is the same */ ++ robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, ++ &val16, sizeof(val16)); ++ if (val16 & (0x1 << phy)) ++ return 0; ++ ++ return -1; ++} ++ ++/* ++ * Set power save modes on the robo switch ++ */ ++int32 ++robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy) ++{ ++ int32 error = -1; ++ ++ if (phy > MAX_NO_PHYS) { ++ ET_ERROR(("Passed parameter phy is out of range\n")); ++ return -1; ++ } ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ switch (mode) { ++ case ROBO_PWRSAVE_NORMAL: ++ /* If the phy in the power save mode come out of it */ ++ error = robo_power_save_mode_normal(robo, phy); ++ break; ++ ++ case ROBO_PWRSAVE_AUTO_MANUAL: ++ /* If the switch supports auto and manual power down ++ * enable both of them ++ */ ++ case ROBO_PWRSAVE_AUTO: ++ error = robo_power_save_mode_auto(robo, phy); ++ if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO)) ++ break; ++ ++ case ROBO_PWRSAVE_MANUAL: ++ error = robo_power_save_mode_manual(robo, phy); ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return error; ++} ++ ++/* ++ * Get the current power save mode of the switch ports. ++ */ ++int32 ++robo_power_save_mode_get(robo_info_t *robo, int32 phy) ++{ ++ ASSERT(robo); ++ ++ if (phy >= MAX_NO_PHYS) ++ return -1; ++ ++ return robo->pwrsave_mode_phys[phy]; ++} ++ ++/* ++ * Configure the power save mode for the switch ports. ++ */ ++int32 ++robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy) ++{ ++ int32 error; ++ ++ ASSERT(robo); ++ ++ if (phy >= MAX_NO_PHYS) ++ return -1; ++ ++ error = robo_power_save_mode(robo, mode, phy); ++ ++ if (error) ++ return error; ++ ++ if (mode == ROBO_PWRSAVE_NORMAL) { ++ robo->pwrsave_mode_manual &= ~(1 << phy); ++ robo->pwrsave_mode_auto &= ~(1 << phy); ++ } else if (mode == ROBO_PWRSAVE_AUTO) { ++ robo->pwrsave_mode_auto |= (1 << phy); ++ robo->pwrsave_mode_manual &= ~(1 << phy); ++ robo_power_save_mode_clear_manual(robo, phy); ++ } else if (mode == ROBO_PWRSAVE_MANUAL) { ++ robo->pwrsave_mode_manual |= (1 << phy); ++ robo->pwrsave_mode_auto &= ~(1 << phy); ++ robo_power_save_mode_clear_auto(robo, phy); ++ } else { ++ robo->pwrsave_mode_auto |= (1 << phy); ++ robo->pwrsave_mode_manual |= (1 << phy); ++ } ++ ++ return 0; ++} ++#endif /* _CFE_ */ ++ ++void ++robo_watchdog(robo_info_t *robo) ++{ ++ return; ++} ++ ++int ++robo_write_reg(void *rih, unsigned char page, unsigned char reg, void *val, int len) ++{ ++ robo_info_t *robo = (robo_info_t*)rih; ++ return robo->ops->write_reg(robo, (uint8)page, (uint8)reg, val, len); ++} ++ ++ ++int ++robo_read_reg(void *rih, unsigned char page, unsigned char reg, void *val, int len) ++{ ++ robo_info_t *robo = (robo_info_t*)rih; ++ return robo->ops->read_reg(robo, (uint8)page, (uint8)reg, val, len); ++} ++ ++ ++int ++robo_is_port5_cpu(void) ++{ ++ char name[16]; ++ char *var; ++ ++ /* get port5 config */ ++ sprintf(name, PORTCFG, PORTCFG_5); ++ var = getvar(NULL, name); ++ ++ /* check if not CPU port */ ++ if (var == NULL) { ++ /* if no port 5 config then CPU port */ ++ return 1; ++ } ++ /* now check if valid CONFIGURATION */ ++ if (strcmp(var, PORTCFG_RGMII)==0) { ++ printf("%s port5 is configured as RGMII port\n", __FUNCTION__); ++ return 0; ++ } ++ if (strcmp(var, PORTCFG_SGMII)==0) { ++ printf("%s port5 is configured as SGMII port\n", __FUNCTION__); ++ return 0; ++ } ++ if (strcmp(var, PORTCFG_GPHY)==0) { ++ printf("%s port5 is configured as GPHY port\n", __FUNCTION__); ++ return 0; ++ } ++ ++ printf("%s port5 has UNKNOWN configuration: %s\n", __FUNCTION__, var); ++ /* must be CPU port */ ++ return 1; ++} ++ ++ ++int ++robo_is_port_cfg(int port, char *cfg) ++{ ++ char name[16]; ++ char *var; ++ ++ /* get port5 config */ ++ sprintf(name, PORTCFG, port); ++ var = getvar(NULL, name); ++ if (var == NULL) { ++ /* if no port config then normal port config */ ++ return 0; ++ } ++ ++ if (strcmp(var, cfg)==0) { ++ /* the port is the configuration we are looing for */ ++ return 1; ++ } ++ ++ /* not config we are looking for */ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c b/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c +new file mode 100755 +index 0000000..be26681 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch new file mode 100644 index 00000000..2469a414 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch @@ -0,0 +1,5115 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c +@@ -0,0 +1,5109 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Routines to access SPROM and to parse SROM/CIS variables. ++ * ++ * $Id: bcmsrom.c 323253 2012-03-23 17:21:10Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef BCMSPI ++#include ++#endif ++ ++#include ++#include ++ ++#if defined(BCMUSBDEV) ++#include ++#include ++#include ++#endif ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++#include ++#endif ++#include /* for sprom content groking */ ++ ++ ++#if defined(BCMDBG_ERR) || defined(WLTEST) ++#define BS_ERROR(args) printf args ++#else ++#define BS_ERROR(args) ++#endif ++ ++#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \ ++ (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \ ++ ((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \ ++ ((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET)) ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ ++#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ ++#endif ++ ++typedef struct varbuf { ++ char *base; /* pointer to buffer base */ ++ char *buf; /* pointer to current position */ ++ unsigned int size; /* current (residual) size in bytes */ ++} varbuf_t; ++extern char *_vars; ++extern uint _varsz; ++ ++#define SROM_CIS_SINGLE 1 ++ ++ ++static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *count); ++static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b); ++static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count); ++static int initvars_cis_pcmcia(si_t *sih, osl_t *osh, char **vars, uint *count); ++#if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) ++static int initvars_flash_si(si_t *sih, char **vars, uint *count); ++#endif ++#ifdef BCMSPI ++static int initvars_cis_spi(osl_t *osh, char **vars, uint *count); ++#endif /* BCMSPI */ ++static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd); ++static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data); ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data); ++#endif ++static int sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, ++ uint nwords, bool check_crc); ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz); ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, ++ uint16 data); ++ ++static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count); ++static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len); ++ ++#if defined(BCMUSBDEV) ++static int get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz, bool check_crc); ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++static int set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz); ++#endif ++#endif ++ ++#if defined(BCMUSBDEV) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++/* default to bcm94323 P200, other boards should have OTP programmed */ ++static char BCMATTACHDATA(defaultsromvars_4322usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:d3:04:73\0" ++ "sromrev=8\0" ++ "devid=0x432b\0" ++ "boardrev=0x1200\0" ++ "boardflags=0xa00\0" ++ "boardflags2=0x602\0" ++ "boardtype=0x04a8\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x0\0" ++ "pdetrange2g=0x0\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x2\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x0\0" ++ "pdetrange5g=0x0\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x2\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "pa2gw0a0=0xFEA8\0" ++ "pa2gw1a0=0x16CD\0" ++ "pa2gw2a0=0xFAA5\0" ++ "maxp5ga0=0x40\0" ++ "itt5ga0=0x3e\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x40\0" ++ "pa5gw0a0=0xFEB2\0" ++ "pa5gw1a0=0x1471\0" ++ "pa5gw2a0=0xFB1F\0" ++ "pa5glw0a0=0xFEA2\0" ++ "pa5glw1a0=0x149A\0" ++ "pa5glw2a0=0xFAFC\0" ++ "pa5ghw0a0=0xFEC6\0" ++ "pa5ghw1a0=0x13DD\0" ++ "pa5ghw2a0=0xFB48\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "pa2gw0a1=0xFEA3\0" ++ "pa2gw1a1=0x1687\0" ++ "pa2gw2a1=0xFAAA\0" ++ "maxp5ga1=0x40\0" ++ "itt5ga1=0x3e\0" ++ "maxp5gha1=0x3c\0" ++ "maxp5gla1=0x40\0" ++ "pa5gw0a1=0xFEBC\0" ++ "pa5gw1a1=0x14F9\0" ++ "pa5gw2a1=0xFB05\0" ++ "pa5glw0a1=0xFEBE\0" ++ "pa5glw1a1=0x1478\0" ++ "pa5glw2a1=0xFB1A\0" ++ "pa5ghw0a1=0xFEE1\0" ++ "pa5ghw1a1=0x14FD\0" ++ "pa5ghw2a1=0xFB38\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0x2\0" ++ "ledbh2=0x3\0" ++ "ledbh3=0xff\0" ++ "leddc=0xa0a0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43234usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:03:21:23\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x2\0" ++ "aa5g=0x2\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "txchain=0x2\0" ++ "rxchain=0x2\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4346\0" ++ "boardrev=0x1403\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x2000\0" ++ "boardtype=0x0521\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x4444\0" ++ "mcs2gpo5=0x4444\0" ++ "mcs2gpo6=0x4444\0" ++ "mcs2gpo7=0x4444\0" ++ "mcs5gpo4=0x2222\0" ++ "mcs5gpo5=0x2222\0" ++ "mcs5gpo6=0x2222\0" ++ "mcs5gpo7=0x2222\0" ++ "mcs5glpo4=0x2222\0" ++ "mcs5glpo5=0x2222\0" ++ "mcs5glpo6=0x2222\0" ++ "mcs5glpo7=0x2222\0" ++ "mcs5ghpo4=0x2222\0" ++ "mcs5ghpo5=0x2222\0" ++ "mcs5ghpo6=0x2222\0" ++ "mcs5ghpo7=0x2222\0" ++ "maxp2ga0=0x42\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xFF21\0" ++ "pa2gw1a0=0x13B7\0" ++ "pa2gw2a0=0xFB44\0" ++ "maxp5ga0=0x3E\0" ++ "maxp5gha0=0x3a\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xFEB2\0" ++ "pa5gw1a0=0x1570\0" ++ "pa5gw2a0=0xFAD6\0" ++ "pa5glw0a0=0xFE64\0" ++ "pa5glw1a0=0x13F7\0" ++ "pa5glw2a0=0xFAF6\0" ++ "pa5ghw0a0=0xFEAB\0" ++ "pa5ghw1a0=0x15BB\0" ++ "pa5ghw2a0=0xFAC6\0" ++ "maxp2ga1=0x42\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xFF17\0" ++ "pa2gw1a1=0x13C4\0" ++ "pa2gw2a1=0xFB3C\0" ++ "maxp5ga1=0x3E\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xFE6F\0" ++ "pa5gw1a1=0x13CC\0" ++ "pa5gw2a1=0xFAF8\0" ++ "pa5glw0a1=0xFE87\0" ++ "pa5glw1a1=0x14BE\0" ++ "pa5glw2a1=0xFAD6\0" ++ "pa5ghw0a1=0xFE68\0" ++ "pa5ghw1a1=0x13E9\0" ++ "pa5ghw2a1=0xFAF6\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43235usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:05:30:01\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4347\0" ++ "boardrev=0x1113\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x0\0" ++ "boardtype=0x0571\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x2222\0" ++ "mcs2gpo5=0x2222\0" ++ "mcs2gpo6=0x2222\0" ++ "mcs2gpo7=0x4444\0" ++ "maxp2ga0=0x42\0" ++ "itt2ga0=0x20\0" ++ "pa2gw0a0=0xFF00\0" ++ "pa2gw1a0=0x143C\0" ++ "pa2gw2a0=0xFB27\0" ++ "maxp2ga1=0x42\0" ++ "itt2ga1=0x20\0" ++ "pa2gw0a1=0xFF22\0" ++ "pa2gw1a1=0x142E\0" ++ "pa2gw2a1=0xFB45\0" ++ "tempthresh=120\0" ++ "temps_period=5\0" ++ "temp_hysteresis=5\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43236usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:03:21:23\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4346\0" ++ "boardrev=0x1532\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x2000\0" ++ "boardtype=0x0521\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x33333333\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x3333\0" ++ "mcs2gpo1=0x3333\0" ++ "mcs2gpo2=0x3333\0" ++ "mcs2gpo3=0x3333\0" ++ "mcs2gpo4=0x5555\0" ++ "mcs2gpo5=0x5555\0" ++ "mcs2gpo6=0x5555\0" ++ "mcs2gpo7=0x5555\0" ++ "mcs5gpo4=0x2222\0" ++ "mcs5gpo5=0x2222\0" ++ "mcs5gpo6=0x2222\0" ++ "mcs5gpo7=0x2222\0" ++ "mcs5glpo4=0x2222\0" ++ "mcs5glpo5=0x2222\0" ++ "mcs5glpo6=0x2222\0" ++ "mcs5glpo7=0x2222\0" ++ "mcs5ghpo4=0x2222\0" ++ "mcs5ghpo5=0x2222\0" ++ "mcs5ghpo6=0x2222\0" ++ "mcs5ghpo7=0x2222\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xFFD8\0" ++ "pa2gw1a0=0x171C\0" ++ "pa2gw2a0=0xFB14\0" ++ "maxp5ga0=0x3e\0" ++ "maxp5gha0=0x3a\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xFE88\0" ++ "pa5gw1a0=0x141C\0" ++ "pa5gw2a0=0xFB17\0" ++ "pa5glw0a0=0xFE8C\0" ++ "pa5glw1a0=0x1493\0" ++ "pa5glw2a0=0xFAFC\0" ++ "pa5ghw0a0=0xFE86\0" ++ "pa5ghw1a0=0x13CC\0" ++ "pa5ghw2a0=0xFB20\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0x0020\0" ++ "pa2gw1a1=0x1791\0" ++ "pa2gw2a1=0xFB5F\0" ++ "maxp5ga1=0x3e\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xFE7E\0" ++ "pa5gw1a1=0x1399\0" ++ "pa5gw2a1=0xFB27\0" ++ "pa5glw0a1=0xFE82\0" ++ "pa5glw1a1=0x13F3\0" ++ "pa5glw2a1=0xFB14\0" ++ "pa5ghw0a1=0xFE96\0" ++ "pa5ghw1a1=0x13BF\0" ++ "pa5ghw2a1=0xFB30\0" ++ "tempthresh=120\0" ++ "temps_period=5\0" ++ "temp_hysteresis=5\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319usb)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x4e7\0" ++ "boardrev=0x1508\0" ++ "boardflags=0x200\0" ++ "xtalfreq=30000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=255\0" ++ "opo=0\0" ++ "pa0b0=5756\0" ++ "pa0b1=64121\0" ++ "pa0b2=65153\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=76\0" ++ "rssismf2g=0xa\0" ++ "rssismc2g=0xb\0" ++ "rssisav2g=0x3\0" ++ "bxa2g=0\0" ++ "tri2g=78\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x44441111\0" ++ "mcs2gpo0=0xaaaa\0" ++ "mcs2gpo1=0xaaaa\0" ++ "boardnum=1\0" ++ "macaddr=00:90:4c:16:${maclo}\0" ++ "otpimagesize=182\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4360usb)[] = ++ "sromrev=11\0" ++ "boardtype=0x623\0" ++ "venid=0x14e4\0" ++ "boardvendor=0x14e4\0" ++ "devid=0x43a0\0" ++ "boardrev=0x1101\0" ++ "boardflags=0x10001000\0" ++ "boardflags2=0x0\0" ++ "boardflags3=0x0\0" ++ "macaddr=00:90:4c:0e:60:01\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "agbg0=0x2\0" ++ "agbg1=0x2\0" ++ "agbg2=0xff\0" ++ "aga0=0x2\0" ++ "aga1=0x2\0" ++ "aga2=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "tssiposslope2g=1\0" ++ "epagain2g=0\0" ++ "pdgain2g=2\0" ++ "tworangetssi2g=0\0" ++ "papdcap2g=0\0" ++ "femctrl=1\0" ++ "tssiposslope5g=1\0" ++ "epagain5g=0\0" ++ "pdgain5g=2\0" ++ "tworangetssi5g=0\0" ++ "papdcap5g=0\0" ++ "gainctrlsph=0\0" ++ "tempthresh=0xff\0" ++ "tempoffset=0xff\0" ++ "rawtempsense=0x1ff\0" ++ "measpower=0x7f\0" ++ "tempsense_slope=0xff\0" ++ "tempcorrx=0x3f\0" ++ "tempsense_option=0x3\0" ++ "phycal_tempdelta=255\0" ++ "temps_period=15\0" ++ "temps_hysteresis=15\0" ++ "measpower1=0x7f\0" ++ "subband5gver=0x4\0" ++ "pcieingress_war=15\0" ++ "sar2g=18\0" ++ "sar5g=15\0" ++ "noiselvl2ga0=31\0" ++ "noiselvl2ga1=31\0" ++ "noiselvl2ga2=31\0" ++ "noiselvl5gla0=31\0" ++ "noiselvl5gla1=31\0" ++ "noiselvl5gla2=31\0" ++ "noiselvl5gma0=31\0" ++ "noiselvl5gma1=31\0" ++ "noiselvl5gma2=31\0" ++ "noiselvl5gha0=31\0" ++ "noiselvl5gha1=31\0" ++ "noiselvl5gha2=31\0" ++ "noiselvl5gua0=31\0" ++ "noiselvl5gua1=31\0" ++ "noiselvl5gua2=31\0" ++ "rxgainerr2g=0xffff\0" ++ "rxgainerr5g=0xffff,0xffff,0xffff,0xffff\0" ++ "maxp2ga0=76\0" ++ "pa2ga0=0xfe72,0x14c0,0xfac7\0" ++ "rxgains2gelnagaina0=4\0" ++ "rxgains2gtrisoa0=10\0" ++ "rxgains2gtrelnabypa0=1\0" ++ "rxgains5gelnagaina0=4\0" ++ "rxgains5gtrisoa0=11\0" ++ "rxgains5gtrelnabypa0=1\0" ++ "maxp5ga0=72,72,76,76\0" ++"pa5ga0=0xfe75,0x14b5,0xfad4,0xfe97,0x121a,0xfb6e,0xfe7f,0x149d,0xfad0,0xfe7c,0x1431,0xfae6\0" ++ "maxp2ga1=76\0" ++ "pa2ga1=0xfe80,0x1472,0xfabc\0" ++ "rxgains2gelnagaina1=4\0" ++ "rxgains2gtrisoa1=10\0" ++ "rxgains2gtrelnabypa1=1\0" ++ "rxgains5gelnagaina1=4\0" ++ "rxgains5gtrisoa1=11\0" ++ "rxgains5gtrelnabypa1=1\0" ++ "maxp5ga1=72,72,76,76\0" ++"pa5ga1=0xfe72,0x155e,0xfa96,0xfea1,0x125d,0xfb55,0xfe77,0x1596,0xfa8e,0xfe78,0x15e1,0xfa7a\0" ++ "END\0"; ++ ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++#endif /* BCMUSBDEV */ ++ ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++/* Also used by wl_readconfigdata for vars download */ ++char BCMATTACHDATA(mfgsromvars)[VARS_MAX]; ++int BCMATTACHDATA(defvarslen) = 0; ++#endif ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++static char BCMATTACHDATA(defaultsromvars_4331)[] = ++ "sromrev=9\0" ++ "boardrev=0x1104\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x0\0" ++ "boardtype=0x524\0" ++ "boardvendor=0x14e4\0" ++ "boardnum=0x2064\0" ++ "macaddr=00:90:4c:1a:20:64\0" ++ "ccode=0x0\0" ++ "regrev=0x0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0xffff\0" ++ "opo=0x0\0" ++ "aa2g=0x7\0" ++ "aa5g=0x7\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "pa0b0=0xfe7f\0" ++ "pa0b1=0x15d9\0" ++ "pa0b2=0xfac6\0" ++ "pa0itssit=0x20\0" ++ "pa0maxpwr=0x48\0" ++ "pa1b0=0xfe89\0" ++ "pa1b1=0x14b1\0" ++ "pa1b2=0xfada\0" ++ "pa1lob0=0xffff\0" ++ "pa1lob1=0xffff\0" ++ "pa1lob2=0xffff\0" ++ "pa1hib0=0xfe8f\0" ++ "pa1hib1=0x13df\0" ++ "pa1hib2=0xfafa\0" ++ "pa1itssit=0x3e\0" ++ "pa1maxpwr=0x3c\0" ++ "pa1lomaxpwr=0x3c\0" ++ "pa1himaxpwr=0x3c\0" ++ "bxa2g=0x3\0" ++ "rssisav2g=0x7\0" ++ "rssismc2g=0xf\0" ++ "rssismf2g=0xf\0" ++ "bxa5g=0x3\0" ++ "rssisav5g=0x7\0" ++ "rssismc5g=0xf\0" ++ "rssismf5g=0xf\0" ++ "tri2g=0xff\0" ++ "tri5g=0xff\0" ++ "tri5gl=0xff\0" ++ "tri5gh=0xff\0" ++ "rxpo2g=0xff\0" ++ "rxpo5g=0xff\0" ++ "txchain=0x7\0" ++ "rxchain=0x7\0" ++ "antswitch=0x0\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x4\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "elna2g=0xff\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x4\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "elna5g=0xff\0" ++ "cckbw202gpo=0x0\0" ++ "cckbw20ul2gpo=0x0\0" ++ "legofdmbw202gpo=0x0\0" ++ "legofdmbw20ul2gpo=0x0\0" ++ "legofdmbw205glpo=0x0\0" ++ "legofdmbw20ul5glpo=0x0\0" ++ "legofdmbw205gmpo=0x0\0" ++ "legofdmbw20ul5gmpo=0x0\0" ++ "legofdmbw205ghpo=0x0\0" ++ "legofdmbw20ul5ghpo=0x0\0" ++ "mcsbw202gpo=0x0\0" ++ "mcsbw20ul2gpo=0x0\0" ++ "mcsbw402gpo=0x0\0" ++ "mcsbw205glpo=0x0\0" ++ "mcsbw20ul5glpo=0x0\0" ++ "mcsbw405glpo=0x0\0" ++ "mcsbw205gmpo=0x0\0" ++ "mcsbw20ul5gmpo=0x0\0" ++ "mcsbw405gmpo=0x0\0" ++ "mcsbw205ghpo=0x0\0" ++ "mcsbw20ul5ghpo=0x0\0" ++ "mcsbw405ghpo=0x0\0" ++ "mcs32po=0x0\0" ++ "legofdm40duppo=0x0\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xfe7f\0" ++ "pa2gw1a0=0x15d9\0" ++ "pa2gw2a0=0xfac6\0" ++ "maxp5ga0=0x3c\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xfe89\0" ++ "pa5gw1a0=0x14b1\0" ++ "pa5gw2a0=0xfada\0" ++ "pa5glw0a0=0xffff\0" ++ "pa5glw1a0=0xffff\0" ++ "pa5glw2a0=0xffff\0" ++ "pa5ghw0a0=0xfe8f\0" ++ "pa5ghw1a0=0x13df\0" ++ "pa5ghw2a0=0xfafa\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xfe54\0" ++ "pa2gw1a1=0x1563\0" ++ "pa2gw2a1=0xfa7f\0" ++ "maxp5ga1=0x3c\0" ++ "maxp5gha1=0x3c\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xfe53\0" ++ "pa5gw1a1=0x14fe\0" ++ "pa5gw2a1=0xfa94\0" ++ "pa5glw0a1=0xffff\0" ++ "pa5glw1a1=0xffff\0" ++ "pa5glw2a1=0xffff\0" ++ "pa5ghw0a1=0xfe6e\0" ++ "pa5ghw1a1=0x1457\0" ++ "pa5ghw2a1=0xfab9\0" ++ "END\0"; ++#endif ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++static char BCMATTACHDATA(defaultsromvars_wltest)[] = ++ "macaddr=00:90:4c:f8:00:01\0" ++ "et0macaddr=00:11:22:33:44:52\0" ++ "et0phyaddr=30\0" ++ "et0mdcport=0\0" ++ "gpio2=robo_reset\0" ++ "boardvendor=0x14e4\0" ++ "boardflags=0x210\0" ++ "boardflags2=0\0" ++ "boardtype=0x04c3\0" ++ "boardrev=0x1100\0" ++ "sromrev=8\0" ++ "devid=0x432c\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "ledbh0=255\0" ++ "ledbh1=255\0" ++ "ledbh2=255\0" ++ "ledbh3=255\0" ++ "leddc=0xffff\0" ++ "aa2g=3\0" ++ "ag0=2\0" ++ "ag1=2\0" ++ "aa5g=3\0" ++ "aa0=2\0" ++ "aa1=2\0" ++ "txchain=3\0" ++ "rxchain=3\0" ++ "antswitch=0\0" ++ "itt2ga0=0x20\0" ++ "maxp2ga0=0x48\0" ++ "pa2gw0a0=0xfe9e\0" ++ "pa2gw1a0=0x15d5\0" ++ "pa2gw2a0=0xfae9\0" ++ "itt2ga1=0x20\0" ++ "maxp2ga1=0x48\0" ++ "pa2gw0a1=0xfeb3\0" ++ "pa2gw1a1=0x15c9\0" ++ "pa2gw2a1=0xfaf7\0" ++ "tssipos2g=1\0" ++ "extpagain2g=0\0" ++ "pdetrange2g=0\0" ++ "triso2g=3\0" ++ "antswctl2g=0\0" ++ "tssipos5g=1\0" ++ "extpagain5g=0\0" ++ "pdetrange5g=0\0" ++ "triso5g=3\0" ++ "antswctl5g=0\0" ++ "cck2gpo=0\0" ++ "ofdm2gpo=0\0" ++ "mcs2gpo0=0\0" ++ "mcs2gpo1=0\0" ++ "mcs2gpo2=0\0" ++ "mcs2gpo3=0\0" ++ "mcs2gpo4=0\0" ++ "mcs2gpo5=0\0" ++ "mcs2gpo6=0\0" ++ "mcs2gpo7=0\0" ++ "cddpo=0\0" ++ "stbcpo=0\0" ++ "bw40po=4\0" ++ "bwduppo=0\0" ++ "END\0"; ++#endif ++ ++static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */ ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) || (defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)) ++/* It must end with pattern of "END" */ ++static uint ++BCMATTACHFN(srom_vars_len)(char *vars) ++{ ++ uint pos = 0; ++ uint len; ++ char *s; ++ ++ for (s = vars; s && *s;) { ++ ++ if (strcmp(s, "END") == 0) ++ break; ++ ++ len = strlen(s); ++ s += strlen(s) + 1; ++ pos += len + 1; ++ /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */ ++ if (pos > 4000) { ++ return 0; ++ } ++ } ++ ++ return pos + 4; /* include the "END\0" */ ++} ++#endif ++ ++/* Initialization of varbuf structure */ ++static void ++BCMATTACHFN(varbuf_init)(varbuf_t *b, char *buf, uint size) ++{ ++ b->size = size; ++ b->base = b->buf = buf; ++} ++ ++/* append a null terminated var=value string */ ++static int ++BCMATTACHFN(varbuf_append)(varbuf_t *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ size_t len; ++ char *s; ++ ++ if (b->size < 2) ++ return 0; ++ ++ va_start(ap, fmt); ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ va_end(ap); ++ ++ /* C99 snprintf behavior returns r >= size on overflow, ++ * others return -1 on overflow. ++ * All return -1 on format error. ++ * We need to leave room for 2 null terminations, one for the current var ++ * string, and one for final null of the var table. So check that the ++ * strlen written, r, leaves room for 2 chars. ++ */ ++ if ((r == -1) || (r > (int)(b->size - 2))) { ++ b->size = 0; ++ return 0; ++ } ++ ++ /* Remove any earlier occurrence of the same variable */ ++ if ((s = strchr(b->buf, '=')) != NULL) { ++ len = (size_t)(s - b->buf); ++ for (s = b->base; s < b->buf;) { ++ if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') { ++ len = strlen(s) + 1; ++ memmove(s, (s + len), ((b->buf + r + 1) - (s + len))); ++ b->buf -= len; ++ b->size += (unsigned int)len; ++ break; ++ } ++ ++ while (*s++) ++ ; ++ } ++ } ++ ++ /* skip over this string's null termination */ ++ r++; ++ b->size -= r; ++ b->buf += r; ++ ++ return r; ++} ++ ++/* ++ * Initialize local vars from the right source for this platform. ++ * Return 0 on success, nonzero on error. ++ */ ++int ++BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ char **vars, uint *count) ++{ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ if (vars == NULL || count == NULL) ++ return (0); ++ ++ *vars = NULL; ++ *count = 0; ++ ++ switch (BUSTYPE(bustype)) { ++ case SI_BUS: ++ case JTAG_BUS: ++ return initvars_srom_si(sih, osh, curmap, vars, count); ++ ++ case PCI_BUS: ++ ASSERT(curmap != NULL); ++ if (curmap == NULL) ++ return (-1); ++ ++ return initvars_srom_pci(sih, curmap, vars, count); ++ ++ case PCMCIA_BUS: ++ return initvars_cis_pcmcia(sih, osh, vars, count); ++ ++ ++#ifdef BCMSPI ++ case SPI_BUS: ++ return initvars_cis_spi(osh, vars, count); ++#endif /* BCMSPI */ ++ ++ default: ++ ASSERT(0); ++ } ++ return (-1); ++} ++ ++/* support only 16-bit word read from srom */ ++int ++srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf, bool check_crc) ++{ ++ uint i, off, nw; ++ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ ++ /* check input - 16-bit access only */ ++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX) ++ return 1; ++ ++ off = byteoff / 2; ++ nw = nbytes / 2; ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ if (!curmap) ++ return 1; ++ ++ if (si_is_sprom_available(sih)) { ++ uint16 *srom; ++ ++ srom = (uint16 *)SROM_OFFSET(sih); ++ if (srom == NULL) ++ return 1; ++ ++ if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc)) ++ return 1; ++ } ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++ else { ++ if (otp_read_pci(osh, sih, buf, SROM_MAX)) ++ return 1; ++ } ++#endif ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ for (i = 0; i < nw; i++) { ++ if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16 *)(buf + i))) ++ return 1; ++ } ++#ifdef BCMSPI ++ } else if (BUSTYPE(bustype) == SPI_BUS) { ++ if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0) ++ return 1; ++#endif /* BCMSPI */ ++ } else if (BUSTYPE(bustype) == SI_BUS) { ++#if defined(BCMUSBDEV) ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint origidx; ++ void *regs; ++ int rc; ++ bool wasup; ++ ++ /* Don't bother if we can't talk to SPROM */ ++ if (!si_is_sprom_available(sih)) ++ return 1; ++ ++ origidx = si_coreidx(sih); ++ regs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!regs) ++ regs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(regs != NULL); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ rc = get_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes, check_crc); ++ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ return rc; ++ } ++#endif ++ ++ return 1; ++ } else { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* support only 16-bit word write into srom */ ++int ++srom_write(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf) ++{ ++ uint i, nw, crc_range; ++ uint16 *old, *new; ++ uint8 crc; ++ volatile uint32 val32; ++ int rc = 1; ++ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ ++ old = MALLOC(osh, SROM_MAXW * sizeof(uint16)); ++ new = MALLOC(osh, SROM_MAXW * sizeof(uint16)); ++ ++ if (old == NULL || new == NULL) ++ goto done; ++ ++ /* check input - 16-bit access only. use byteoff 0x55aa to indicate ++ * srclear ++ */ ++ if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1))) ++ goto done; ++ ++ if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX)) ++ goto done; ++ ++ if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ crc_range = SROM_MAX; ++ } ++#if defined(BCMUSBDEV) ++ else { ++ crc_range = srom_size(sih, osh); ++ } ++#else ++ else { ++ crc_range = (SROM8_SIGN + 1) * 2; /* must big enough for SROM8 */ ++ } ++#endif ++ ++ nw = crc_range / 2; ++ /* read first small number words from srom, then adjust the length, read all */ ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ ++ BS_ERROR(("%s: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n", ++ __FUNCTION__, old[SROM4_SIGN], old[SROM8_SIGN])); ++ /* Deal with blank srom */ ++ if (old[0] == 0xffff) { ++ /* see if the input buffer is valid SROM image or not */ ++ if (buf[SROM11_SIGN] == SROM11_SIGNATURE) { ++ BS_ERROR(("%s: buf[SROM11_SIGN] 0x%x\n", ++ __FUNCTION__, buf[SROM11_SIGN])); ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM11_WORDS * 2) { ++ rc = BCME_BUFTOOSHORT; ++ goto done; ++ } else if (nbytes > SROM11_WORDS * 2) { ++ rc = BCME_BUFTOOLONG; ++ goto done; ++ } ++ ++ nw = SROM11_WORDS; ++ } else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (buf[SROM8_SIGN] == SROM4_SIGNATURE)) { ++ BS_ERROR(("%s: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n", ++ __FUNCTION__, buf[SROM4_SIGN], buf[SROM8_SIGN])); ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM4_WORDS * 2) { ++ rc = BCME_BUFTOOSHORT; ++ goto done; ++ } else if (nbytes > SROM4_WORDS * 2) { ++ rc = BCME_BUFTOOLONG; ++ goto done; ++ } ++ ++ nw = SROM4_WORDS; ++ } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */ ++ BS_ERROR(("%s: Not SROM4 or SROM8.\n", __FUNCTION__)); ++ ++ nw = SROM_WORDS; ++ } else { ++ BS_ERROR(("%s: Invalid input file signature\n", __FUNCTION__)); ++ rc = BCME_BADARG; ++ goto done; ++ } ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else if (old[SROM11_SIGN] == SROM11_SIGNATURE) { ++ nw = SROM11_WORDS; ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (old[SROM8_SIGN] == SROM4_SIGNATURE)) { ++ nw = SROM4_WORDS; ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else { ++ /* Assert that we have already read enough for sromrev 2 */ ++ ASSERT(crc_range >= SROM_WORDS * 2); ++ nw = SROM_WORDS; ++ crc_range = nw * 2; ++ } ++ ++ if (byteoff == 0x55aa) { ++ /* Erase request */ ++ crc_range = 0; ++ memset((void *)new, 0xff, nw * 2); ++ } else { ++ /* Copy old contents */ ++ bcopy((void *)old, (void *)new, nw * 2); ++ /* make changes */ ++ bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes); ++ } ++ ++ if (crc_range) { ++ /* calculate crc */ ++ htol16_buf(new, crc_range); ++ crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE); ++ ltoh16_buf(new, crc_range); ++ new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff); ++ } ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ uint16 *srom = NULL; ++ void *ccregs = NULL; ++ uint32 ccval = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* save current control setting */ ++ ccval = si_chipcontrl_read(sih); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { ++ /* Disable Ext PA lines to allow reading from SROM */ ++ si_chipcontrl_epa4331(sih, FALSE); ++ } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ si_chipcontrl_srom4360(sih, TRUE); ++ } ++ ++ /* enable writes to the SPROM */ ++ if (sih->ccrev > 31) { ++ ccregs = (void *)((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET); ++ srom = (uint16 *)((uint8 *)ccregs + CC_SROM_OTP); ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0); ++ } else { ++ srom = (uint16 *)((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET); ++ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ val32 |= SPROM_WRITEEN; ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32); ++ } ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ if (old[i] != new[i]) { ++ if (sih->ccrev > 31) { ++ if ((sih->cccaps & CC_CAP_SROM) == 0) { ++ /* No srom support in this chip */ ++ BS_ERROR(("srom_write, invalid srom, skip\n")); ++ } else ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE, ++ i, new[i]); ++ } else { ++ W_REG(osh, &srom[i], new[i]); ++ } ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ } ++ /* disable writes to the SPROM */ ++ if (sih->ccrev > 31) { ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0); ++ } else { ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ++ ~SPROM_WRITEEN); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* Restore config after reading SROM */ ++ si_chipcontrl_restore(sih, ccval); ++ } ++ ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ /* enable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WEN)) ++ goto done; ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ if (old[i] != new[i]) { ++ sprom_write_pcmcia(osh, (uint16)(i), new[i]); ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ } ++ /* disable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WDS)) ++ goto done; ++ } else if (BUSTYPE(bustype) == SI_BUS) { ++#if defined(BCMUSBDEV) ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint origidx; ++ void *regs; ++ bool wasup; ++ ++ origidx = si_coreidx(sih); ++ regs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!regs) ++ regs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(regs != NULL); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ rc = set_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes); ++ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ goto done; ++ } ++#endif ++ goto done; ++ } else { ++ goto done; ++ } ++ ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ rc = 0; ++ ++done: ++ if (old != NULL) ++ MFREE(osh, old, SROM_MAXW * sizeof(uint16)); ++ if (new != NULL) ++ MFREE(osh, new, SROM_MAXW * sizeof(uint16)); ++ ++ return rc; ++} ++#endif ++ ++#if defined(BCMUSBDEV) ++#define SI_PCMCIA_READ(osh, regs, fcr) \ ++ R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2) ++#define SI_PCMCIA_WRITE(osh, regs, fcr, v) \ ++ W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v) ++ ++/* set PCMCIA srom command register */ ++static int ++srom_cmd_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint8 cmd) ++{ ++ uint8 status = 0; ++ uint wait_cnt = 0; ++ ++ /* write srom command register */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_CS, cmd); ++ ++ /* wait status */ ++ while (++wait_cnt < 1000000) { ++ status = SI_PCMCIA_READ(osh, pcmregs, SROM_CS); ++ if (status & SROM_DONE) ++ return 0; ++ OSL_DELAY(1); ++ } ++ ++ BS_ERROR(("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, status)); ++ return 1; ++} ++ ++/* read a word from the PCMCIA srom over SI */ ++static int ++srom_read_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l); ++ ++ /* do read */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_READ)) ++ return 1; ++ ++ /* read data */ ++ data_h = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAH); ++ data_l = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAL); ++ *data = ((uint16)data_h << 8) | data_l; ++ ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* write a word to the PCMCIA srom over SI */ ++static int ++srom_write_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ int rc; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l); ++ ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); ++ ++ /* write data */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAH, data_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAL, data_l); ++ ++ /* do write */ ++ rc = srom_cmd_si_pcmcia(osh, pcmregs, SROM_WRITE); ++ OSL_DELAY(20000); ++ return rc; ++} ++#endif ++ ++/* ++ * Read the srom for the pcmcia-srom over si case. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz, bool check_crc) ++{ ++ uint i, nw, woff, wsz; ++ int err = 0; ++ ++ /* read must be at word boundary */ ++ ASSERT((boff & 1) == 0 && (bsz & 1) == 0); ++ ++ /* read sprom size and validate the parms */ ++ if ((nw = srom_size(sih, osh)) == 0) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom size unknown\n")); ++ err = -1; ++ goto out; ++ } ++ if (boff + bsz > 2 * nw) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom size exceeded\n")); ++ err = -2; ++ goto out; ++ } ++ ++ /* read in sprom contents */ ++ for (woff = boff / 2, wsz = bsz / 2, i = 0; ++ woff < nw && i < wsz; woff ++, i ++) { ++ if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &srom[i])) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom read failed\n")); ++ err = -3; ++ goto out; ++ } ++ } ++ ++ if (check_crc) { ++ if (srom[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: srom[0] == 0xffff, assuming unprogrammed srom\n", ++ __FUNCTION__)); ++ err = -4; ++ goto out; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(srom, nw * 2); ++ if (hndcrc8((uint8 *)srom, nw * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ BS_ERROR(("%s: bad crc\n", __FUNCTION__)); ++ err = -5; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(srom, nw * 2); ++ } ++ ++out: ++ return err; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* ++ * Write the srom for the pcmcia-srom over si case. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz) ++{ ++ uint i, nw, woff, wsz; ++ uint16 word; ++ uint8 crc; ++ int err = 0; ++ ++ /* write must be at word boundary */ ++ ASSERT((boff & 1) == 0 && (bsz & 1) == 0); ++ ++ /* read sprom size and validate the parms */ ++ if ((nw = srom_size(sih, osh)) == 0) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom size unknown\n")); ++ err = -1; ++ goto out; ++ } ++ if (boff + bsz > 2 * nw) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom size exceeded\n")); ++ err = -2; ++ goto out; ++ } ++ ++ /* enable write */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WEN)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom wen failed\n")); ++ err = -3; ++ goto out; ++ } ++ ++ /* write buffer to sprom */ ++ for (woff = boff / 2, wsz = bsz / 2, i = 0; ++ woff < nw && i < wsz; woff ++, i ++) { ++ if (srom_write_si_pcmcia(osh, pcmregs, (uint16)woff, srom[i])) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom write failed\n")); ++ err = -4; ++ goto out; ++ } ++ } ++ ++ /* fix crc */ ++ crc = CRC8_INIT_VALUE; ++ for (woff = 0; woff < nw; woff ++) { ++ if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &word)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom fix crc read failed\n")); ++ err = -5; ++ goto out; ++ } ++ word = htol16(word); ++ crc = hndcrc8((uint8 *)&word, woff != nw - 1 ? 2 : 1, crc); ++ } ++ word = (~crc << 8) + (ltoh16(word) & 0xff); ++ if (srom_write_si_pcmcia(osh, pcmregs, (uint16)(woff - 1), word)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom fix crc write failed\n")); ++ err = -6; ++ goto out; ++ } ++ ++ /* disable write */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WDS)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom wds failed\n")); ++ err = -7; ++ goto out; ++ } ++ ++out: ++ return err; ++} ++#endif ++#endif ++ ++static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s"; ++static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s"; ++static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x"; ++static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x"; ++static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d"; ++static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d"; ++static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d"; ++static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x"; ++static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x"; ++static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x"; ++static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x"; ++static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x"; ++static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x"; ++static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d"; ++static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d"; ++static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" }; ++static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d"; ++static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1lob)[][11] = ++ { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1hib)[][11] = ++ { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d"; ++static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d"; ++static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x"; ++static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x"; ++static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x"; ++static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x"; ++static const char BCMATTACHDATA(vstr_ledbh)[] = "ledbh%d=0x%x"; ++static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0"; ++static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c"; ++static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x"; ++static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x"; ++static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d"; ++static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d"; ++static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d"; ++static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d"; ++static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d"; ++static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d"; ++static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d"; ++static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d"; ++static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d"; ++static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d"; ++static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d"; ++static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d"; ++static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d"; ++static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d"; ++static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d"; ++static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d"; ++static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d"; ++static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d"; ++static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d"; ++static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d"; ++static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x"; ++static const char BCMATTACHDATA(vstr_leddc)[] = "leddc=0x%04x"; ++static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x"; ++static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x"; ++static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d"; ++static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x"; ++static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x"; ++static const char BCMNMIATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x"; ++static const char BCMNMIATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x"; ++static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x"; ++static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x"; ++static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x"; ++static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x"; ++static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x"; ++static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x"; ++static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x"; ++static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x"; ++static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x"; ++static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x"; ++static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x"; ++static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x"; ++static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x"; ++static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x"; ++static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x"; ++static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x"; ++static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x"; ++static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x"; ++static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x"; ++static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x"; ++static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x"; ++static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d"; ++static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x"; ++#ifdef BCM_BOOTLOADER ++static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x"; ++static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x"; ++static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x"; ++static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x"; ++static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x"; ++static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x"; ++static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x"; ++static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x"; ++static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x"; ++static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x"; ++static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x"; ++static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x"; ++static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x"; ++static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x"; ++static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x"; ++static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x"; ++static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x"; ++#endif /* BCM_BOOTLOADER */ ++static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d"; ++static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s"; ++static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x"; ++ ++/* Power per rate for SROM V9 */ ++static const char BCMATTACHDATA(vstr_cckbw202gpo)[][19] = ++ { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x" }; ++static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][22] = ++ { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" }; ++static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] = ++ { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x", ++ "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x", ++ "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" }; ++ ++static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] = ++{ "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] = ++ { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] = ++ { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] = ++ { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x"; ++static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x"; ++ ++/* SROM V11 */ ++static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d"; /* HNBU_TEMPTHRESH */ ++static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d"; ++static const char BCMATTACHDATA(vstr_temp_hysteresis)[] = "temp_hysteresis=%d"; ++static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d"; ++static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d"; ++static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d"; ++static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d"; ++static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d"; /* HNBU_FEM_CFG */ ++static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d"; ++static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d"; ++static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d"; ++static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d"; ++static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d"; ++static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d"; ++static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d"; /* HNBU_ACPA_CX */ ++static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," ++ "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina=%d"; ++static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d"; ++static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d"; ++static const char BCMATTACHDATA(vstr_measpower)[] = "measpower%d=0x%x"; /* HNBU_MEAS_PWR */ ++static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x"; ++static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x"; ++/* HNBU_ACPPR_2GPO */ ++static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805glpo)[] = "mcsbw805glpo=0x%x"; /* HNBU_ACPPR_5GPO */ ++static const char BCMATTACHDATA(vstr_mcsbw1605glpo)[] = "mcsbw1605glpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805gmpo)[] = "mcsbw805gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw1605gmpo)[] = "mcsbw1605gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805ghpo)[] = "mcsbw805ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw1605ghpo)[] = "mcsbw1605ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5rlpo)[] = "mcslr5rlpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5gmpo)[] = "mcslr5gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5ghpo)[] = "mcslr5ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_sb20in40rrpo)[] = "sb20in40%crrpo=0x%x"; /* HNBU_ACPPR_SBPO */ ++static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x"; ++static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x"; ++static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x"; ++static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d"; /* HNBU_NOISELVL */ ++static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5g%ca%d=%d"; ++static const char BCMATTACHDATA(vstr_rxgainerr2g)[] = "rxgainerr2g=0x%x"; /* HNBU_RXGAIN_ERR */ ++static const char BCMATTACHDATA(vstr_rxgainerr5g)[] = "rxgainerr5g=0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x"; /* HNBU_AGBGA */ ++static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x"; ++ ++static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s"; ++ ++static const char BCMATTACHDATA(vstr_end)[] = "END\0"; ++ ++uint8 patch_pair = 0; ++ ++/* For dongle HW, accept partial calibration parameters */ ++#if defined(BCMUSBDEV) ++#define BCMDONGLECASE(n) case n: ++#else ++#define BCMDONGLECASE(n) ++#endif ++ ++#ifdef BCM_BOOTLOADER ++/* The format of the PMUREGS OTP Tuple -> ++ * 1 byte -> Lower 5 bits has the address of the register ++ * Higher 3 bits has the mode of the register like ++ * PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask ++ * 4 bytes -> Value of the register to be updated. ++ */ ++#define PMUREGS_MODE_MASK 0xE0 ++#define PMUREGS_MODE_SHIFT 5 ++#define PMUREGS_ADDR_MASK 0x1F ++#define PMUREGS_TPL_SIZE 5 ++ ++enum { ++ PMU_PLLREG_MODE, ++ PMU_CCREG_MODE, ++ PMU_VOLTREG_MODE, ++ PMU_RES_TIME_MODE, ++ PMU_RESDEPEND_MODE ++}; ++ ++#define USBREGS_TPL_SIZE 5 ++enum { ++ USB_DEV_CTRL_REG, ++ HSIC_PHY_CTRL1_REG, ++ HSIC_PHY_CTRL2_REG ++}; ++ ++#define USBRDY_DLY_TYPE 0x8000 /* Bit indicating if the byte is pre or post delay value */ ++#define USBRDY_DLY_MASK 0x7FFF /* Bits indicating the amount of delay */ ++#define USBRDY_MAXOTP_SIZE 5 /* Max size of the OTP parameter */ ++ ++#endif /* BCM_BOOTLOADER */ ++ ++#ifdef BCM_BMAC_VARS_APPEND ++int ++BCMATTACHFN(srom_probe_boardtype)(uint8 *pcis[], uint ciscnt) ++{ ++ int i; ++ uint cisnum; ++ uint8 *cis, tup, tlen; ++ ++ for (cisnum = 0; cisnum < ciscnt; cisnum++) { ++ cis = *pcis++; ++ i = 0; ++ do { ++ tup = cis[i++]; ++ if (tup == CISTPL_NULL || tup == CISTPL_END) ++ tlen = 0; ++ else ++ tlen = cis[i++]; ++ ++ if ((i + tlen) >= CIS_SIZE) ++ break; ++ ++ if ((tup == CISTPL_BRCM_HNBU) && (cis[i] == HNBU_BOARDTYPE)) { ++ return (int)((cis[i + 2] << 8) + cis[i + 1]); ++ } ++ ++ i += tlen; ++ ++ } while (tup != CISTPL_END); ++ } ++ ++ return 0; ++} ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++int ++BCMATTACHFN(srom_parsecis)(osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *count) ++{ ++ char eabuf[32]; ++ char *base; ++ varbuf_t b; ++ uint8 *cis, tup, tlen, sromrev = 1; ++ int i, j; ++#ifndef BCM_BOOTLOADER ++ bool ag_init = FALSE; ++#endif ++ uint32 w32; ++ uint funcid; ++ uint cisnum; ++ int32 boardnum; ++ int err; ++ bool standard_cis; ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ boardnum = -1; ++ ++ base = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(base != NULL); ++ if (!base) ++ return -2; ++ ++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS); ++ bzero(base, MAXSZ_NVRAM_VARS); ++#ifdef BCM_BMAC_VARS_APPEND ++ /* 43236 use defaultsromvars_43236usb as the base, ++ * then append and update it with the content from OTP. ++ * Only revision/board specfic content or updates used to override ++ * the driver default will be stored in OTP ++ */ ++ *count -= (strlen(vstr_end) + 1 + 1); /* back off the termnating END\0\0 from fakenvram */ ++ bcopy(*vars, base, *count); ++ b.buf += *count; ++#endif /* BCM_BMAC_VARS_APPEND */ ++ eabuf[0] = '\0'; ++ for (cisnum = 0; cisnum < ciscnt; cisnum++) { ++ cis = *pcis++; ++ i = 0; ++ funcid = 0; ++ standard_cis = TRUE; ++ do { ++ if (standard_cis) { ++ tup = cis[i++]; ++ if (tup == CISTPL_NULL || tup == CISTPL_END) ++ tlen = 0; ++ else ++ tlen = cis[i++]; ++ } else { ++ if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) { ++ tlen = 0; ++ tup = cis[i]; ++ } else { ++ tlen = cis[i]; ++ tup = CISTPL_BRCM_HNBU; ++ } ++ ++i; ++ } ++ if ((i + tlen) >= CIS_SIZE) ++ break; ++ ++ switch (tup) { ++ case CISTPL_VERS_1: ++ /* assume the strings are good if the version field checks out */ ++ if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) { ++ varbuf_append(&b, vstr_manf, &cis[i + 2]); ++ varbuf_append(&b, vstr_productname, ++ &cis[i + 3 + strlen((char *)&cis[i + 2])]); ++ break; ++ } ++ ++ case CISTPL_MANFID: ++ varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]); ++ varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]); ++ break; ++ ++ case CISTPL_FUNCID: ++ funcid = cis[i]; ++ break; ++ ++ case CISTPL_FUNCE: ++ switch (funcid) { ++ case CISTPL_FID_SDIO: ++ funcid = 0; ++ break; ++ default: ++ /* set macaddr if HNBU_MACADDR not seen yet */ ++ if (eabuf[0] == '\0' && cis[i] == LAN_NID && ++ !(ETHER_ISNULLADDR(&cis[i + 2])) && ++ !(ETHER_ISMULTI(&cis[i + 2]))) { ++ ASSERT(cis[i + 1] == ETHER_ADDR_LEN); ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 2], ++ eabuf); ++ ++ /* set boardnum if HNBU_BOARDNUM not seen yet */ ++ if (boardnum == -1) ++ boardnum = (cis[i + 6] << 8) + cis[i + 7]; ++ } ++ break; ++ } ++ break; ++ ++ case CISTPL_CFTABLE: ++ varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]); ++ break; ++ ++ case CISTPL_BRCM_HNBU: ++ switch (cis[i]) { ++ case HNBU_SROMREV: ++ sromrev = cis[i + 1]; ++ varbuf_append(&b, vstr_sromrev, sromrev); ++ break; ++ ++ case HNBU_XTALFREQ: ++ varbuf_append(&b, vstr_xtalfreq, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_CHIPID: ++ varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) + ++ cis[i + 1]); ++ varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) + ++ cis[i + 3]); ++ if (tlen >= 7) { ++ varbuf_append(&b, vstr_chiprev, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ } ++ if (tlen >= 9) { ++ varbuf_append(&b, vstr_subvendid, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ } ++ if (tlen >= 11) { ++ varbuf_append(&b, vstr_subdevid, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ /* subdevid doubles for boardtype */ ++ varbuf_append(&b, vstr_boardtype, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ } ++ break; ++ ++ case HNBU_BOARDNUM: ++ boardnum = (cis[i + 2] << 8) + cis[i + 1]; ++ break; ++ ++ case HNBU_PATCH: ++ { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ ++ /* retrieve the patch pairs ++ * from tlen/6; where 6 is ++ * sizeof(patch addr(2)) + ++ * sizeof(patch data(4)). ++ */ ++ patch_pair = tlen/6; ++ ++ for (j = 0; j < patch_pair; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j); ++ ++ varbuf_append(&b, vstr_paddr, ++ (cis[i + (j*6) + 2] << 8) | ++ cis[i + (j*6) + 1]); ++ ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*6) + 6] << 24) | ++ (cis[i + (j*6) + 5] << 16) | ++ (cis[i + (j*6) + 4] << 8) | ++ cis[i + (j*6) + 3]); ++ } ++ } ++ break; ++ ++ case HNBU_BOARDREV: ++ if (tlen == 2) ++ varbuf_append(&b, vstr_boardrev, cis[i + 1]); ++ else ++ varbuf_append(&b, vstr_boardrev, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_BOARDFLAGS: ++ w32 = (cis[i + 2] << 8) + cis[i + 1]; ++ if (tlen >= 5) ++ w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16)); ++ varbuf_append(&b, vstr_boardflags, w32); ++ ++ if (tlen >= 7) { ++ w32 = (cis[i + 6] << 8) + cis[i + 5]; ++ if (tlen >= 9) ++ w32 |= ((cis[i + 8] << 24) + ++ (cis[i + 7] << 16)); ++ varbuf_append(&b, vstr_boardflags2, w32); ++ } ++ if (tlen >= 11) { ++ w32 = (cis[i + 10] << 8) + cis[i + 9]; ++ if (tlen >= 13) ++ w32 |= ((cis[i + 12] << 24) + ++ (cis[i + 11] << 16)); ++ varbuf_append(&b, vstr_boardflags3, w32); ++ } ++ break; ++ ++ case HNBU_USBFS: ++ varbuf_append(&b, vstr_usbfs, cis[i + 1]); ++ break; ++ ++ case HNBU_BOARDTYPE: ++ varbuf_append(&b, vstr_boardtype, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_HNBUCIS: ++ /* ++ * what follows is a nonstandard HNBU CIS ++ * that lacks CISTPL_BRCM_HNBU tags ++ * ++ * skip 0xff (end of standard CIS) ++ * after this tuple ++ */ ++ tlen++; ++ standard_cis = FALSE; ++ break; ++ ++ case HNBU_USBEPNUM: ++ varbuf_append(&b, vstr_usbepnum, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_PATCH_AUTOINC: { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ uint32 addr_inc; ++ uint8 pcnt; ++ ++ addr_inc = (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ (cis[i + 1]); ++ ++ pcnt = (tlen - 5)/4; ++ for (j = 0; j < pcnt; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j + patch_pair); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j + patch_pair); ++ ++ varbuf_append(&b, vstr_paddr, addr_inc); ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*4) + 8] << 24) | ++ (cis[i + (j*4) + 7] << 16) | ++ (cis[i + (j*4) + 6] << 8) | ++ cis[i + (j*4) + 5]); ++ addr_inc += 4; ++ } ++ patch_pair += pcnt; ++ } ++ break; ++ case HNBU_PATCH2: ++ { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ ++ /* retrieve the patch pairs ++ * from tlen/8; where 8 is ++ * sizeof(patch addr(4)) + ++ * sizeof(patch data(4)). ++ */ ++ patch_pair = tlen/8; ++ ++ for (j = 0; j < patch_pair; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j); ++ ++ varbuf_append(&b, vstr_paddr, ++ (cis[i + (j*8) + 4] << 24) | ++ (cis[i + (j*8) + 3] << 16) | ++ (cis[i + (j*8) + 2] << 8) | ++ cis[i + (j*8) + 1]); ++ ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*8) + 8] << 24) | ++ (cis[i + (j*8) + 7] << 16) | ++ (cis[i + (j*8) + 6] << 8) | ++ cis[i + (j*8) + 5]); ++ } ++ } ++ break; ++ case HNBU_USBFLAGS: ++ varbuf_append(&b, vstr_usbflags, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++#ifdef BCM_BOOTLOADER ++ case HNBU_MDIOEX_REGLIST: ++ case HNBU_MDIO_REGLIST: { ++ /* Format: addr (8 bits) | val (16 bits) */ ++ const uint8 msize = 3; ++ char mdiostr[24]; ++ const char *mdiodesc; ++ uint8 *st; ++ ++ mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ? ++ vstr_mdio : vstr_mdioex; ++ ++ ASSERT(((tlen - 1) % msize) == 0); ++ ++ st = &cis[i + 1]; /* start of reg list */ ++ for (j = 0; j < (tlen - 1); j += msize, st += msize) { ++ snprintf(mdiostr, sizeof(mdiostr), ++ mdiodesc, st[0]); ++ varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]); ++ } ++ } ++ break; ++ case HNBU_BRMIN: ++ varbuf_append(&b, vstr_brmin, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_BRMAX: ++ varbuf_append(&b, vstr_brmax, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++#endif /* BCM_BOOTLOADER */ ++ ++ case HNBU_RDLID: ++ varbuf_append(&b, vstr_rdlid, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_GCI_CCR: ++ { ++ /* format: ++ * |0x80 | <== brcm ++ * |len| <== variable, multiple of 5 ++ * |tup| <== tupletype ++ * |ccreg_ix0|<== ix of ccreg [1byte] ++ * |ccreg_val0|<= corr value [4bytes] ++ * --- ++ * Multiple registers are possible. for eg: we ++ * can specify reg_ix3val3 and reg_ix5val5, etc ++ */ ++ char vstr_gci_ccreg_entry[16]; ++ int num_entries = 0; ++ ++ /* retrieve the index-value pairs ++ * from tlen/5; where 5 is ++ * sizeof(ccreg_ix(1)) + ++ * sizeof(ccreg_val(4)). ++ */ ++ num_entries = tlen/5; ++ ++ for (j = 0; j < num_entries; j++) { ++ snprintf(vstr_gci_ccreg_entry, ++ sizeof(vstr_gci_ccreg_entry), ++ "gcr%d=0x%%x", cis[i + (j*5) + 1]); ++ ++ varbuf_append(&b, vstr_gci_ccreg_entry, ++ (cis[i + (j*5) + 5] << 24) | ++ (cis[i + (j*5) + 4] << 16) | ++ (cis[i + (j*5) + 3] << 8) | ++ cis[i + (j*5) + 2]); ++ } ++ } ++ break; ++ ++#ifdef BCM_BOOTLOADER ++ case HNBU_RDLRNDIS: ++ varbuf_append(&b, vstr_rdlrndis, cis[i + 1]); ++ break; ++ ++ case HNBU_RDLRWU: ++ varbuf_append(&b, vstr_rdlrwu, cis[i + 1]); ++ break; ++ ++ case HNBU_RDLSN: ++ if (tlen >= 5) ++ varbuf_append(&b, vstr_rdlsn, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ else ++ varbuf_append(&b, vstr_rdlsn, ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_PMUREGS: ++ { ++ uint8 offset = 1, mode_addr, mode, addr; ++ const char *fmt; ++ ++ do { ++ mode_addr = cis[i+offset]; ++ ++ mode = (mode_addr & PMUREGS_MODE_MASK) ++ >> PMUREGS_MODE_SHIFT; ++ addr = mode_addr & PMUREGS_ADDR_MASK; ++ ++ switch (mode) { ++ case PMU_PLLREG_MODE: ++ fmt = vstr_pllreg; ++ break; ++ case PMU_CCREG_MODE: ++ fmt = vstr_ccreg; ++ break; ++ case PMU_VOLTREG_MODE: ++ fmt = vstr_regctrl; ++ break; ++ case PMU_RES_TIME_MODE: ++ fmt = vstr_time; ++ break; ++ case PMU_RESDEPEND_MODE: ++ fmt = vstr_depreg; ++ break; ++ default: ++ fmt = NULL; ++ break; ++ } ++ ++ if (fmt != NULL) { ++ varbuf_append(&b, fmt, addr, ++ (cis[i + offset + 4] << 24) | ++ (cis[i + offset + 3] << 16) | ++ (cis[i + offset + 2] << 8) | ++ cis[i + offset + 1]); ++ } ++ ++ offset += PMUREGS_TPL_SIZE; ++ } while (offset < tlen); ++ } ++ break; ++ ++ case HNBU_USBREGS: ++ { ++ uint8 offset = 1, usb_reg; ++ const char *fmt; ++ ++ do { ++ usb_reg = cis[i+offset]; ++ ++ switch (usb_reg) { ++ case USB_DEV_CTRL_REG: ++ fmt = vstr_usbdevctrl; ++ break; ++ case HSIC_PHY_CTRL1_REG: ++ fmt = vstr_hsicphyctrl1; ++ break; ++ case HSIC_PHY_CTRL2_REG: ++ fmt = vstr_hsicphyctrl2; ++ break; ++ default: ++ fmt = NULL; ++ break; ++ } ++ ++ if (fmt != NULL) { ++ varbuf_append(&b, fmt, ++ (cis[i + offset + 4] << 24) | ++ (cis[i + offset + 3] << 16) | ++ (cis[i + offset + 2] << 8) | ++ cis[i + offset + 1]); ++ } ++ ++ offset += USBREGS_TPL_SIZE; ++ } while (offset < tlen); ++ } ++ break; ++ ++ case HNBU_USBRDY: ++ /* The first byte of this tuple indicate if the host ++ * needs to be informed about the readiness of ++ * the HSIC/USB for enumeration on which GPIO should ++ * the device assert this event. ++ */ ++ varbuf_append(&b, vstr_usbrdy, cis[i + 1]); ++ ++ /* The following fields in this OTP are optional. ++ * The remaining bytes will indicate the delay required ++ * before and/or after the ch_init(). The delay is defined ++ * using 16-bits of this the MSB(bit15 of 15:0) will be ++ * used indicate if the parameter is for Pre or Post delay. ++ */ ++ for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen; ++ j += 2) { ++ uint16 usb_delay; ++ ++ usb_delay = cis[i + j] | (cis[i + j + 1] << 8); ++ ++ /* The bit-15 of the delay field will indicate the ++ * type of delay (pre or post). ++ */ ++ if (usb_delay & USBRDY_DLY_TYPE) { ++ varbuf_append(&b, vstr_usbpostdly, ++ (usb_delay & USBRDY_DLY_MASK)); ++ } else { ++ varbuf_append(&b, vstr_usbpredly, ++ (usb_delay & USBRDY_DLY_MASK)); ++ } ++ } ++ break; ++ ++ case HNBU_BLDR_TIMEOUT: ++ /* The Delay after USBConnect for timeout till dongle ++ * receives get_descriptor request. ++ */ ++ varbuf_append(&b, vstr_bldr_reset_timeout, ++ (cis[i + 1] | (cis[i + 2] << 8))); ++ break; ++ case HNBU_MUXENAB: ++ varbuf_append(&b, vstr_muxenab, cis[i + 1]); ++ break; ++#else ++ case HNBU_AA: ++ varbuf_append(&b, vstr_aa2g, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_aa5g, cis[i + 2]); ++ break; ++ ++ case HNBU_AG: ++ varbuf_append(&b, vstr_ag, 0, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_ag, 1, cis[i + 2]); ++ if (tlen >= 4) ++ varbuf_append(&b, vstr_ag, 2, cis[i + 3]); ++ if (tlen >= 5) ++ varbuf_append(&b, vstr_ag, 3, cis[i + 4]); ++ ag_init = TRUE; ++ break; ++ ++ case HNBU_ANT5G: ++ varbuf_append(&b, vstr_aa5g, cis[i + 1]); ++ varbuf_append(&b, vstr_ag, 1, cis[i + 2]); ++ break; ++ ++ case HNBU_CC: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_cc, cis[i + 1]); ++ break; ++ ++ case HNBU_PAPARMS: ++ switch (tlen) { ++ case 2: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]); ++ break; ++ case 10: ++ ASSERT(sromrev >= 2); ++ varbuf_append(&b, vstr_opo, cis[i + 9]); ++ /* FALLTHROUGH */ ++ case 9: ++ varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]); ++ /* FALLTHROUGH */ ++ BCMDONGLECASE(8) ++ varbuf_append(&b, vstr_pa0itssit, cis[i + 7]); ++ /* FALLTHROUGH */ ++ BCMDONGLECASE(7) ++ for (j = 0; j < 3; j++) { ++ varbuf_append(&b, vstr_pa0b[j], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ break; ++ default: ++ ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10)); ++ break; ++ } ++ break; ++ ++ case HNBU_PAPARMS5G: ++ ASSERT((sromrev == 2) || (sromrev == 3)); ++ switch (tlen) { ++ case 23: ++ varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]); ++ varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]); ++ varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]); ++ /* FALLTHROUGH */ ++ case 20: ++ varbuf_append(&b, vstr_pa1itssit, cis[i + 19]); ++ /* FALLTHROUGH */ ++ case 19: ++ for (j = 0; j < 3; j++) { ++ varbuf_append(&b, vstr_pa1b[j], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ for (j = 3; j < 6; j++) { ++ varbuf_append(&b, vstr_pa1lob[j - 3], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ for (j = 6; j < 9; j++) { ++ varbuf_append(&b, vstr_pa1hib[j - 6], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ break; ++ default: ++ ASSERT((tlen == 19) || ++ (tlen == 20) || (tlen == 23)); ++ break; ++ } ++ break; ++ ++ case HNBU_OEM: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_oem, ++ cis[i + 1], cis[i + 2], ++ cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], ++ cis[i + 7], cis[i + 8]); ++ break; ++ ++ case HNBU_LEDS: ++ for (j = 1; j <= 4; j++) { ++ if (cis[i + j] != 0xff) { ++ varbuf_append(&b, vstr_ledbh, j-1, ++ cis[i + j]); ++ } ++ } ++ break; ++ ++ case HNBU_CCODE: ++ ASSERT(sromrev > 1); ++ if ((cis[i + 1] == 0) || (cis[i + 2] == 0)) ++ varbuf_append(&b, vstr_noccode); ++ else ++ varbuf_append(&b, vstr_ccode, ++ cis[i + 1], cis[i + 2]); ++ varbuf_append(&b, vstr_cctl, cis[i + 3]); ++ break; ++ ++ case HNBU_CCKPO: ++ ASSERT(sromrev > 2); ++ varbuf_append(&b, vstr_cckpo, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_OFDMPO: ++ ASSERT(sromrev > 2); ++ varbuf_append(&b, vstr_ofdmpo, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_WPS: ++ varbuf_append(&b, vstr_wpsgpio, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_wpsled, cis[i + 2]); ++ break; ++ ++ case HNBU_RSSISMBXA2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf); ++ varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf); ++ varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7); ++ varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3); ++ break; ++ ++ case HNBU_RSSISMBXA5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf); ++ varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf); ++ varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7); ++ varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3); ++ break; ++ ++ case HNBU_TRI2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_tri2g, cis[i + 1]); ++ break; ++ ++ case HNBU_TRI5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_tri5gl, cis[i + 1]); ++ varbuf_append(&b, vstr_tri5g, cis[i + 2]); ++ varbuf_append(&b, vstr_tri5gh, cis[i + 3]); ++ break; ++ ++ case HNBU_RXPO2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rxpo2g, cis[i + 1]); ++ break; ++ ++ case HNBU_RXPO5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rxpo5g, cis[i + 1]); ++ break; ++ ++ case HNBU_MACADDR: ++ if (!(ETHER_ISNULLADDR(&cis[i+1])) && ++ !(ETHER_ISMULTI(&cis[i+1]))) { ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 1], ++ eabuf); ++ ++ /* set boardnum if HNBU_BOARDNUM not seen yet */ ++ if (boardnum == -1) ++ boardnum = (cis[i + 5] << 8) + cis[i + 6]; ++ } ++ break; ++ ++ case HNBU_LEDDC: ++ /* CIS leddc only has 16bits, convert it to 32bits */ ++ w32 = ((cis[i + 2] << 24) | /* oncount */ ++ (cis[i + 1] << 8)); /* offcount */ ++ varbuf_append(&b, vstr_leddc, w32); ++ break; ++ ++ case HNBU_CHAINSWITCH: ++ varbuf_append(&b, vstr_txchain, cis[i + 1]); ++ varbuf_append(&b, vstr_rxchain, cis[i + 2]); ++ varbuf_append(&b, vstr_antswitch, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ break; ++ ++ case HNBU_ELNA2G: ++ varbuf_append(&b, vstr_elna2g, cis[i + 1]); ++ break; ++ ++ case HNBU_ELNA5G: ++ varbuf_append(&b, vstr_elna5g, cis[i + 1]); ++ break; ++ ++ case HNBU_REGREV: ++ varbuf_append(&b, vstr_regrev, cis[i + 1]); ++ break; ++ ++ case HNBU_FEM: { ++ uint16 fem = (cis[i + 2] << 8) + cis[i + 1]; ++ varbuf_append(&b, vstr_antswctl2g, (fem & ++ SROM8_FEM_ANTSWLUT_MASK) >> ++ SROM8_FEM_ANTSWLUT_SHIFT); ++ varbuf_append(&b, vstr_triso2g, (fem & ++ SROM8_FEM_TR_ISO_MASK) >> ++ SROM8_FEM_TR_ISO_SHIFT); ++ varbuf_append(&b, vstr_pdetrange2g, (fem & ++ SROM8_FEM_PDET_RANGE_MASK) >> ++ SROM8_FEM_PDET_RANGE_SHIFT); ++ varbuf_append(&b, vstr_extpagain2g, (fem & ++ SROM8_FEM_EXTPA_GAIN_MASK) >> ++ SROM8_FEM_EXTPA_GAIN_SHIFT); ++ varbuf_append(&b, vstr_tssipos2g, (fem & ++ SROM8_FEM_TSSIPOS_MASK) >> ++ SROM8_FEM_TSSIPOS_SHIFT); ++ if (tlen < 5) break; ++ ++ fem = (cis[i + 4] << 8) + cis[i + 3]; ++ varbuf_append(&b, vstr_antswctl5g, (fem & ++ SROM8_FEM_ANTSWLUT_MASK) >> ++ SROM8_FEM_ANTSWLUT_SHIFT); ++ varbuf_append(&b, vstr_triso5g, (fem & ++ SROM8_FEM_TR_ISO_MASK) >> ++ SROM8_FEM_TR_ISO_SHIFT); ++ varbuf_append(&b, vstr_pdetrange5g, (fem & ++ SROM8_FEM_PDET_RANGE_MASK) >> ++ SROM8_FEM_PDET_RANGE_SHIFT); ++ varbuf_append(&b, vstr_extpagain5g, (fem & ++ SROM8_FEM_EXTPA_GAIN_MASK) >> ++ SROM8_FEM_EXTPA_GAIN_SHIFT); ++ varbuf_append(&b, vstr_tssipos5g, (fem & ++ SROM8_FEM_TSSIPOS_MASK) >> ++ SROM8_FEM_TSSIPOS_SHIFT); ++ break; ++ } ++ ++ case HNBU_PAPARMS_C0: ++ varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]); ++ varbuf_append(&b, vstr_itt2ga0, cis[i + 2]); ++ varbuf_append(&b, vstr_pa, 2, 0, 0, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_pa, 2, 1, 0, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_pa, 2, 2, 0, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ if (tlen < 31) break; ++ ++ varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]); ++ varbuf_append(&b, vstr_itt5ga0, cis[i + 10]); ++ varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]); ++ varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]); ++ varbuf_append(&b, vstr_pa, 5, 0, 0, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_pa, 5, 1, 0, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_pa, 5, 2, 0, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0, ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0, ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0, ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0, ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0, ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0, ++ (cis[i + 30] << 8) + cis[i + 29]); ++ break; ++ ++ case HNBU_PAPARMS_C1: ++ varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]); ++ varbuf_append(&b, vstr_itt2ga1, cis[i + 2]); ++ varbuf_append(&b, vstr_pa, 2, 0, 1, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_pa, 2, 1, 1, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_pa, 2, 2, 1, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ if (tlen < 31) break; ++ ++ varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]); ++ varbuf_append(&b, vstr_itt5ga1, cis[i + 10]); ++ varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]); ++ varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]); ++ varbuf_append(&b, vstr_pa, 5, 0, 1, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_pa, 5, 1, 1, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_pa, 5, 2, 1, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1, ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1, ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1, ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1, ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1, ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1, ++ (cis[i + 30] << 8) + cis[i + 29]); ++ break; ++ ++ case HNBU_PO_CCKOFDM: ++ varbuf_append(&b, vstr_cck2gpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdm2gpo, ++ (cis[i + 6] << 24) + (cis[i + 5] << 16) + ++ (cis[i + 4] << 8) + cis[i + 3]); ++ if (tlen < 19) break; ++ ++ varbuf_append(&b, vstr_ofdm5gpo, ++ (cis[i + 10] << 24) + (cis[i + 9] << 16) + ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_ofdm5glpo, ++ (cis[i + 14] << 24) + (cis[i + 13] << 16) + ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_ofdm5ghpo, ++ (cis[i + 18] << 24) + (cis[i + 17] << 16) + ++ (cis[i + 16] << 8) + cis[i + 15]); ++ break; ++ ++ case HNBU_PO_MCS2G: ++ for (j = 0; j <= (tlen/2); j++) { ++ varbuf_append(&b, vstr_mcspo, 2, j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ break; ++ ++ case HNBU_PO_MCS5GM: ++ for (j = 0; j <= (tlen/2); j++) { ++ varbuf_append(&b, vstr_mcspo, 5, j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ break; ++ ++ case HNBU_PO_MCS5GLH: ++ for (j = 0; j <= (tlen/4); j++) { ++ varbuf_append(&b, vstr_mcspohl, 5, 'l', j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ ++ for (j = 0; j <= (tlen/4); j++) { ++ varbuf_append(&b, vstr_mcspohl, 5, 'h', j, ++ (cis[i + ((tlen/2)+2) + 2*j] << 8) + ++ cis[i + ((tlen/2)+1) + 2*j]); ++ } ++ ++ break; ++ ++ case HNBU_PO_CDD: ++ varbuf_append(&b, vstr_cddpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_STBC: ++ varbuf_append(&b, vstr_stbcpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_40M: ++ varbuf_append(&b, vstr_bw40po, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_40MDUP: ++ varbuf_append(&b, vstr_bwduppo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_OFDMPO5G: ++ varbuf_append(&b, vstr_ofdm5gpo, ++ (cis[i + 4] << 24) + (cis[i + 3] << 16) + ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdm5glpo, ++ (cis[i + 8] << 24) + (cis[i + 7] << 16) + ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_ofdm5ghpo, ++ (cis[i + 12] << 24) + (cis[i + 11] << 16) + ++ (cis[i + 10] << 8) + cis[i + 9]); ++ break; ++ /* Power per rate for SROM V9 */ ++ case HNBU_CCKBW202GPO: ++ varbuf_append(&b, vstr_cckbw202gpo[0], ++ ((cis[i + 2] << 8) + cis[i + 1])); ++ if (tlen > 4) ++ varbuf_append(&b, vstr_cckbw202gpo[1], ++ ((cis[i + 4] << 8) + cis[i + 3])); ++ break; ++ ++ case HNBU_LEGOFDMBW202GPO: ++ varbuf_append(&b, vstr_legofdmbw202gpo[0], ++ ((cis[i + 4] << 24) + (cis[i + 3] << 16) + ++ (cis[i + 2] << 8) + cis[i + 1])); ++ if (tlen > 6) { ++ varbuf_append(&b, vstr_legofdmbw202gpo[1], ++ ((cis[i + 8] << 24) + (cis[i + 7] << 16) + ++ (cis[i + 6] << 8) + cis[i + 5])); ++ } ++ break; ++ ++ case HNBU_LEGOFDMBW205GPO: ++ for (j = 0; j < 6; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_legofdmbw205gpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS2GPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs2gpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GLPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5glpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GMPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5gmpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GHPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5ghpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS32PO: ++ varbuf_append(&b, vstr_mcs32po, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_LEG40DUPPO: ++ varbuf_append(&b, vstr_legofdm40duppo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_CUSTOM1: ++ varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) + ++ (cis[i + 3] << 16) + (cis[i + 2] << 8) + ++ cis[i + 1])); ++ break; ++ ++#if defined(BCMCCISSR3) ++ case HNBU_SROM3SWRGN: ++ if (tlen >= 73) { ++ uint16 srom[35]; ++ uint8 srev = cis[i + 1 + 70]; ++ ASSERT(srev == 3); ++ /* make tuple value 16-bit aligned and parse it */ ++ bcopy(&cis[i + 1], srom, sizeof(srom)); ++ _initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b); ++ /* 2.4G antenna gain is included in SROM */ ++ ag_init = TRUE; ++ /* Ethernet MAC address is included in SROM */ ++ eabuf[0] = 0; ++ boardnum = -1; ++ } ++ /* create extra variables */ ++ if (tlen >= 75) ++ varbuf_append(&b, vstr_vendid, ++ (cis[i + 1 + 73] << 8) + ++ cis[i + 1 + 72]); ++ if (tlen >= 77) ++ varbuf_append(&b, vstr_devid, ++ (cis[i + 1 + 75] << 8) + ++ cis[i + 1 + 74]); ++ if (tlen >= 79) ++ varbuf_append(&b, vstr_xtalfreq, ++ (cis[i + 1 + 77] << 8) + ++ cis[i + 1 + 76]); ++ break; ++#endif ++ ++ case HNBU_CCKFILTTYPE: ++ varbuf_append(&b, vstr_cckdigfilttype, ++ (cis[i + 1])); ++ break; ++ ++ case HNBU_TEMPTHRESH: ++ varbuf_append(&b, vstr_tempthresh, ++ (cis[i + 1])); ++ /* period in msb nibble */ ++ varbuf_append(&b, vstr_temps_period, ++ (cis[i + 2] >> 4)); ++ /* hysterisis in lsb nibble */ ++ varbuf_append(&b, vstr_temp_hysteresis, ++ (cis[i + 2] & 0xF)); ++ if (tlen >= 4) ++ varbuf_append(&b, vstr_tempoffset, ++ (cis[i + 3])); ++ if (tlen >= 5) { ++ varbuf_append(&b, vstr_temp_corrx, ++ (cis[i + 4] >> 2)); ++ varbuf_append(&b, vstr_tempsense_option, ++ (cis[i + 4] & 0x3)); ++ } ++ if (tlen >= 6) ++ varbuf_append(&b, vstr_phycal_tempdelta, ++ (cis[i + 5])); ++ break; ++ ++ case HNBU_FEM_CFG: ++ /* fem_cfg1 */ ++ varbuf_append(&b, vstr_tssiposslopeg, 2, ++ (cis[i + 1] & 0x1)); ++ varbuf_append(&b, vstr_epagaing, 2, ++ (cis[i + 1] & 0xe) >> 1); ++ varbuf_append(&b, vstr_pdgaing, 2, ++ ((cis[i + 2] & 0x1) << 8) + ++ ((cis[i + 1] & 0xf0) >> 4)); ++ varbuf_append(&b, vstr_tworangetssi, 2, ++ (cis[i + 2] & 0x2) >> 1); ++ varbuf_append(&b, vstr_papdcap, 2, ++ (cis[i + 2] & 0x4) >> 2); ++ varbuf_append(&b, vstr_femctrl, ++ (cis[i + 2] & 0xf8) >> 3); ++ /* fem_cfg2 */ ++ varbuf_append(&b, vstr_tssiposslopeg, 5, ++ (cis[i + 3] & 0x1)); ++ varbuf_append(&b, vstr_epagaing, 5, ++ (cis[i + 3] & 0xe) >> 1); ++ varbuf_append(&b, vstr_pdgaing, 5, ++ ((cis[i + 4] & 0x1) << 8) + ++ ((cis[i + 3] & 0xf0) >> 4)); ++ varbuf_append(&b, vstr_tworangetssi, 2, ++ (cis[i + 4] & 0x2) >> 1); ++ varbuf_append(&b, vstr_papdcap, 5, ++ (cis[i + 4] & 0x4) >> 2); ++ varbuf_append(&b, vstr_gainctrlsph, ++ (cis[i + 4] & 0xf8) >> 3); ++ break; ++ ++ case HNBU_ACPA_C0: ++ { ++ const int a = 0; ++ ++ varbuf_append(&b, vstr_subband5gver, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7], ++ (cis[i + 10] << 8) + cis[i + 9]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 11] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 11] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 11] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 12] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 12] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 12] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 13], ++ cis[i + 14], ++ cis[i + 15], ++ cis[i + 16]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37], ++ (cis[i + 40] << 8) + cis[i + 39]); ++ break; ++ } ++ ++ case HNBU_ACPA_C1: ++ { ++ const int a = 1; ++ ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 9] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 9] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 9] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 10] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 10] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 10] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 11], ++ cis[i + 12], ++ cis[i + 13], ++ cis[i + 14]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 16] << 8) + cis[i + 15], ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37]); ++ break; ++ } ++ ++ case HNBU_ACPA_C2: ++ { ++ const int a = 2; ++ ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 9] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 9] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 9] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 10] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 10] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 10] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 11], ++ cis[i + 12], ++ cis[i + 13], ++ cis[i + 14]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 16] << 8) + cis[i + 15], ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37]); ++ break; ++ } ++ ++ case HNBU_MEAS_PWR: ++ varbuf_append(&b, vstr_measpower, cis[i + 1]); ++ varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2])); ++ varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3])); ++ varbuf_append(&b, vstr_rawtempsense, ++ ((cis[i + 5] & 0x1) << 8) + cis[i + 4]); ++ break; ++ ++ case HNBU_ACPPR_2GPO: ++ varbuf_append(&b, vstr_dot11agofdmhrbw202gpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdmlrbw202gpo, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ break; ++ ++ case HNBU_ACPPR_5GPO: ++ varbuf_append(&b, vstr_mcsbw805glpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_mcsbw1605glpo, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_mcsbw805gmpo, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_mcsbw1605gmpo, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_mcsbw805ghpo, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ varbuf_append(&b, vstr_mcsbw1605ghpo, ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_mcslr5rlpo, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_mcslr5gmpo, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_mcslr5ghpo, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ break; ++ ++ case HNBU_ACPPR_SBPO: ++ varbuf_append(&b, vstr_sb20in40rrpo, 'h', ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l', ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l', ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm', ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm', ++ (cis[i + 10] << 8) + cis[i + 9]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h', ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h', ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_sb20in40rrpo, 'l', ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l', ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l', ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm', ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm', ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h', ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h', ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_dot11agduprpo, 'h', ++ (cis[i + 30] << 8) + cis[i + 24]); ++ varbuf_append(&b, vstr_dot11agduprpo, 'l', ++ (cis[i + 32] << 8) + cis[i + 26]); ++ break; ++ ++ case HNBU_NOISELVL: ++ /* noiselvl2g */ ++ varbuf_append(&b, vstr_noiselvl2ga, 0, ++ (cis[i + 1] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl2ga, 1, ++ ((cis[i + 2] & 0x3) << 4) + ++ ((cis[i + 1] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl2ga, 2, ++ (cis[i + 2] & 0x7c) >> 2); ++ /* noiselvl5gl */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 0, ++ (cis[i + 3] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 1, ++ ((cis[i + 4] & 0x3) << 4) + ++ ((cis[i + 3] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 2, ++ (cis[i + 4] & 0x7c) >> 2); ++ /* noiselvl5gm */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 0, ++ (cis[i + 5] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 1, ++ ((cis[i + 6] & 0x3) << 4) + ++ ((cis[i + 5] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 2, ++ (cis[i + 6] & 0x7c) >> 2); ++ /* noiselvl5gh */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 0, ++ (cis[i + 7] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 1, ++ ((cis[i + 8] & 0x3) << 4) + ++ ((cis[i + 7] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 2, ++ (cis[i + 8] & 0x7c) >> 2); ++ /* noiselvl5gu */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 0, ++ (cis[i + 9] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 1, ++ ((cis[i + 10] & 0x3) << 4) + ++ ((cis[i + 9] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 2, ++ (cis[i + 10] & 0x7c) >> 2); ++ break; ++ ++ case HNBU_RXGAIN_ERR: ++ varbuf_append(&b, vstr_rxgainerr2g, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_rxgainerr5g, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7], ++ (cis[i + 10] << 8) + cis[i + 9]); ++ break; ++ ++ case HNBU_AGBGA: ++ varbuf_append(&b, vstr_agbg, 0, cis[i + 1]); ++ varbuf_append(&b, vstr_agbg, 1, cis[i + 2]); ++ varbuf_append(&b, vstr_agbg, 2, cis[i + 3]); ++ varbuf_append(&b, vstr_aga, 3, cis[i + 4]); ++ varbuf_append(&b, vstr_aga, 4, cis[i + 5]); ++ varbuf_append(&b, vstr_aga, 5, cis[i + 6]); ++ break; ++ ++ case HNBU_UUID: ++ { ++ /* uuid format 12345678-1234-5678-1234-567812345678 */ ++ ++ char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */ ++ ++ snprintf(uuidstr, sizeof(uuidstr), ++ "%02X%02X%02X%02X-%02X%02X-%02X%02X-" ++ "%02X%02X-%02X%02X%02X%02X%02X%02X", ++ cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8], ++ cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12], ++ cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]); ++ ++ varbuf_append(&b, vstr_uuid, uuidstr); ++ break; ++ ++ } ++#endif /* !BCM_BOOTLOADER */ ++ } ++ ++ break; ++ } ++ i += tlen; ++ } while (tup != CISTPL_END); ++ } ++ ++ if (boardnum != -1) { ++ varbuf_append(&b, vstr_boardnum, boardnum); ++ } ++ ++ if (eabuf[0]) { ++ varbuf_append(&b, vstr_macaddr, eabuf); ++ } ++ ++#ifndef BCM_BOOTLOADER ++ /* if there is no antenna gain field, set default */ ++ if (getvar(NULL, "ag0") == NULL && ag_init == FALSE) { ++ varbuf_append(&b, vstr_ag, 0, 0xff); ++ } ++#endif ++ ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ varbuf_append(&b, vstr_end, NULL); ++#endif /* BCMUSBDEV_BMAC */ ++ ++ /* final nullbyte terminator */ ++ ASSERT(b.size >= 1); ++ *b.buf++ = '\0'; ++ ++ ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS); ++ err = initvars_table(osh, base, b.buf, vars, count); ++ ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ return err; ++} ++ ++/* set PCMCIA sprom command register */ ++static int ++sprom_cmd_pcmcia(osl_t *osh, uint8 cmd) ++{ ++ uint8 status = 0; ++ uint wait_cnt = 1000; ++ ++ /* write sprom command register */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1); ++ ++ /* wait status */ ++ while (wait_cnt--) { ++ OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1); ++ if (status & SROM_DONE) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/* read a word from the PCMCIA srom */ ++static int ++sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); ++ ++ /* do read */ ++ if (sprom_cmd_pcmcia(osh, SROM_READ)) ++ return 1; ++ ++ /* read data */ ++ data_h = data_l = 0; ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ *data = (data_h << 8) | data_l; ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* write a word to the PCMCIA srom */ ++static int ++sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); ++ ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); ++ ++ /* write data */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ /* do write */ ++ return sprom_cmd_pcmcia(osh, SROM_WRITE); ++} ++#endif ++ ++/* In chips with chipcommon rev 32 and later, the srom is in chipcommon, ++ * not in the bus cores. ++ */ ++static uint16 ++srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, uint16 data) ++{ ++ chipcregs_t *cc = (chipcregs_t *)ccregs; ++ uint wait_cnt = 1000; ++ ++ if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) { ++ W_REG(osh, &cc->sromaddress, wordoff * 2); ++ if (cmd == SRC_OP_WRITE) ++ W_REG(osh, &cc->sromdata, data); ++ } ++ ++ W_REG(osh, &cc->sromcontrol, SRC_START | cmd); ++ ++ while (wait_cnt--) { ++ if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0) ++ break; ++ } ++ ++ if (!wait_cnt) { ++ BS_ERROR(("%s: Command 0x%x timed out\n", __FUNCTION__, cmd)); ++ return 0xffff; ++ } ++ if (cmd == SRC_OP_READ) ++ return (uint16)R_REG(osh, &cc->sromdata); ++ else ++ return 0xffff; ++} ++ ++/* ++ * Read in and validate sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, ++ bool check_crc) ++{ ++ int err = 0; ++ uint i; ++ void *ccregs = NULL; ++ uint32 ccval = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* save current control setting */ ++ ccval = si_chipcontrl_read(sih); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { ++ /* Disable Ext PA lines to allow reading from SROM */ ++ si_chipcontrl_epa4331(sih, FALSE); ++ } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ si_chipcontrl_srom4360(sih, TRUE); ++ } ++ ++ /* read the sprom */ ++ for (i = 0; i < nwords; i++) { ++ ++ if (sih->ccrev > 31 && ISSIM_ENAB(sih)) { ++ /* use indirect since direct is too slow on QT */ ++ if ((sih->cccaps & CC_CAP_SROM) == 0) { ++ err = 1; ++ goto error; ++ } ++ ++ ccregs = (void *)((uint8 *)sprom - CC_SROM_OTP); ++ buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0); ++ ++ } else { ++ if (ISSIM_ENAB(sih)) ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); ++ ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); ++ } ++ ++ } ++ ++ /* bypass crc checking for simulation to allow srom hack */ ++ if (ISSIM_ENAB(sih)) { ++ goto error; ++ } ++ ++ if (check_crc) { ++ ++ if (buf[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0])); ++ err = 1; ++ goto error; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, nwords * 2); ++ if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ /* DBG only pci always read srom4 first, then srom8/9 */ ++ /* BS_ERROR(("%s: bad crc\n", __FUNCTION__)); */ ++ err = 1; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, nwords * 2); ++ } ++ ++error: ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ ++ /* Restore config after reading SROM */ ++ si_chipcontrl_restore(sih, ccval); ++ } ++ ++ return err; ++} ++ ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++static int ++otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz) ++{ ++ uint8 *otp; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int err = 0; ++ ++ ASSERT(bufsz <= OTP_SZ_MAX); ++ ++ if ((otp = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return BCME_ERROR; ++ } ++ ++ bzero(otp, OTP_SZ_MAX); ++ ++ err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz); ++ ++ if (err) { ++ MFREE(osh, otp, OTP_SZ_MAX); ++ return err; ++ } ++ ++ bcopy(otp, buf, bufsz); ++ ++ MFREE(osh, otp, OTP_SZ_MAX); ++ ++ /* Check CRC */ ++ if (buf[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0])); ++ return 1; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, bufsz); ++ if (hndcrc8((uint8 *)buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && ++ hndcrc8((uint8 *)buf, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ BS_ERROR(("%s: bad crc\n", __FUNCTION__)); ++ err = 1; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, bufsz); ++ ++ return err; ++} ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++ ++#if defined(WLTEST) || defined(BCMDBG) ++int ++srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write) ++{ ++ int err = 0, crc = 0; ++ uint8 *buf8; ++ ++ /* Check nbytes is not odd or too big */ ++ if ((nbytes & 1) || (nbytes > SROM_MAX)) ++ return 1; ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM4_WORDS * 2) ++ return BCME_BUFTOOSHORT; ++ else if (nbytes > SROM10_WORDS * 2) ++ return BCME_BUFTOOLONG; ++ ++ /* Verify signatures */ ++ if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (buf16[SROM8_SIGN] == SROM4_SIGNATURE) || ++ (buf16[SROM10_SIGN] == SROM4_SIGNATURE))) { ++ BS_ERROR(("%s: wrong signature SROM4_SIGN %x SROM8_SIGN %x SROM10_SIGN %x\n", ++ __FUNCTION__, buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN])); ++ return BCME_ERROR; ++ } ++ ++ /* Check CRC */ ++ if (buf16[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: invalid buf16[0] = 0x%x\n", __FUNCTION__, buf16[0])); ++ goto out; ++ } ++ ++ buf8 = (uint8*)buf16; ++ /* fixup the endianness and then calculate crc */ ++ htol16_buf(buf8, nbytes); ++ crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE); ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf8, nbytes); ++ if (nbytes == SROM10_WORDS * 2) ++ buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff); ++ else ++ buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff); ++ ++#ifdef BCMNVRAMW ++ /* Write the CRC back */ ++ if (write) ++ err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2); ++#endif /* BCMNVRAMW */ ++ ++out: ++ return write ? err : crc; ++} ++#endif ++ ++/* ++* Create variable table from memory. ++* Return 0 on success, nonzero on error. ++*/ ++static int ++BCMATTACHFN(initvars_table)(osl_t *osh, char *start, char *end, char **vars, uint *count) ++{ ++ int c = (int)(end - start); ++ ++ /* do it only when there is more than just the null string */ ++ if (c > 1) { ++ char *vp = MALLOC(osh, c); ++ ASSERT(vp != NULL); ++ if (!vp) ++ return BCME_NOMEM; ++ bcopy(start, vp, c); ++ *vars = vp; ++ *count = c; ++ } ++ else { ++ *vars = NULL; ++ *count = 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Find variables with from flash. 'base' points to the beginning ++ * of the table upon enter and to the end of the table upon exit when success. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len) ++{ ++ char *vp = *base; ++ char *flash; ++ int err; ++ char *s; ++ uint l, dl, copy_len; ++ char devpath[SI_DEVPATH_BUFSZ]; ++ char coded_name[SI_DEVPATH_BUFSZ] = {0}; ++ int path_len, coded_len, devid_len; ++ ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) ++ return BCME_NOMEM; ++ if ((err = nvram_getall(flash, NVRAM_SPACE))) ++ goto exit; ++ ++ /* create legacy devpath prefix */ ++ si_devpath(sih, devpath, sizeof(devpath)); ++ path_len = strlen(devpath); ++ ++ /* create coded devpath prefix */ ++ si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid"); ++ ++ /* coded_name now is 'xx:devid, eat ending 'devid' */ ++ /* to be 'xx:' */ ++ devid_len = strlen("devid"); ++ coded_len = strlen(coded_name); ++ if (coded_len > devid_len) { ++ coded_name[coded_len - devid_len] = '\0'; ++ coded_len -= devid_len; ++ } ++ else ++ coded_len = 0; ++ ++ /* grab vars with the prefix or previx in name */ ++ for (s = flash; s && *s; s += l + 1) { ++ l = strlen(s); ++ ++ /* skip non-matching variable */ ++ if (strncmp(s, devpath, path_len) == 0) ++ dl = path_len; ++ else if (coded_len && strncmp(s, coded_name, coded_len) == 0) ++ dl = coded_len; ++ else ++ continue; ++ ++ /* is there enough room to copy? */ ++ copy_len = l - dl + 1; ++ if (len < copy_len) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ ++ /* no prefix, just the name=value */ ++ strncpy(vp, &s[dl], copy_len); ++ vp += copy_len; ++ len -= copy_len; ++ } ++ ++ /* add null string as terminator */ ++ if (len < 1) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ *vp++ = '\0'; ++ ++ *base = vp; ++ ++exit: MFREE(osh, flash, NVRAM_SPACE); ++ return err; ++} ++ ++#if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) ++/* ++ * Initialize nonvolatile variable table from flash. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count) ++{ ++ osl_t *osh = si_osh(sih); ++ char *vp, *base; ++ int err; ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(vp != NULL); ++ if (!vp) ++ return BCME_NOMEM; ++ ++ if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0) ++ err = initvars_table(osh, base, vp, vars, count); ++ ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ ++ return err; ++} ++#endif ++ ++/* Parse SROM and create name=value pairs. 'srom' points to ++ * the SROM word array. 'off' specifies the offset of the ++ * first word 'srom' points to, which should be either 0 or ++ * SROM3_SWRG_OFF (full SROM or software region). ++ */ ++ ++static uint ++mask_shift(uint16 mask) ++{ ++ uint i; ++ for (i = 0; i < (sizeof(mask) << 3); i ++) { ++ if (mask & (1 << i)) ++ return i; ++ } ++ ASSERT(mask); ++ return 0; ++} ++ ++static uint ++mask_width(uint16 mask) ++{ ++ int i; ++ for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) { ++ if (mask & (1 << i)) ++ return (uint)(i - mask_shift(mask) + 1); ++ } ++ ASSERT(mask); ++ return 0; ++} ++ ++#ifdef BCMASSERT_SUPPORT ++static bool ++mask_valid(uint16 mask) ++{ ++ uint shift = mask_shift(mask); ++ uint width = mask_width(mask); ++ return mask == ((~0 << shift) & ~(~0 << (shift + width))); ++} ++#endif ++ ++static void ++BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b) ++{ ++ uint16 w; ++ uint32 val; ++ const sromvar_t *srv; ++ uint width; ++ uint flags; ++ uint32 sr = (1 << sromrev); ++ bool in_array = FALSE; ++ static char array_temp[256]; ++ uint array_curr = 0; ++ const char* array_name = NULL; ++ ++ varbuf_append(b, "sromrev=%d", sromrev); ++ ++ for (srv = pci_sromvars; srv->name != NULL; srv ++) { ++ const char *name; ++ static bool in_array = FALSE; ++ static char array_temp[256]; ++ static uint array_curr = 0; ++ static const char* array_name = NULL; ++ ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (srv->off < off) ++ continue; ++ ++ flags = srv->flags; ++ name = srv->name; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (flags & SRFL_NOVAR) ++ continue; ++ ++ if (flags & SRFL_ETHADDR) { ++ char eabuf[ETHER_ADDR_STR_LEN]; ++ struct ether_addr ea; ++ ++ ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff; ++ ea.octet[1] = srom[srv->off - off] & 0xff; ++ ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff; ++ ea.octet[3] = srom[srv->off + 1 - off] & 0xff; ++ ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff; ++ ea.octet[5] = srom[srv->off + 2 - off] & 0xff; ++ bcm_ether_ntoa(&ea, eabuf); ++ ++ varbuf_append(b, "%s=%s", name, eabuf); ++ } ++ else { ++ ASSERT(mask_valid(srv->mask)); ++ ASSERT(mask_width(srv->mask)); ++ ++ /* Start of an array */ ++ if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { ++ array_curr = 0; ++ array_name = (const char*)srv->name; ++ memset((void*)array_temp, 0, sizeof(array_temp)); ++ in_array = TRUE; ++ } ++ ++ w = srom[srv->off - off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ while (srv->flags & SRFL_MORE) { ++ srv ++; ++ ASSERT(srv->name != NULL); ++ ++ if (srv->off == 0 || srv->off < off) ++ continue; ++ ++ ASSERT(mask_valid(srv->mask)); ++ ASSERT(mask_width(srv->mask)); ++ ++ w = srom[srv->off - off]; ++ val += ((w & srv->mask) >> mask_shift(srv->mask)) << width; ++ width += mask_width(srv->mask); ++ } ++ ++ if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ /* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */ ++ if (sromrev <= 9 && srv->flags & SRFL_ARRAY) { ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ } ++ ++ if (in_array) { ++ int ret; ++ ++ if (flags & SRFL_PRHEX) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "0x%x,", val); ++ } else if ((flags & SRFL_PRSIGN) && ++ (val & (1 << (width - 1)))) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%d,", ++ (int)(val | (~0 << width))); ++ } else { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%u,", val); ++ } ++ ++ if (ret > 0) { ++ array_curr += ret; ++ } else { ++ BS_ERROR(("%s: array %s parsing error. buffer too short.\n", ++ __FUNCTION__, array_name)); ++ ASSERT(0); ++ ++ /* buffer too small, skip this param */ ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ in_array = FALSE; ++ continue; ++ } ++ ++ if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ ++ /* Remove the last ',' */ ++ array_temp[array_curr-1] = '\0'; ++ in_array = FALSE; ++ varbuf_append(b, "%s=%s", array_name, array_temp); ++ } ++ } else if (flags & SRFL_CCODE) { ++ if (val == 0) ++ varbuf_append(b, "ccode="); ++ else ++ varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff)); ++ } ++ /* LED Powersave duty cycle has to be scaled: ++ *(oncount >> 24) (offcount >> 8) ++ */ ++ else if (flags & SRFL_LEDDC) { ++ uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */ ++ (((val & 0xff)) << 8); /* offcount */ ++ varbuf_append(b, "leddc=%d", w32); ++ } ++ else if (flags & SRFL_PRHEX) ++ varbuf_append(b, "%s=0x%x", name, val); ++ else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) ++ varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width))); ++ else ++ varbuf_append(b, "%s=%u", name, val); ++ } ++ } ++ ++ if (sromrev >= 4) { ++ /* Do per-path variables */ ++ uint p, pb, psz, path_num; ++ ++ if (sromrev >= 11) { ++ pb = SROM11_PATH0; ++ psz = SROM11_PATH1 - SROM11_PATH0; ++ path_num = MAX_PATH_SROM_11; ++ } else if (sromrev >= 8) { ++ pb = SROM8_PATH0; ++ psz = SROM8_PATH1 - SROM8_PATH0; ++ path_num = MAX_PATH_SROM; ++ } else { ++ pb = SROM4_PATH0; ++ psz = SROM4_PATH1 - SROM4_PATH0; ++ path_num = MAX_PATH_SROM; ++ } ++ ++ for (p = 0; p < path_num; p++) { ++ for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) { ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (pb + srv->off < off) ++ continue; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (srv->flags & SRFL_NOVAR) ++ continue; ++ ++ /* Start of an array */ ++ if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { ++ array_curr = 0; ++ array_name = (const char*)srv->name; ++ memset((void*)array_temp, 0, sizeof(array_temp)); ++ in_array = TRUE; ++ } ++ ++ w = srom[pb + srv->off - off]; ++ ++ ASSERT(mask_valid(srv->mask)); ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ flags = srv->flags; ++ ++ /* Cheating: no per-path var is more than 1 word */ ++ ++ if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ if (in_array) { ++ int ret; ++ ++ if (flags & SRFL_PRHEX) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "0x%x,", val); ++ } else if ((flags & SRFL_PRSIGN) && ++ (val & (1 << (width - 1)))) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%d,", ++ (int)(val | (~0 << width))); ++ } else { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%u,", val); ++ } ++ ++ if (ret > 0) { ++ array_curr += ret; ++ } else { ++ BS_ERROR( ++ ("%s: array %s parsing error. buffer too short.\n", ++ __FUNCTION__, array_name)); ++ ASSERT(0); ++ ++ /* buffer too small, skip this param */ ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ in_array = FALSE; ++ continue; ++ } ++ ++ if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ ++ /* Remove the last ',' */ ++ array_temp[array_curr-1] = '\0'; ++ in_array = FALSE; ++ varbuf_append(b, "%s%d=%s", ++ array_name, p, array_temp); ++ } ++ } else if (srv->flags & SRFL_PRHEX) ++ varbuf_append(b, "%s%d=0x%x", srv->name, p, val); ++ else ++ varbuf_append(b, "%s%d=%d", srv->name, p, val); ++ } ++ pb += psz; ++ } ++ } ++} ++ ++/* ++ * Initialize nonvolatile variable table from sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_srom_pci)(si_t *sih, void *curmap, char **vars, uint *count) ++{ ++ uint16 *srom, *sromwindow; ++ uint8 sromrev = 0; ++ uint32 sr; ++ varbuf_t b; ++ char *vp, *base = NULL; ++ osl_t *osh = si_osh(sih); ++ bool flash = FALSE; ++ int err = 0; ++ ++ /* ++ * Apply CRC over SROM content regardless SROM is present or not, ++ * and use variable sromrev's existance in flash to decide ++ * if we should return an error when CRC fails or read SROM variables ++ * from flash. ++ */ ++ srom = MALLOC(osh, SROM_MAX); ++ ASSERT(srom != NULL); ++ if (!srom) ++ return -2; ++ ++ sromwindow = (uint16 *)SROM_OFFSET(sih); ++ if (si_is_sprom_available(sih)) { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM11_WORDS, TRUE); ++ ++ if (err == 0) { ++ if (srom[SROM11_SIGN] == SROM11_SIGNATURE) /* srom 11 */ ++ sromrev = srom[SROM11_CRCREV] & 0xff; ++ } else { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM4_WORDS, TRUE); ++ ++ if (err == 0) { ++ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4 */ ++ (srom[SROM8_SIGN] == SROM4_SIGNATURE) ) { /* srom 8, 9 */ ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++ } else { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, ++ srom, SROM_WORDS, TRUE); ++ ++ if (err == 0) { ++ /* srom is good and is rev < 4 */ ++ /* top word of sprom contains version and crc8 */ ++ sromrev = srom[SROM_CRCREV] & 0xff; ++ /* bcm4401 sroms misprogrammed */ ++ if (sromrev == 0x10) ++ sromrev = 1; ++ } ++ } ++ } ++ } ++ ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++ /* Use OTP if SPROM not available */ ++ else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) { ++ /* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */ ++ if (srom[SROM11_SIGN] == SROM11_SIGNATURE) ++ sromrev = srom[SROM11_CRCREV] & 0xff; ++ else if (srom[SROM10_SIGN] == SROM10_SIGNATURE) ++ sromrev = srom[SROM10_CRCREV] & 0xff; ++ else ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++ else { ++ err = 1; ++ BS_ERROR(("Neither SPROM nor OTP has valid image\n")); ++ } ++ ++ BS_ERROR(("srom rev:%d\n", sromrev)); ++ ++ ++ /* We want internal/wltest driver to come up with default sromvars so we can ++ * program a blank SPROM/OTP. ++ */ ++ if (err) { ++ char *value; ++ uint32 val; ++ val = 0; ++ BCM_REFERENCE(val); ++ ++ if ((value = si_getdevpathvar(sih, "sromrev"))) { ++ sromrev = (uint8)bcm_strtoul(value, NULL, 0); ++ flash = TRUE; ++ goto varscont; ++ } ++ ++ BS_ERROR(("%s, SROM CRC Error\n", __FUNCTION__)); ++ ++#ifndef DONGLEBUILD ++ if ((value = si_getnvramflvar(sih, "sromrev"))) { ++ err = 0; ++ goto errout; ++ } ++#endif ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++ val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ if ((si_is_sprom_available(sih) && srom[0] == 0xffff) || ++ (val & SPROM_OTPIN_USE)) { ++ vp = base = mfgsromvars; ++ ++ if (defvarslen == 0) { ++ BS_ERROR(("No nvm file, use generic default (for programming" ++ " SPROM/OTP only)\n")); ++ ++ if (((sih->chip == BCM4331_CHIP_ID) || ++ (sih->chip == BCM43431_CHIP_ID)) && ++ (sih->chiprev < 3)) { ++ ++ defvarslen = srom_vars_len(defaultsromvars_4331); ++ bcopy(defaultsromvars_4331, vp, defvarslen); ++ ++ } else { ++ /* For 4311 A1 there is no signature to indicate that OTP is ++ * programmed, so can't really verify the OTP is ++ * unprogrammed or a bad OTP. ++ */ ++ if (sih->chip == BCM4311_CHIP_ID) { ++ const char *devid = "devid=0x4311"; ++ const size_t devid_strlen = strlen(devid); ++ BS_ERROR(("setting the devid to be 4311\n")); ++ bcopy(devid, vp, devid_strlen + 1); ++ vp += devid_strlen + 1; ++ } ++ defvarslen = srom_vars_len(defaultsromvars_wltest); ++ bcopy(defaultsromvars_wltest, vp, defvarslen); ++ } ++ } else { ++ BS_ERROR(("Use nvm file as default\n")); ++ } ++ ++ vp += defvarslen; ++ /* add final null terminator */ ++ *vp++ = '\0'; ++ ++ BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen)); ++ goto varsdone; ++ ++ } else if ((((sih->chip == BCM4331_CHIP_ID) || ++ (sih->chip == BCM43431_CHIP_ID)) && ++ (sih->chiprev < 3)) || (sih->chip == BCM4360_CHIP_ID) || ++ (sih->chip == BCM43460_CHIP_ID) || ++ (sih->chip == BCM4352_CHIP_ID)) { ++ base = vp = mfgsromvars; ++ ++ if ((sih->chip == BCM4360_CHIP_ID) || ++ (sih->chip == BCM43460_CHIP_ID) || ++ (sih->chip == BCM4352_CHIP_ID)) ++ BS_ERROR(("4360 BOOT w/o SPROM or OTP\n")); ++ else ++ BS_ERROR(("4331 BOOT w/o SPROM or OTP\n")); ++ ++ defvarslen = srom_vars_len(defaultsromvars_4331); ++ bcopy(defaultsromvars_4331, vp, defvarslen); ++ vp += defvarslen; ++ *vp++ = '\0'; ++ goto varsdone; ++ } else ++#endif ++ { ++ err = -1; ++ goto errout; ++ } ++ } ++ ++varscont: ++ /* Bitmask for the sromrev */ ++ sr = 1 << sromrev; ++ ++ /* srom version check: Current valid versions: 1-5, 8-11, SROM_MAXREV */ ++ if ((sr & 0xf3e) == 0) { ++ BS_ERROR(("Invalid SROM rev %d\n", sromrev)); ++ err = -2; ++ goto errout; ++ } ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(vp != NULL); ++ if (!vp) { ++ err = -2; ++ goto errout; ++ } ++ ++ /* read variables from flash */ ++ if (flash) { ++ if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS))) ++ goto errout; ++ goto varsdone; ++ } ++ ++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS); ++ ++ /* parse SROM into name=value pairs. */ ++ _initvars_srom_pci(sromrev, srom, 0, &b); ++ ++ ++ /* final nullbyte terminator */ ++ ASSERT(b.size >= 1); ++ vp = b.buf; ++ *vp++ = '\0'; ++ ++ ASSERT((vp - base) <= MAXSZ_NVRAM_VARS); ++ ++varsdone: ++ err = initvars_table(osh, base, vp, vars, count); ++ ++errout: ++/* BCMHOSTVARS are enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++ if (base && (base != mfgsromvars)) ++#else ++ if (base) ++#endif ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ ++ MFREE(osh, srom, SROM_MAX); ++ return err; ++} ++ ++/* ++ * Read the cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_pcmcia)(si_t *sih, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis = NULL; ++ int rc; ++ uint data_sz; ++ ++ data_sz = (sih->buscorerev == 1) ? SROM_MAX : CIS_SIZE; ++ ++ if ((cis = MALLOC(osh, data_sz)) == NULL) ++ return (-2); ++ ++ if (sih->buscorerev == 1) { ++ if (srom_read(sih, PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis, ++ TRUE)) { ++ MFREE(osh, cis, data_sz); ++ return (-1); ++ } ++ /* fix up endianess for 16-bit data vs 8-bit parsing */ ++ htol16_buf((uint16 *)cis, data_sz); ++ } else ++ OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz); ++ ++ rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count); ++ ++ MFREE(osh, cis, data_sz); ++ ++ return (rc); ++} ++ ++ ++#ifdef BCMSPI ++/* ++ * Read the SPI cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_spi)(osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis; ++ int rc; ++ ++#if defined(NDIS) && !defined(UNDER_CE) ++ uint8 cisd[SBSDIO_CIS_SIZE_LIMIT]; ++ cis = (uint8*)cisd; ++#else ++ if ((cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) { ++ return -1; ++ } ++#endif /* defined(NDIS) && (!defined(UNDER_CE)) */ ++ ++ bzero(cis, SBSDIO_CIS_SIZE_LIMIT); ++ ++ if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) { ++#if defined(NDIS) && !defined(UNDER_CE) ++ /* nothing to do */ ++#else ++ MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); ++#endif /* defined(NDIS) && (!defined(UNDER_CE)) */ ++ return -2; ++ } ++ ++ rc = srom_parsecis(osh, &cis, SDIO_FUNC_1, vars, count); ++ ++#if defined(NDIS) && !defined(UNDER_CE) ++ /* nothing to do here */ ++#else ++ MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); ++#endif ++ ++ return (rc); ++} ++#endif /* BCMSPI */ ++ ++#if defined(BCMUSBDEV) ++/* Return sprom size in 16-bit words */ ++uint ++srom_size(si_t *sih, osl_t *osh) ++{ ++ uint size = 0; ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint32 origidx; ++ sdpcmd_regs_t *pcmregs; ++ bool wasup; ++ ++ origidx = si_coreidx(sih); ++ pcmregs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!pcmregs) ++ pcmregs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(pcmregs); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ /* not worry about earlier core revs */ ++ /* valid for only pcmcia core */ ++ if (si_coreid(sih) == PCMCIA_CORE_ID) ++ if (si_corerev(sih) < 8) ++ goto done; ++ ++ ++ switch (SI_PCMCIA_READ(osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) { ++ case 1: ++ size = 256; /* SROM_INFO == 1 means 4kbit */ ++ break; ++ case 2: ++ size = 1024; /* SROM_INFO == 2 means 16kbit */ ++ break; ++ default: ++ break; ++ } ++ ++ done: ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ } ++ return size; ++} ++#endif ++ ++/* ++ * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at ++ * the same time, but only because all of the code is in attach functions and not in ROM. ++ */ ++ ++#if defined(BCMUSBDEV_ENABLED) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++/* ++ * Read the USB cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int rc = BCME_OK; ++ ++ if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return -1; ++ } ++ ++ bzero(cis, OTP_SZ_MAX); ++ ++ if (otp_read_region(sih, OTP_SW_RGN, (uint16 *)cis, &sz)) { ++ BS_ERROR(("%s: OTP read SW region failure.\n*", __FUNCTION__)); ++ rc = -2; ++ } else { ++ BS_ERROR(("%s: OTP programmed. use OTP for srom vars\n*", __FUNCTION__)); ++ rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count); ++ } ++ ++ MFREE(osh, cis, OTP_SZ_MAX); ++ ++ return (rc); ++} ++ ++/* For driver(not bootloader), if nvram is not downloadable or missing, use default */ ++static int ++BCMATTACHFN(initvars_srom_si_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *varsz) ++{ ++ uint len; ++ char *base; ++ char *fakevars; ++ int rc = -1; ++ ++ base = fakevars = NULL; ++ len = 0; ++ switch (CHIPID(sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ fakevars = defaultsromvars_4322usb; ++ break; ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ /* check against real chipid instead of compile time flag */ ++ if (sih->chip == BCM43234_CHIP_ID) { ++ fakevars = defaultsromvars_43234usb; ++ } else if (sih->chip == BCM43235_CHIP_ID) { ++ fakevars = defaultsromvars_43235usb; ++ } else ++ fakevars = defaultsromvars_43236usb; ++ break; ++ ++ case BCM4319_CHIP_ID: ++ fakevars = defaultsromvars_4319usb; ++ break; ++ case BCM4360_CHIP_ID: ++ case BCM43460_CHIP_ID: ++ case BCM43526_CHIP_ID: ++ fakevars = defaultsromvars_4360usb; ++ break; ++ default: ++ ASSERT(0); ++ return rc; ++ } ++ ++#ifndef BCM_BMAC_VARS_APPEND ++ if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) { ++ /* Make OTP/SROM variables global */ ++ if (srvars_inited == FALSE) ++ nvram_append((void *)sih, *vars, *varsz); ++ return BCME_OK; ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++ /* NO OTP, if nvram downloaded, use it */ ++ if ((_varsz != 0) && (_vars != NULL)) { ++ len = _varsz + (strlen(vstr_end)); ++ base = MALLOC(osh, len + 2); /* plus 2 terminating \0 */ ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, len + 2); ++ ++ /* make a copy of the _vars, _vars is at the top of the memory, cannot append ++ * END\0\0 to it. copy the download vars to base, back of the terminating \0, ++ * then append END\0\0 ++ */ ++ bcopy((void *)_vars, base, _varsz); ++ /* backoff all the terminating \0s except the one the for the last string */ ++ len = _varsz; ++ while (!base[len - 1]) ++ len--; ++ len++; /* \0 for the last string */ ++ /* append END\0\0 to the end */ ++ bcopy((void *)vstr_end, (base + len), strlen(vstr_end)); ++ len += (strlen(vstr_end) + 2); ++ *vars = base; ++ *varsz = len; ++ ++ BS_ERROR(("%s USB nvram downloaded %d bytes\n", __FUNCTION__, _varsz)); ++ } else { ++ /* Fall back to fake srom vars if OTP not programmed */ ++ len = srom_vars_len(fakevars); ++ base = MALLOC(osh, (len + 1)); ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, (len + 1)); ++ bcopy(fakevars, base, len); ++ *(base + len) = '\0'; /* add final nullbyte terminator */ ++ *vars = base; ++ *varsz = len + 1; ++ BS_ERROR(("initvars_srom_usbdriver: faked nvram %d bytes\n", len)); ++ } ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) { ++ if (base) ++ MFREE(osh, base, (len + 1)); ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ /* Make OTP/SROM variables global */ ++ if (srvars_inited == FALSE) { ++ nvram_append((void *)sih, *vars, *varsz); ++ srvars_inited = TRUE; ++ } ++ return BCME_OK; ++ ++} ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++ ++#ifdef BCM_DONGLEVARS ++static int ++BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */ ++ uint sz = 0; /* srom size in bytes */ ++ void *oh = NULL; ++ int rc = BCME_OK; ++ ++ if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) { ++ /* Access OTP if it is present, powered on, and programmed */ ++ sz = otp_size(oh); ++ sel = 1; ++ } else if ((sz = srom_size(sih, osh)) != 0) { ++ /* Access the SPROM if it is present */ ++ sz <<= 1; ++ sel = 2; ++ } ++ ++ /* Read CIS in OTP/SPROM */ ++ if (sel != 0) { ++ uint16 *srom; ++ uint8 *body = NULL; ++ uint otpsz = sz; ++ ++ ASSERT(sz); ++ ++ /* Allocate memory */ ++ if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL) ++ return BCME_NOMEM; ++ ++ /* Read CIS */ ++ switch (sel) { ++ case 1: ++ rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz); ++ sz = otpsz; ++ body = (uint8 *)srom; ++ break; ++ case 2: ++ rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE); ++ /* sprom has 8 byte h/w header */ ++ body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET; ++ break; ++ default: ++ /* impossible to come here */ ++ ASSERT(0); ++ break; ++ } ++ ++ /* Parse CIS */ ++ if (rc == BCME_OK) { ++ /* each word is in host endian */ ++ htol16_buf((uint8 *)srom, sz); ++ ASSERT(body); ++ rc = srom_parsecis(osh, &body, SROM_CIS_SINGLE, vars, varsz); ++ } ++ ++ MFREE(osh, srom, sz); /* Clean up */ ++ ++ /* Make SROM variables global */ ++ if (rc == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ } ++ ++ return BCME_OK; ++} ++#endif /* #ifdef BCM_DONGLEVARS */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ ++ /* Bail out if we've dealt with OTP/SPROM before! */ ++ if (srvars_inited) ++ goto exit; ++ ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ /* read OTP or use faked var array */ ++ switch (CHIPID(sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ case BCM4319_CHIP_ID: ++ case BCM4360_CHIP_ID: ++ case BCM43460_CHIP_ID: ++ case BCM4352_CHIP_ID: ++ if (BCME_OK != initvars_srom_si_usbdriver(sih, osh, vars, varsz)) ++ goto exit; ++ return BCME_OK; ++ default: ++ UNUSED_PARAMETER(defaultsromvars_4322usb); ++ UNUSED_PARAMETER(defaultsromvars_43234usb); ++ UNUSED_PARAMETER(defaultsromvars_43235usb); ++ UNUSED_PARAMETER(defaultsromvars_43236usb); ++ UNUSED_PARAMETER(defaultsromvars_4319usb); ++ } ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++ ++#ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read OTP \ ++ or SROM */ ++ if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz)) ++ return BCME_ERROR; ++#endif ++ ++ /* update static local var to skip for next call */ ++ srvars_inited = TRUE; ++ ++exit: ++ /* Tell the caller there is no individual SROM variables */ ++ *vars = NULL; ++ *varsz = 0; ++ ++ /* return OK so the driver will load & use defaults if bad srom/otp */ ++ return BCME_OK; ++} ++ ++#elif defined(BCMSDIODEV_ENABLED) ++ ++#ifdef BCM_DONGLEVARS ++static uint8 BCMATTACHDATA(defcis4325)[] = { 0x20, 0x4, 0xd0, 0x2, 0x25, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4315)[] = { 0x20, 0x4, 0xd0, 0x2, 0x15, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4329)[] = { 0x20, 0x4, 0xd0, 0x2, 0x29, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4319)[] = { 0x20, 0x4, 0xd0, 0x2, 0x19, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4336)[] = { 0x20, 0x4, 0xd0, 0x2, 0x36, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4330)[] = { 0x20, 0x4, 0xd0, 0x2, 0x30, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis43237)[] = { 0x20, 0x4, 0xd0, 0x2, 0xe5, 0xa8, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4324)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4335)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff }; ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x05a1\0" ++ "boardrev=0x1102\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=26000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa\0" ++ "rssismc2g=0xb\0" ++ "rssisav2g=0x3\0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:06:c0:19\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio_hmb)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x058c\0" ++ "boardrev=0x1102\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=26000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa \0" ++ "rssismc2g=0xb \0" ++ "rssisav2g=0x3 \0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:06:c0:19\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio_usbsd)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x05a2\0" ++ "boardrev=0x1100\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=30000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa \0" ++ "rssismc2g=0xb \0" ++ "rssisav2g=0x3 \0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:08:90:00\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43237)[] = ++ "vendid=0x14e4\0" ++ "devid=0x4355\0" ++ "boardtype=0x0583\0" ++ "boardrev=0x1103\0" ++ "boardnum=0x1\0" ++ "boardflags=0x200\0" ++ "boardflags2=0\0" ++ "sromrev=8\0" ++ "macaddr=00:90:4c:51:a8:e4\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0xffff\0" ++ "opo=0x0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "pa0b0=0xfed1\0" ++ "pa0b1=0x15fd\0" ++ "pa0b2=0xfac2\0" ++ "pa0itssit=0x20\0" ++ "pa0maxpwr=0x4c\0" ++ "pa1b0=0xfecd\0" ++ "pa1b1=0x1497\0" ++ "pa1b2=0xfae3\0" ++ "pa1lob0=0xfe87\0" ++ "pa1lob1=0x1637\0" ++ "pa1lob2=0xfa8e\0" ++ "pa1hib0=0xfedc\0" ++ "pa1hib1=0x144b\0" ++ "pa1hib2=0xfb01\0" ++ "pa1itssit=0x3e\0" ++ "pa1maxpwr=0x40\0" ++ "pa1lomaxpwr=0x3a\0" ++ "pa1himaxpwr=0x3c\0" ++ "bxa2g=0x3\0" ++ "rssisav2g=0x7\0" ++ "rssismc2g=0xf\0" ++ "rssismf2g=0xf\0" ++ "bxa5g=0x3\0" ++ "rssisav5g=0x7\0" ++ "rssismc5g=0xf\0" ++ "rssismf5g=0xf\0" ++ "tri2g=0xff\0" ++ "tri5g=0xff\0" ++ "tri5gl=0xff\0" ++ "tri5gh=0xff\0" ++ "rxpo2g=0xff\0" ++ "rxpo5g=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0x0\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "cck2gpo=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x0\0" ++ "mcs2gpo5=0x0\0" ++ "mcs2gpo6=0x0\0" ++ "mcs2gpo7=0x0\0" ++ "mcs5gpo0=0x0\0" ++ "mcs5gpo1=0x0\0" ++ "mcs5gpo2=0x0\0" ++ "mcs5gpo3=0x0\0" ++ "mcs5gpo4=0x0\0" ++ "mcs5gpo5=0x0\0" ++ "mcs5gpo6=0x0\0" ++ "mcs5gpo7=0x0\0" ++ "mcs5glpo0=0x0\0" ++ "mcs5glpo1=0x0\0" ++ "mcs5glpo2=0x0\0" ++ "mcs5glpo3=0x0\0" ++ "mcs5glpo4=0x0\0" ++ "mcs5glpo5=0x0\0" ++ "mcs5glpo6=0x0\0" ++ "mcs5glpo7=0x0\0" ++ "mcs5ghpo0=0x0\0" ++ "mcs5ghpo1=0x0\0" ++ "mcs5ghpo2=0x0\0" ++ "mcs5ghpo3=0x0\0" ++ "mcs5ghpo4=0x0\0" ++ "mcs5ghpo5=0x0\0" ++ "mcs5ghpo6=0x0\0" ++ "mcs5ghpo7=0x0\0" ++ "cddpo=0x0\0" ++ "stbcpo=0x0\0" ++ "bw40po=0x0\0" ++ "bwduppo=0x0\0" ++ "maxp2ga0=0x4c\0" ++ "pa2gw0a0=0xfed1\0" ++ "pa2gw1a0=0x15fd\0" ++ "pa2gw2a0=0xfac2\0" ++ "maxp5ga0=0x3c\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xfeb0\0" ++ "pa5gw1a0=0x1491\0" ++ "pa5gw2a0=0xfaf8\0" ++ "pa5glw0a0=0xfeaa\0" ++ "pa5glw1a0=0x14b9\0" ++ "pa5glw2a0=0xfaf0\0" ++ "pa5ghw0a0=0xfec5\0" ++ "pa5ghw1a0=0x1439\0" ++ "pa5ghw2a0=0xfb18\0" ++ "maxp2ga1=0x4c\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xfed2\0" ++ "pa2gw1a1=0x15d9\0" ++ "pa2gw2a1=0xfac6\0" ++ "maxp5ga1=0x3a\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3a\0" ++ "pa5gw0a1=0xfebe\0" ++ "pa5gw1a1=0x1306\0" ++ "pa5gw2a1=0xfb63\0" ++ "pa5glw0a1=0xfece\0" ++ "pa5glw1a1=0x1361\0" ++ "pa5glw2a1=0xfb5f\0" ++ "pa5ghw0a1=0xfe9e\0" ++ "pa5ghw1a1=0x12ca\0" ++ "pa5ghw2a1=0xfb41\0" ++ "END\0"; ++ ++static int ++srom_load_nvram(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *varsz) ++{ ++ uint len = 0, base_len; ++ char *base; ++ char *fakevars; ++ ++ base = fakevars = NULL; ++ switch (CHIPID(sih->chip)) { ++ case BCM4319_CHIP_ID: ++ printf("load driver default for chip %x\n", CHIPID(sih->chip)); ++ fakevars = defaultsromvars_4319sdio; ++ if (si_cis_source(sih) == CIS_OTP) { ++ switch (srom_probe_boardtype(pcis, ciscnt)) { ++ case BCM94319SDHMB_SSID: ++ fakevars = defaultsromvars_4319sdio_hmb; ++ break; ++ case BCM94319USBSDB_SSID: ++ fakevars = defaultsromvars_4319sdio_usbsd; ++ break; ++ default: ++ fakevars = defaultsromvars_4319sdio; ++ break; ++ } ++ } ++ break; ++ case BCM43237_CHIP_ID: ++ printf("load driver default for chip %x\n", CHIPID(sih->chip)); ++ fakevars = defaultsromvars_43237; ++ break; ++ default: ++ printf("unknown chip %x\n", CHIPID(sih->chip)); ++ return BCME_ERROR; /* fakevars == NULL for switch default */ ++ } ++ ++ ++ /* NO OTP, if nvram downloaded, use it */ ++ if ((_varsz != 0) && (_vars != NULL)) { ++ len = _varsz + (strlen(vstr_end)); ++ base_len = len + 2; /* plus 2 terminating \0 */ ++ base = MALLOC(osh, base_len); ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, base_len); ++ ++ /* make a copy of the _vars, _vars is at the top of the memory, cannot append ++ * END\0\0 to it. copy the download vars to base, back of the terminating \0, ++ * then append END\0\0 ++ */ ++ bcopy((void *)_vars, base, _varsz); ++ /* backoff all the terminating \0s except the one the for the last string */ ++ len = _varsz; ++ while (!base[len - 1]) ++ len--; ++ len++; /* \0 for the last string */ ++ /* append END\0\0 to the end */ ++ bcopy((void *)vstr_end, (base + len), strlen(vstr_end)); ++ len += (strlen(vstr_end) + 2); ++ *vars = base; ++ *varsz = len; ++ ++ BS_ERROR(("%s nvram downloaded %d bytes\n", __FUNCTION__, _varsz)); ++ } else { ++ /* Fall back to fake srom vars if OTP not programmed */ ++ len = srom_vars_len(fakevars); ++ base = MALLOC(osh, (len + 1)); ++ base_len = len + 1; ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, base_len); ++ bcopy(fakevars, base, len); ++ *(base + len) = '\0'; /* add final nullbyte terminator */ ++ *vars = base; ++ *varsz = len + 1; ++ BS_ERROR(("srom_load_driver)default: faked nvram %d bytes\n", len)); ++ } ++ /* Parse the CIS */ ++ if ((srom_parsecis(osh, pcis, ciscnt, vars, varsz)) == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ MFREE(osh, base, base_len); ++ return BCME_OK; ++} ++ ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ int cis_src; ++ uint msz = 0; ++ uint sz = 0; ++ void *oh = NULL; ++ int rc = BCME_OK; ++ bool new_cisformat = FALSE; ++ ++ uint16 *cisbuf = NULL; ++ ++ /* # sdiod fns + common + extra */ ++ uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 }; ++ ++ uint ciss = 0; ++ uint8 *defcis; ++ uint hdrsz; ++ ++ /* Bail out if we've dealt with OTP/SPROM before! */ ++ if (srvars_inited) ++ goto exit; ++ ++ /* Initialize default and cis format count */ ++ switch (CHIPID(sih->chip)) { ++ case BCM4325_CHIP_ID: ciss = 3; defcis = defcis4325; hdrsz = 8; break; ++ case BCM4315_CHIP_ID: ciss = 3; defcis = defcis4315; hdrsz = 8; break; ++ case BCM4329_CHIP_ID: ciss = 4; defcis = defcis4329; hdrsz = 12; break; ++ case BCM4319_CHIP_ID: ciss = 3; defcis = defcis4319; hdrsz = 12; break; ++ case BCM4336_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break; ++ case BCM43362_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break; ++ case BCM4330_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM43237_CHIP_ID: ciss = 1; defcis = defcis43237; hdrsz = 4; break; ++ case BCM4324_CHIP_ID: ciss = 1; defcis = defcis4324; hdrsz = 4; break; ++ case BCM4314_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM4334_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM4335_CHIP_ID: ciss = 1; defcis = defcis4335; hdrsz = 4; break; ++ default: ++ BS_ERROR(("%s: Unknown chip 0x%04x\n", __FUNCTION__, sih->chip)); ++ return BCME_ERROR; ++ } ++ if (sih->ccrev >= 36) { ++ uint32 otplayout; ++ otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout), 0, 0); ++ if (otplayout & OTP_CISFORMAT_NEW) { ++ ciss = 1; ++ hdrsz = 2; ++ new_cisformat = TRUE; ++ } ++ else { ++ ciss = 3; ++ hdrsz = 12; ++ } ++ } ++ ++ cis_src = si_cis_source(sih); ++ switch (cis_src) { ++ case CIS_SROM: ++ sz = srom_size(sih, osh) << 1; ++ break; ++ case CIS_OTP: ++ if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW)) ++ sz = otp_size(oh); ++ break; ++ } ++ ++ if (sz != 0) { ++ if ((cisbuf = (uint16*)MALLOC(osh, sz)) == NULL) ++ return BCME_NOMEM; ++ msz = sz; ++ ++ switch (cis_src) { ++ case CIS_SROM: ++ rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE); ++ break; ++ case CIS_OTP: ++ sz >>= 1; ++ rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz); ++ sz <<= 1; ++ break; ++ } ++ ++ ASSERT(sz > hdrsz); ++ if (rc == BCME_OK) { ++ if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) { ++ MFREE(osh, cisbuf, msz); ++ cisbuf = NULL; ++ } else if (new_cisformat) { ++ cis[0] = (uint8*)(cisbuf + hdrsz); ++ } else { ++ cis[0] = (uint8*)cisbuf + hdrsz; ++ cis[1] = (uint8*)cisbuf + hdrsz + ++ (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) - ++ SBSDIO_CIS_BASE_COMMON; ++ cis[2] = (uint8*)cisbuf + hdrsz + ++ cisbuf[3] - SBSDIO_CIS_BASE_COMMON; ++ cis[3] = (uint8*)cisbuf + hdrsz + ++ cisbuf[4] - SBSDIO_CIS_BASE_COMMON; ++ ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz)); ++ ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz)); ++ ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) || ++ (ciss <= 3)); ++ } ++ } ++ } ++ ++ /* Use default if strapped to, or strapped source empty */ ++ if (cisbuf == NULL) { ++ ciss = 1; ++ cis[0] = defcis; ++ } ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ srom_load_nvram(sih, osh, cis, ciss, vars, varsz); ++#else ++ /* Parse the CIS */ ++ if (rc == BCME_OK) { ++ if ((rc = srom_parsecis(osh, cis, ciss, vars, varsz)) == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ /* Clean up */ ++ if (cisbuf != NULL) ++ MFREE(osh, cisbuf, msz); ++ ++ srvars_inited = TRUE; ++exit: ++ /* Tell the caller there is no individual SROM variables */ ++ *vars = NULL; ++ *varsz = 0; ++ ++ /* return OK so the driver will load & use defaults if bad srom/otp */ ++ return BCME_OK; ++} ++#else /* BCM_DONGLEVARS */ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ *vars = NULL; ++ *varsz = 0; ++ return BCME_OK; ++} ++#endif /* BCM_DONGLEVARS */ ++ ++#else /* !BCMUSBDEV && !BCMSDIODEV */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ /* Search flash nvram section for srom variables */ ++ return initvars_flash_si(sih, vars, varsz); ++} ++#endif ++ ++void ++srom_var_deinit(si_t *sih) ++{ ++ srvars_inited = FALSE; ++} ++ ++extern void _make_gcc_happy_about_unused_variabe_(void); ++void ++_make_gcc_happy_about_unused_variabe_(void) ++{ ++#if defined(BCMUSBDEV) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ UNUSED_PARAMETER(defaultsromvars_4322usb); ++ UNUSED_PARAMETER(defaultsromvars_43234usb); ++ UNUSED_PARAMETER(defaultsromvars_43235usb); ++ UNUSED_PARAMETER(defaultsromvars_43236usb); ++ UNUSED_PARAMETER(defaultsromvars_4319usb); ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++#endif /* BCMUSBDEV */ ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmutils.c b/drivers/bcmdrivers/gmac/src/shared/bcmutils.c +new file mode 100755 +index 0000000..9f45f68 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch new file mode 100644 index 00000000..4f055f3f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch @@ -0,0 +1,3259 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmutils.c +@@ -0,0 +1,3253 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Driver O/S-independent utility routines ++ * ++ * $Id: bcmutils.c 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#include ++#include ++#include ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++#include ++#else ++#include ++#endif ++#ifdef BCMDRIVER ++ ++#include ++#include ++#include ++#include ++ ++#else /* !BCMDRIVER */ ++ ++#include ++#include ++#include ++ ++#if defined(BCMEXTSUP) ++#include ++#endif ++ ++ ++#endif /* !BCMDRIVER */ ++ ++#if defined(_WIN32) || defined(NDIS) || defined(__vxworks) || defined(_CFE_) ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef BCMPERFSTATS ++#include ++#endif ++#include ++void *_bcmutils_dummy_fn = NULL; ++ ++#ifdef BCMDRIVER ++ ++#ifdef WLC_LOW ++/* nvram vars cache */ ++static char *nvram_vars = NULL; ++static int vars_len = -1; ++#endif /* WLC_LOW */ ++ ++int ++pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx) ++{ ++ int i, err = BCME_OK; ++ void *p; ++ int pktplen; ++ ++ ASSERT(pktp != NULL); ++ ASSERT(osh != NULL); ++ ASSERT(pplen != NULL); ++ ++ pktplen = *pplen; ++ ++ bzero(pktp, sizeof(pktpool_t)); ++ pktp->inited = TRUE; ++ pktp->istx = istx ? TRUE : FALSE; ++ pktp->plen = (uint16)plen; ++ *pplen = 0; ++ ++ pktp->maxlen = PKTPOOL_LEN_MAX; ++ if (pktplen > pktp->maxlen) ++ pktplen = pktp->maxlen; ++ ++ for (i = 0; i < pktplen; i++) { ++ p = PKTGET(osh, plen, pktp->istx); ++ if (p == NULL) { ++ /* Not able to allocate all requested pkts ++ * so just return what was actually allocated ++ * We can add to the pool later ++ */ ++ if (pktp->w == 0) ++ err = BCME_NOMEM; ++ ++ goto exit; ++ } ++ ++ PKTSETPOOL(osh, p, TRUE, pktp); ++ pktp->q[i] = p; ++ pktp->w++; ++ pktp->len++; ++#ifdef BCMDBG_POOL ++ pktp->dbg_q[pktp->dbg_qlen++].p = p; ++#endif ++ } ++ ++exit: ++ *pplen = pktp->w; ++ pktp->len++; /* Add one for end */ ++ return err; ++} ++ ++int ++pktpool_deinit(osl_t *osh, pktpool_t *pktp) ++{ ++ int i; ++ int cnt; ++ ++ ASSERT(osh != NULL); ++ ASSERT(pktp != NULL); ++ ++ cnt = pktp->len; ++ for (i = 0; i < cnt; i++) { ++ if (pktp->q[i] != NULL) { ++ PKTSETPOOL(osh, pktp->q[i], FALSE, NULL); ++ PKTFREE(osh, pktp->q[i], pktp->istx); ++ pktp->q[i] = NULL; ++ pktp->len--; ++ } ++#ifdef BCMDBG_POOL ++ if (pktp->dbg_q[i].p != NULL) ++ pktp->dbg_q[i].p = NULL; ++#endif ++ } ++ pktp->inited = FALSE; ++ ++ /* Are there still pending pkts? */ ++ ASSERT(pktpool_len(pktp) == 0); ++ ++ return 0; ++} ++ ++int ++pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal) ++{ ++ void *p; ++ int err = 0; ++ int len, psize, maxlen; ++ ++ ASSERT(pktpool_plen(pktp) != 0); ++ ++ maxlen = pktpool_maxlen(pktp); ++ psize = minimal ? (maxlen >> 2) : maxlen; ++ len = pktpool_len(pktp); ++ for (; len < psize; len++) { ++ p = PKTGET(osh, pktpool_plen(pktp), FALSE); ++ if (p == NULL) { ++ err = BCME_NOMEM; ++ break; ++ } ++ ++ if (pktpool_add(pktp, p) != BCME_OK) { ++ PKTFREE(osh, p, FALSE); ++ err = BCME_ERROR; ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++uint16 ++pktpool_avail(pktpool_t *pktp) ++{ ++ if (pktp->w == pktp->r) ++ return 0; ++ ++ return (pktp->w > pktp->r) ? (pktp->w - pktp->r) : ((pktp->len) - (pktp->r - pktp->w)); ++} ++ ++static void * ++pktpool_deq(pktpool_t *pktp) ++{ ++ void *p; ++ ++ if (pktp->r == pktp->w) ++ return NULL; ++ ++ p = pktp->q[pktp->r]; ++ ASSERT(p != NULL); ++ ++ pktp->q[pktp->r++] = NULL; ++ pktp->r %= (pktp->len); ++ ++ return p; ++} ++ ++static void ++pktpool_enq(pktpool_t *pktp, void *p) ++{ ++ uint16 next; ++ ++ ASSERT(p != NULL); ++ ++ next = (pktp->w + 1) % (pktp->len); ++ if (next == pktp->r) { ++ /* Should not happen; otherwise pkt leak */ ++ ASSERT(0); ++ return; ++ } ++ ++ ASSERT(pktp->q[pktp->w] == NULL); ++ ++ pktp->q[pktp->w] = p; ++ pktp->w = next; ++} ++ ++int ++pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb != NULL); ++ ++ i = pktp->cbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->cbs[i].cb == NULL); ++ pktp->cbs[i].cb = cb; ++ pktp->cbs[i].arg = arg; ++ pktp->cbcnt++; ++ ++ return 0; ++} ++ ++int ++pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb != NULL); ++ ++ i = pktp->ecbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->ecbs[i].cb == NULL); ++ pktp->ecbs[i].cb = cb; ++ pktp->ecbs[i].arg = arg; ++ pktp->ecbcnt++; ++ ++ return 0; ++} ++ ++static int ++pktpool_empty_notify(pktpool_t *pktp) ++{ ++ int i; ++ ++ pktp->empty = TRUE; ++ for (i = 0; i < pktp->ecbcnt; i++) { ++ ASSERT(pktp->ecbs[i].cb != NULL); ++ pktp->ecbs[i].cb(pktp, pktp->ecbs[i].arg); ++ } ++ pktp->empty = FALSE; ++ ++ return 0; ++} ++ ++#ifdef BCMDBG_POOL ++int ++pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb); ++ ++ i = pktp->dbg_cbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->dbg_cbs[i].cb == NULL); ++ pktp->dbg_cbs[i].cb = cb; ++ pktp->dbg_cbs[i].arg = arg; ++ pktp->dbg_cbcnt++; ++ ++ return 0; ++} ++ ++int pktpool_dbg_notify(pktpool_t *pktp); ++ ++int ++pktpool_dbg_notify(pktpool_t *pktp) ++{ ++ int i; ++ ++ for (i = 0; i < pktp->dbg_cbcnt; i++) { ++ ASSERT(pktp->dbg_cbs[i].cb); ++ pktp->dbg_cbs[i].cb(pktp, pktp->dbg_cbs[i].arg); ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_dbg_dump(pktpool_t *pktp) ++{ ++ int i; ++ ++ printf("pool len=%d maxlen=%d\n", pktp->dbg_qlen, pktp->maxlen); ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p); ++ printf("%d, p: 0x%x dur:%lu us state:%d\n", i, ++ pktp->dbg_q[i].p, pktp->dbg_q[i].dur/100, PKTPOOLSTATE(pktp->dbg_q[i].p)); ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats) ++{ ++ int i; ++ int state; ++ ++ bzero(stats, sizeof(pktpool_stats_t)); ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ state = PKTPOOLSTATE(pktp->dbg_q[i].p); ++ switch (state) { ++ case POOL_TXENQ: ++ stats->enq++; break; ++ case POOL_TXDH: ++ stats->txdh++; break; ++ case POOL_TXD11: ++ stats->txd11++; break; ++ case POOL_RXDH: ++ stats->rxdh++; break; ++ case POOL_RXD11: ++ stats->rxd11++; break; ++ case POOL_RXFILL: ++ stats->rxfill++; break; ++ case POOL_IDLE: ++ stats->idle++; break; ++ } ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_start_trigger(pktpool_t *pktp, void *p) ++{ ++ uint32 cycles, i; ++ ++ if (!PKTPOOL(NULL, p)) ++ return 0; ++ ++ OSL_GETCYCLES(cycles); ++ ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ if (pktp->dbg_q[i].p == p) { ++ pktp->dbg_q[i].cycles = cycles; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++int pktpool_stop_trigger(pktpool_t *pktp, void *p); ++int ++pktpool_stop_trigger(pktpool_t *pktp, void *p) ++{ ++ uint32 cycles, i; ++ ++ if (!PKTPOOL(NULL, p)) ++ return 0; ++ ++ OSL_GETCYCLES(cycles); ++ ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ if (pktp->dbg_q[i].p == p) { ++ if (pktp->dbg_q[i].cycles == 0) ++ break; ++ ++ if (cycles >= pktp->dbg_q[i].cycles) ++ pktp->dbg_q[i].dur = cycles - pktp->dbg_q[i].cycles; ++ else ++ pktp->dbg_q[i].dur = ++ (((uint32)-1) - pktp->dbg_q[i].cycles) + cycles + 1; ++ ++ pktp->dbg_q[i].cycles = 0; ++ break; ++ } ++ } ++ ++ return 0; ++} ++#endif /* BCMDBG_POOL */ ++ ++int ++pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp) ++{ ++ ASSERT(pktp); ++ pktp->availcb_excl = NULL; ++ return 0; ++} ++ ++int ++pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb) ++{ ++ int i; ++ ++ ASSERT(pktp); ++ ASSERT(pktp->availcb_excl == NULL); ++ for (i = 0; i < pktp->cbcnt; i++) { ++ if (cb == pktp->cbs[i].cb) { ++ pktp->availcb_excl = &pktp->cbs[i]; ++ break; ++ } ++ } ++ ++ if (pktp->availcb_excl == NULL) ++ return BCME_ERROR; ++ else ++ return 0; ++} ++ ++static int ++pktpool_avail_notify(pktpool_t *pktp) ++{ ++ int i, k, idx; ++ int avail; ++ ++ ASSERT(pktp); ++ if (pktp->availcb_excl != NULL) { ++ pktp->availcb_excl->cb(pktp, pktp->availcb_excl->arg); ++ return 0; ++ } ++ ++ k = pktp->cbcnt - 1; ++ for (i = 0; i < pktp->cbcnt; i++) { ++ avail = pktpool_avail(pktp); ++ ++ if (avail) { ++ if (pktp->cbtoggle) ++ idx = i; ++ else ++ idx = k--; ++ ++ ASSERT(pktp->cbs[idx].cb != NULL); ++ pktp->cbs[idx].cb(pktp, pktp->cbs[idx].arg); ++ } ++ } ++ ++ /* Alternate between filling from head or tail ++ */ ++ pktp->cbtoggle ^= 1; ++ ++ return 0; ++} ++ ++void * ++pktpool_get(pktpool_t *pktp) ++{ ++ void *p; ++ ++ p = pktpool_deq(pktp); ++ ++ if (p == NULL) { ++ /* Notify and try to reclaim tx pkts */ ++ if (pktp->ecbcnt) ++ pktpool_empty_notify(pktp); ++ ++ p = pktpool_deq(pktp); ++ } ++ ++ return p; ++} ++ ++void ++pktpool_free(pktpool_t *pktp, void *p) ++{ ++ ASSERT(p != NULL); ++ ++#ifdef BCMDBG_POOL ++ /* pktpool_stop_trigger(pktp, p); */ ++#endif ++ ++ pktpool_enq(pktp, p); ++ ++ if (pktp->emptycb_disable) ++ return; ++ ++ if (pktp->cbcnt) { ++ if (pktp->empty == FALSE) ++ pktpool_avail_notify(pktp); ++ } ++} ++ ++int ++pktpool_add(pktpool_t *pktp, void *p) ++{ ++ ASSERT(p != NULL); ++ ++ if (pktpool_len(pktp) == pktp->maxlen) ++ return BCME_RANGE; ++ ++ ASSERT(pktpool_plen(pktp) == PKTLEN(NULL, p)); /* pkts in pool have same length */ ++ PKTSETPOOL(NULL, p, TRUE, pktp); ++ ++ pktp->len++; ++ if (pktp->r > pktp->w) { ++ /* Add to tail */ ++ ASSERT(pktp->q[pktp->len - 1] == NULL); ++ pktp->q[pktp->len - 1] = p; ++ } else ++ pktpool_enq(pktp, p); ++ ++#ifdef BCMDBG_POOL ++ pktp->dbg_q[pktp->dbg_qlen++].p = p; ++#endif ++ ++ return 0; ++} ++ ++int ++pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen) ++{ ++ if (maxlen > PKTPOOL_LEN_MAX) ++ maxlen = PKTPOOL_LEN_MAX; ++ ++ /* if pool is already beyond maxlen, then just cap it ++ * since we currently do not reduce the pool len ++ * already allocated ++ */ ++ pktp->maxlen = (pktpool_len(pktp) > maxlen) ? pktpool_len(pktp) : maxlen; ++ ++ return pktp->maxlen; ++} ++ ++void ++pktpool_emptycb_disable(pktpool_t *pktp, bool disable) ++{ ++ ASSERT(pktp); ++ ++ pktp->emptycb_disable = disable; ++} ++ ++bool ++pktpool_emptycb_disabled(pktpool_t *pktp) ++{ ++ ASSERT(pktp); ++ return pktp->emptycb_disable; ++} ++ ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ if (len < 0) ++ len = 4096; /* "infinite" */ ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(PKTDATA(osh, p) + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++/* copy a buffer into a pkt buffer chain */ ++uint ++pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(buf, PKTDATA(osh, p) + offset, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++#ifdef NOTYET ++/* copy data from one pkt buffer (chain) to another */ ++uint ++pkt2pktcopy(osl_t *osh, void *p1, uint offs1, void *p2, uint offs2, int maxlen) ++{ ++ uint8 *dp1, *dp2; ++ uint len1, len2, copylen, totallen; ++ ++ for (; p1 && offs; p1 = PKTNEXT(osh, p1)) { ++ if (offs1 < (uint)PKTLEN(osh, p1)) ++ break; ++ offs1 -= PKTLEN(osh, p1); ++ } ++ for (; p2 && offs; p2 = PKTNEXT(osh, p2)) { ++ if (offs2 < (uint)PKTLEN(osh, p2)) ++ break; ++ offs2 -= PKTLEN(osh, p2); ++ } ++ ++ /* Heck w/it, only need the above for now */ ++} ++#endif /* NOTYET */ ++ ++ ++/* return total length of buffer chain */ ++uint BCMFASTPATH ++pkttotlen(osl_t *osh, void *p) ++{ ++ uint total; ++ int len; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) { ++ len = PKTLEN(osh, p); ++#ifdef MACOSX ++ if (len < 0) { ++ /* Bad packet length, just drop and exit */ ++ printf("wl: pkttotlen bad (%p,%d)\n", p, len); ++ break; ++ } ++#endif /* MACOSX */ ++ total += len; ++ } ++ ++ return (total); ++} ++ ++/* return the last buffer of chained pkt */ ++void * ++pktlast(osl_t *osh, void *p) ++{ ++ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) ++ ; ++ ++ return (p); ++} ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt(osl_t *osh, void *p) ++{ ++ uint cnt; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) ++ cnt++; ++ ++ return cnt; ++} ++ ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt_war(osl_t *osh, void *p) ++{ ++ uint cnt; ++ uint8 *pktdata; ++ uint len, remain, align64; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) { ++ cnt++; ++ len = PKTLEN(osh, p); ++ if (len > 128) { ++ pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */ ++ /* Check for page boundary straddle (2048B) */ ++ if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff)) ++ cnt++; ++ ++ align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */ ++ align64 = (64 - align64) & 0x3f; ++ len -= align64; /* bytes from aligned 64B to end */ ++ /* if aligned to 128B, check for MOD 128 between 1 to 4B */ ++ remain = len % 128; ++ if (remain > 0 && remain <= 4) ++ cnt++; /* add extra seg */ ++ } ++ } ++ ++ return cnt; ++} ++ ++uint8 * BCMFASTPATH ++pktdataoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint pkt_off = 0, len = 0; ++ uint8 *pdata = (uint8 *) PKTDATA(osh, p); ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ pdata = (uint8 *) PKTDATA(osh, p); ++ pkt_off = offset - len; ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return (uint8*) (pdata+pkt_off); ++} ++ ++ ++/* given a offset in pdata, find the pkt seg hdr */ ++void * ++pktoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint len = 0; ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return p; ++} ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty precedence ++ */ ++void * BCMFASTPATH ++pktq_penq(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ PKTSETLINK(q->tail, p); ++ else ++ q->head = p; ++ ++ q->tail = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_penq_head(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == NULL) ++ q->tail = p; ++ ++ PKTSETLINK(p, q->head); ++ q->head = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if (prev_p == NULL) ++ return NULL; ++ ++ if ((p = PKTLINK(prev_p)) == NULL) ++ return NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(prev_p, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_tail(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ return p; ++} ++ ++void ++pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ struct pktq_prec *q; ++ void *p, *prev = NULL; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ if (fn == NULL || (*fn)(p, arg)) { ++ bool head = (p == q->head); ++ if (head) ++ q->head = PKTLINK(p); ++ else ++ PKTSETLINK(prev, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ PKTFREE(osh, p, dir); ++ q->len--; ++ pq->len--; ++ p = (head ? q->head : PKTLINK(prev)); ++ } else { ++ prev = p; ++ p = PKTLINK(p); ++ } ++ } ++ ++ if (q->head == NULL) { ++ ASSERT(q->len == 0); ++ q->tail = NULL; ++ } ++} ++ ++bool BCMFASTPATH ++pktq_pdel(struct pktq *pq, void *pktbuf, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (!pktbuf) ++ return FALSE; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == pktbuf) { ++ if ((q->head = PKTLINK(pktbuf)) == NULL) ++ q->tail = NULL; ++ } else { ++ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) ++ ; ++ if (p == NULL) ++ return FALSE; ++ ++ PKTSETLINK(p, PKTLINK(pktbuf)); ++ if (q->tail == pktbuf) ++ q->tail = p; ++ } ++ ++ q->len--; ++ pq->len--; ++ PKTSETLINK(pktbuf, NULL); ++ return TRUE; ++} ++ ++void ++pktq_init(struct pktq *pq, int num_prec, int max_len) ++{ ++ int prec; ++ ++ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); ++ ++ /* pq is variable size; only zero out what's requested */ ++ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); ++ ++ pq->num_prec = (uint16)num_prec; ++ ++ pq->max = (uint16)max_len; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} ++ ++void ++pktq_set_max_plen(struct pktq *pq, int prec, int max_len) ++{ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (prec < pq->num_prec) ++ pq->q[prec].max = (uint16)max_len; ++} ++ ++void * BCMFASTPATH ++pktq_deq(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_deq_tail(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * ++pktq_peek(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].head); ++} ++ ++void * ++pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].tail); ++} ++ ++void ++pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ int prec; ++ ++ /* Optimize flush, if pktq len = 0, just return. ++ * pktq len of 0 means pktq's prec q's are all empty. ++ */ ++ if (pq->len == 0) { ++ return; ++ } ++ ++ for (prec = 0; prec < pq->num_prec; prec++) ++ pktq_pflush(osh, pq, prec, dir, fn, arg); ++ if (fn == NULL) ++ ASSERT(pq->len == 0); ++} ++ ++/* Return sum of lengths of a specific set of precedences */ ++int ++pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; ++ ++ len = 0; ++ ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; ++ ++ return len; ++} ++ ++/* Priority peek from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ { ++ return NULL; ++ } ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return p; ++} ++/* Priority dequeue from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0)) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++#endif /* BCMDRIVER */ ++ ++#if defined(BCMROMBUILD) ++const unsigned char BCMROMDATA(bcm_ctype)[] = { ++#else ++const unsigned char bcm_ctype[] = { ++#endif ++ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ ++ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, ++ _BCM_C, /* 8-15 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ ++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ ++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ ++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ ++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ ++ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, ++ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ ++ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, ++ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ ++ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ ++}; ++ ++ulong ++BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base) ++{ ++ ulong result, last_result = 0, value; ++ bool minus; ++ ++ minus = FALSE; ++ ++ while (bcm_isspace(*cp)) ++ cp++; ++ ++ if (cp[0] == '+') ++ cp++; ++ else if (cp[0] == '-') { ++ minus = TRUE; ++ cp++; ++ } ++ ++ if (base == 0) { ++ if (cp[0] == '0') { ++ if ((cp[1] == 'x') || (cp[1] == 'X')) { ++ base = 16; ++ cp = &cp[2]; ++ } else { ++ base = 8; ++ cp = &cp[1]; ++ } ++ } else ++ base = 10; ++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { ++ cp = &cp[2]; ++ } ++ ++ result = 0; ++ ++ while (bcm_isxdigit(*cp) && ++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { ++ result = result*base + value; ++ /* Detected overflow */ ++ if (result < last_result && !minus) ++ return (ulong)-1; ++ last_result = result; ++ cp++; ++ } ++ ++ if (minus) ++ result = (ulong)(-(long)result); ++ ++ if (endp) ++ *endp = DISCARD_QUAL(cp, char); ++ ++ return (result); ++} ++ ++int ++BCMROMFN(bcm_atoi)(const char *s) ++{ ++ return (int)bcm_strtoul(s, NULL, 10); ++} ++ ++/* return pointer to location of substring 'needle' in 'haystack' */ ++char * ++BCMROMFN(bcmstrstr)(const char *haystack, const char *needle) ++{ ++ int len, nlen; ++ int i; ++ ++ if ((haystack == NULL) || (needle == NULL)) ++ return DISCARD_QUAL(haystack, char); ++ ++ nlen = strlen(needle); ++ len = strlen(haystack) - nlen + 1; ++ ++ for (i = 0; i < len; i++) ++ if (memcmp(needle, &haystack[i], nlen) == 0) ++ return DISCARD_QUAL(&haystack[i], char); ++ return (NULL); ++} ++ ++char * ++BCMROMFN(bcmstrcat)(char *dest, const char *src) ++{ ++ char *p; ++ ++ p = dest + strlen(dest); ++ ++ while ((*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++char * ++BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size) ++{ ++ char *endp; ++ char *p; ++ ++ p = dest + strlen(dest); ++ endp = p + size; ++ ++ while (p != endp && (*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrtok ++* ++* Purpose: ++* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), ++* but allows strToken() to be used by different strings or callers at the same ++* time. Each call modifies '*string' by substituting a NULL character for the ++* first delimiter that is encountered, and updates 'string' to point to the char ++* after the delimiter. Leading delimiters are skipped. ++* ++* Parameters: ++* string (mod) Ptr to string ptr, updated by token. ++* delimiters (in) Set of delimiter characters. ++* tokdelim (out) Character that delimits the returned token. (May ++* be set to NULL if token delimiter is not required). ++* ++* Returns: Pointer to the next token found. NULL when no more tokens are found. ++***************************************************************************** ++*/ ++char * ++bcmstrtok(char **string, const char *delimiters, char *tokdelim) ++{ ++ unsigned char *str; ++ unsigned long map[8]; ++ int count; ++ char *nextoken; ++ ++ if (tokdelim != NULL) { ++ /* Prime the token delimiter */ ++ *tokdelim = '\0'; ++ } ++ ++ /* Clear control map */ ++ for (count = 0; count < 8; count++) { ++ map[count] = 0; ++ } ++ ++ /* Set bits in delimiter table */ ++ do { ++ map[*delimiters >> 5] |= (1 << (*delimiters & 31)); ++ } ++ while (*delimiters++); ++ ++ str = (unsigned char*)*string; ++ ++ /* Find beginning of token (skip over leading delimiters). Note that ++ * there is no token iff this loop sets str to point to the terminal ++ * null (*str == '\0') ++ */ ++ while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { ++ str++; ++ } ++ ++ nextoken = (char*)str; ++ ++ /* Find the end of the token. If it is not the end of the string, ++ * put a null there. ++ */ ++ for (; *str; str++) { ++ if (map[*str >> 5] & (1 << (*str & 31))) { ++ if (tokdelim != NULL) { ++ *tokdelim = *str; ++ } ++ ++ *str++ = '\0'; ++ break; ++ } ++ } ++ ++ *string = (char*)str; ++ ++ /* Determine if a token has been found. */ ++ if (nextoken == (char *) str) { ++ return NULL; ++ } ++ else { ++ return nextoken; ++ } ++} ++ ++ ++#define xToLower(C) \ ++ ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) ++ ++ ++/**************************************************************************** ++* Function: bcmstricmp ++* ++* Purpose: Compare to strings case insensitively. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstricmp(const char *s1, const char *s2) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ } ++ ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrnicmp ++* ++* Purpose: Compare to strings case insensitively, upto a max of 'cnt' ++* characters. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* cnt (in) Max characters to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstrnicmp(const char* s1, const char* s2, int cnt) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1 && cnt) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ cnt--; ++ } ++ ++ if (!cnt) return 0; ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ ++int ++BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea) ++{ ++ int i = 0; ++ char *ep; ++ ++ for (;;) { ++ ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); ++ p = ep; ++ if (!*p++ || i == 6) ++ break; ++ } ++ ++ return (i == 6); ++} ++ ++ ++#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) ++/* registry routine buffer preparation utility functions: ++ * parameter order is like strncpy, but returns count ++ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) ++ */ ++ulong ++wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) ++{ ++ ulong copyct = 1; ++ ushort i; ++ ++ if (abuflen == 0) ++ return 0; ++ ++ /* wbuflen is in bytes */ ++ wbuflen /= sizeof(ushort); ++ ++ for (i = 0; i < wbuflen; ++i) { ++ if (--abuflen == 0) ++ break; ++ *abuf++ = (char) *wbuf++; ++ ++copyct; ++ } ++ *abuf = '\0'; ++ ++ return copyct; ++} ++#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ ++ ++char * ++bcm_ether_ntoa(const struct ether_addr *ea, char *buf) ++{ ++ static const char hex[] = ++ { ++ '0', '1', '2', '3', '4', '5', '6', '7', ++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ++ }; ++ const uint8 *octet = ea->octet; ++ char *p = buf; ++ int i; ++ ++ for (i = 0; i < 6; i++, octet++) { ++ *p++ = hex[(*octet >> 4) & 0xf]; ++ *p++ = hex[*octet & 0xf]; ++ *p++ = ':'; ++ } ++ ++ *(p-1) = '\0'; ++ ++ return (buf); ++} ++ ++char * ++bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) ++{ ++ snprintf(buf, 16, "%d.%d.%d.%d", ++ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); ++ return (buf); ++} ++ ++#ifdef BCMDRIVER ++ ++void ++bcm_mdelay(uint ms) ++{ ++ uint i; ++ ++ for (i = 0; i < ms; i++) { ++ OSL_DELAY(1000); ++ } ++} ++ ++/* ++ * Search the name=value vars for a specific one and return its value. ++ * Returns NULL if not found. ++ */ ++char * ++getvar(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return NULL; ++#else ++ char *s; ++ int len; ++ ++ if (!name) ++ return NULL; ++ ++ len = strlen(name); ++ if (len == 0) ++ return NULL; ++ ++ /* first look in vars[] */ ++ for (s = vars; s && *s;) { ++ if ((bcmp(s, name, len) == 0) && (s[len] == '=') && (strlen(s)==len)) ++ return (&s[len+1]); ++ ++ while (*s++) ++ ; ++ } ++ ++ /* then query nvram */ ++ return (nvram_get(name)); ++#endif /* defined(_MINOSL_) */ ++} ++ ++/* ++ * Search the vars for a specific one and return its value as ++ * an integer. Returns 0 if not found. ++ */ ++int ++getintvar(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *val; ++ ++ if ((val = getvar(vars, name)) == NULL) ++ return (0); ++ ++ return (bcm_strtoul(val, NULL, 0)); ++#endif /* _MINOSL_ */ ++} ++ ++int ++getintvararray(char *vars, const char *name, int index) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *buf, *endp; ++ int i = 0; ++ int val = 0; ++ ++ if ((buf = getvar(vars, name)) == NULL) { ++ return (0); ++ } ++ ++ /* table values are always separated by "," or " " */ ++ while (*buf != '\0') { ++ val = bcm_strtoul(buf, &endp, 0); ++ if (i == index) { ++ return val; ++ } ++ buf = endp; ++ /* delimiter is ',' */ ++ if (*buf == ',') ++ buf++; ++ i++; ++ } ++ return 0; ++#endif /* _MINOSL_ */ ++} ++ ++int ++getintvararraysize(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *buf, *endp; ++ int count = 0; ++ int val = 0; ++ ++ if ((buf = getvar(vars, name)) == NULL) { ++ return (0); ++ } ++ ++ /* table values are always separated by "," or " " */ ++ while (*buf != '\0') { ++ val = bcm_strtoul(buf, &endp, 0); ++ buf = endp; ++ /* delimiter is ',' */ ++ if (*buf == ',') ++ buf++; ++ count++; ++ } ++ BCM_REFERENCE(val); ++ return count; ++#endif /* _MINOSL_ */ ++} ++ ++/* Search for token in comma separated token-string */ ++static int ++findmatch(const char *string, const char *name) ++{ ++ uint len; ++ char *c; ++ ++ len = strlen(name); ++ while ((c = strchr(string, ',')) != NULL) { ++ if (len == (uint)(c - string) && !strncmp(string, name, len)) ++ return 1; ++ string = c + 1; ++ } ++ ++ return (!strcmp(string, name)); ++} ++ ++/* Return gpio pin number assigned to the named pin ++ * ++ * Variable should be in format: ++ * ++ * gpio=pin_name,pin_name ++ * ++ * This format allows multiple features to share the gpio with mutual ++ * understanding. ++ * ++ * 'def_pin' is returned if a specific gpio is not defined for the requested functionality ++ * and if def_pin is not used by others. ++ */ ++uint ++getgpiopin(char *vars, char *pin_name, uint def_pin) ++{ ++ char name[] = "gpioXXXX"; ++ char *val; ++ uint pin; ++ ++ /* Go thru all possibilities till a match in pin name */ ++ for (pin = 0; pin < GPIO_NUMPINS; pin ++) { ++ snprintf(name, sizeof(name), "gpio%d", pin); ++ val = getvar(vars, name); ++ if (val && findmatch(val, pin_name)) ++ return pin; ++ } ++ ++ if (def_pin != GPIO_PIN_NOTDEFINED) { ++ /* make sure the default pin is not used by someone else */ ++ snprintf(name, sizeof(name), "gpio%d", def_pin); ++ if (getvar(vars, name)) { ++ def_pin = GPIO_PIN_NOTDEFINED; ++ } ++ } ++ return def_pin; ++} ++ ++ ++/* Return the WAN port number ++ * ++ * 0 is returned if no wanport is configured. ++ */ ++int ++getwanport(void) ++{ ++ char name[] = "wanport"; ++ int retval; ++ ++ retval = getintvar(NULL, name); ++ return retval; ++} ++ ++ ++/* Return the brcmtag variable ++ * ++ * 0 is returned if no wanport is configured. ++ */ ++int ++getbrcmtag(void) ++{ ++ char name[] = "brcmtag"; ++ int retval; ++ ++ retval = getintvar(NULL, name); ++ return retval; ++} ++ ++ ++#if defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) ++ ++#define LOGSIZE 256 /* should be power of 2 to avoid div below */ ++static struct { ++ uint cycles; ++ char *fmt; ++ uint a1; ++ uint a2; ++} logtab[LOGSIZE]; ++ ++/* last entry logged */ ++static uint logi = 0; ++/* next entry to read */ ++static uint readi = 0; ++#endif /* defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) */ ++ ++#ifdef BCMPERFSTATS ++void ++bcm_perf_enable() ++{ ++ BCMPERF_ENABLE_INSTRCOUNT(); ++ BCMPERF_ENABLE_ICACHE_MISS(); ++ BCMPERF_ENABLE_ICACHE_HIT(); ++} ++ ++/* WARNING: This routine uses OSL_GETCYCLES(), which can give unexpected results on ++ * modern speed stepping CPUs. Use bcmtslog() instead in combination with TSF counter. ++ */ ++void ++bcmlog(char *fmt, uint a1, uint a2) ++{ ++ static uint last = 0; ++ uint cycles, i; ++ OSL_GETCYCLES(cycles); ++ ++ i = logi; ++ ++ logtab[i].cycles = cycles - last; ++ logtab[i].fmt = fmt; ++ logtab[i].a1 = a1; ++ logtab[i].a2 = a2; ++ ++ logi = (i + 1) % LOGSIZE; ++ last = cycles; ++} ++ ++ ++void ++bcmstats(char *fmt) ++{ ++ static uint last = 0; ++ static uint32 ic_miss = 0; ++ static uint32 instr_count = 0; ++ uint32 ic_miss_cur; ++ uint32 instr_count_cur; ++ uint cycles, i; ++ ++ OSL_GETCYCLES(cycles); ++ BCMPERF_GETICACHE_MISS(ic_miss_cur); ++ BCMPERF_GETINSTRCOUNT(instr_count_cur); ++ ++ i = logi; ++ ++ logtab[i].cycles = cycles - last; ++ logtab[i].a1 = ic_miss_cur - ic_miss; ++ logtab[i].a2 = instr_count_cur - instr_count; ++ logtab[i].fmt = fmt; ++ ++ logi = (i + 1) % LOGSIZE; ++ ++ last = cycles; ++ instr_count = instr_count_cur; ++ ic_miss = ic_miss_cur; ++} ++ ++ ++void ++bcmdumplog(char *buf, int size) ++{ ++ char *limit; ++ int j = 0; ++ int num; ++ ++ limit = buf + size - 80; ++ *buf = '\0'; ++ ++ num = logi - readi; ++ ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* print in chronological order */ ++ ++ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); ++ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, ++ logtab[readi].a2); ++ buf += snprintf(buf, (limit - buf), "\n"); ++ } ++ ++} ++ ++ ++/* ++ * Dump one log entry at a time. ++ * Return index of next entry or -1 when no more . ++ */ ++int ++bcmdumplogent(char *buf, uint i) ++{ ++ bool hit; ++ ++ /* ++ * If buf is NULL, return the starting index, ++ * interpreting i as the indicator of last 'i' entries to dump. ++ */ ++ if (buf == NULL) { ++ i = ((i > 0) && (i < (LOGSIZE - 1))) ? i : (LOGSIZE - 1); ++ return ((logi - i) % LOGSIZE); ++ } ++ ++ *buf = '\0'; ++ ++ ASSERT(i < LOGSIZE); ++ ++ if (i == logi) ++ return (-1); ++ ++ hit = FALSE; ++ for (; (i != logi) && !hit; i = (i + 1) % LOGSIZE) { ++ if (logtab[i].fmt == NULL) ++ continue; ++ buf += sprintf(buf, "%d: %d\t", i, logtab[i].cycles); ++ buf += sprintf(buf, logtab[i].fmt, logtab[i].a1, logtab[i].a2); ++ buf += sprintf(buf, "\n"); ++ hit = TRUE; ++ } ++ ++ return (i); ++} ++ ++#endif /* BCMPERFSTATS */ ++ ++#if defined(BCMTSTAMPEDLOGS) ++/* Store a TSF timestamp and a log line in the log buffer */ ++void ++bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2) ++{ ++ uint i = logi; ++ bool use_delta = FALSE; ++ static uint32 last = 0; /* used only when use_delta is true */ ++ ++ logtab[i].cycles = tstamp; ++ if (use_delta) ++ logtab[i].cycles -= last; ++ ++ logtab[i].fmt = fmt; ++ logtab[i].a1 = a1; ++ logtab[i].a2 = a2; ++ ++ if (use_delta) ++ last = tstamp; ++ logi = (i + 1) % LOGSIZE; ++} ++ ++/* Print out a microsecond timestamp as "sec.ms.us " */ ++void ++bcmprinttstamp(uint32 ticks) ++{ ++ uint us, ms, sec; ++ ++ us = (ticks % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; ++ ms = ticks / TSF_TICKS_PER_MS; ++ sec = ms / 1000; ++ ms -= sec * 1000; ++ printf("%04u.%03u.%03u ", sec, ms, us); ++} ++ ++/* Print out the log buffer with timestamps */ ++void ++bcmprinttslogs(void) ++{ ++ int j = 0; ++ int num; ++ ++ num = logi - readi; ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* Format and print the log entries directly in chronological order */ ++ for (j = 0; j < num; readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ bcmprinttstamp(logtab[readi].cycles); ++ printf(logtab[readi].fmt, logtab[readi].a1, logtab[readi].a2); ++ printf("\n"); ++ } ++} ++ ++void ++bcmdumptslog(char *buf, int size) ++{ ++ char *limit; ++ int j = 0; ++ int num; ++ uint us, ms, sec; ++ ++ limit = buf + size - 80; ++ *buf = '\0'; ++ ++ num = logi - readi; ++ ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* print in chronological order */ ++ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ us = (logtab[readi].cycles % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; ++ ms = logtab[readi].cycles / TSF_TICKS_PER_MS; ++ sec = ms / 1000; ++ ms -= sec * 1000; ++ ++ buf += snprintf(buf, (limit - buf), "%04u.%03u.%03u ", sec, ms, us); ++ /* buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); */ ++ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, ++ logtab[readi].a2); ++ buf += snprintf(buf, (limit - buf), "\n"); ++ } ++} ++ ++#endif /* BCMTSTAMPEDLOGS */ ++ ++#if defined(BCMDBG) || defined(DHD_DEBUG) ++/* pretty hex print a pkt buffer chain */ ++void ++prpkt(const char *msg, osl_t *osh, void *p0) ++{ ++ void *p; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("%s:\n", msg); ++ ++ for (p = p0; p; p = PKTNEXT(osh, p)) ++ prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); ++} ++#endif /* BCMDBG || DHD_DEBUG */ ++ ++/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. ++ * Also updates the inplace vlan tag if requested. ++ * For debugging, it returns an indication of what it did. ++ */ ++uint BCMFASTPATH ++pktsetprio(void *pkt, bool update_vtag) ++{ ++ struct ether_header *eh; ++ struct ethervlan_header *evh; ++ uint8 *pktdata; ++ int priority = 0; ++ int rc = 0; ++ ++ pktdata = (uint8 *)PKTDATA(NULL, pkt); ++ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); ++ ++ eh = (struct ether_header *) pktdata; ++ ++ if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { ++ uint16 vlan_tag; ++ int vlan_prio, dscp_prio = 0; ++ ++ evh = (struct ethervlan_header *)eh; ++ ++ vlan_tag = ntoh16(evh->vlan_tag); ++ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; ++ ++ if (evh->ether_type == hton16(ETHER_TYPE_IP)) { ++ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ } ++ ++ /* DSCP priority gets precedence over 802.1P (vlan tag) */ ++ if (dscp_prio != 0) { ++ priority = dscp_prio; ++ rc |= PKTPRIO_VDSCP; ++ } else { ++ priority = vlan_prio; ++ rc |= PKTPRIO_VLAN; ++ } ++ /* ++ * If the DSCP priority is not the same as the VLAN priority, ++ * then overwrite the priority field in the vlan tag, with the ++ * DSCP priority value. This is required for Linux APs because ++ * the VLAN driver on Linux, overwrites the skb->priority field ++ * with the priority value in the vlan tag ++ */ ++ if (update_vtag && (priority != vlan_prio)) { ++ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); ++ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; ++ evh->vlan_tag = hton16(vlan_tag); ++ rc |= PKTPRIO_UPD; ++ } ++ } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) { ++ uint8 *ip_body = pktdata + sizeof(struct ether_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ rc |= PKTPRIO_DSCP; ++ } ++ ++ ASSERT(priority >= 0 && priority <= MAXPRIO); ++ PKTSETPRIO(pkt, priority); ++ return (rc | priority); ++} ++ ++#ifndef BCM_BOOTLOADER ++ ++static char bcm_undeferrstr[32]; ++static const char *const bcmerrorstrtable[] = BCMERRSTRINGTABLE; ++ ++/* Convert the error codes into related error strings */ ++const char * ++bcmerrorstr(int bcmerror) ++{ ++ /* check if someone added a bcmerror code but forgot to add errorstring */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); ++ ++ if (bcmerror > 0 || bcmerror < BCME_LAST) { ++ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); ++ return bcm_undeferrstr; ++ } ++ ++ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); ++ ++ return bcmerrorstrtable[-bcmerror]; ++} ++ ++#endif /* !BCM_BOOTLOADER */ ++ ++#ifdef WLC_LOW ++static void ++BCMINITFN(bcm_nvram_refresh)(char *flash) ++{ ++ int i; ++ int ret = 0; ++ ++ ASSERT(flash != NULL); ++ ++ /* default "empty" vars cache */ ++ bzero(flash, 2); ++ ++ if ((ret = nvram_getall(flash, NVRAM_SPACE))) ++ return; ++ ++ /* determine nvram length */ ++ for (i = 0; i < NVRAM_SPACE; i++) { ++ if (flash[i] == '\0' && flash[i+1] == '\0') ++ break; ++ } ++ ++ if (i > 1) ++ vars_len = i + 2; ++ else ++ vars_len = 0; ++} ++ ++char * ++bcm_nvram_vars(uint *length) ++{ ++#ifndef BCMNVRAMR ++ /* cache may be stale if nvram is read/write */ ++ if (nvram_vars) { ++ ASSERT(!bcmreclaimed); ++ bcm_nvram_refresh(nvram_vars); ++ } ++#endif ++ if (length) ++ *length = vars_len; ++ return nvram_vars; ++} ++ ++/* copy nvram vars into locally-allocated multi-string array */ ++int ++BCMINITFN(bcm_nvram_cache)(void *sih) ++{ ++ int ret = 0; ++ void *osh; ++ char *flash = NULL; ++ ++ if (vars_len >= 0) { ++#ifndef BCMNVRAMR ++ bcm_nvram_refresh(nvram_vars); ++#endif ++ return 0; ++ } ++ ++ osh = si_osh((si_t *)sih); ++ ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) { ++ ret = BCME_NOMEM; ++ goto exit; ++ } ++ ++ bcm_nvram_refresh(flash); ++ ++#ifdef BCMNVRAMR ++ if (vars_len > 3) { ++ /* copy into a properly-sized buffer */ ++ if (!(nvram_vars = MALLOC(osh, vars_len))) { ++ ret = BCME_NOMEM; ++ } else ++ bcopy(flash, nvram_vars, vars_len); ++ } ++ MFREE(osh, flash, NVRAM_SPACE); ++#else ++ /* cache must be full size of nvram if read/write */ ++ nvram_vars = flash; ++#endif /* BCMNVRAMR */ ++ ++exit: ++ return ret; ++} ++#endif /* WLC_LOW */ ++ ++ ++int32 ++exthdr_validate(char *ptr, uint size) ++{ ++ char *exthdr, *trx_offset; ++ uint hdrsz; ++ int trxof = 0; ++ ++ if ((exthdr = nvram_get("ext_imghdr"))) { ++ char s[] = "XXX"; ++ uint i, j; ++ ++ hdrsz = strlen(exthdr); ++ ++ if (hdrsz > size) { ++ printf("Exthdr_size(%d) > Image_size(%d)\n", hdrsz, size); ++ trxof = -1; ++ goto done; ++ } ++ ++ if (hdrsz == 0) ++ goto match; ++ ++ for (i = 0, j = 0; i < (hdrsz >> 1); i++) { ++ sprintf(s, "%02x", (ptr[i] & 0xff)); ++ if ((exthdr[j++] != s[0]) || (exthdr[j++] != s[1])) { ++ printf("Header mismatch\n"); ++ goto done; ++ } ++ } ++ } ++ ++match: ++ if ((trx_offset = nvram_get("trx_offset"))) ++ trxof = bcm_strtoul(trx_offset, NULL, 0); ++ ++done: ++ return trxof; ++} ++ ++/* iovar table lookup */ ++const bcm_iovar_t* ++bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) ++{ ++ const bcm_iovar_t *vi; ++ const char *lookup_name; ++ ++ /* skip any ':' delimited option prefixes */ ++ lookup_name = strrchr(name, ':'); ++ if (lookup_name != NULL) ++ lookup_name++; ++ else ++ lookup_name = name; ++ ++ ASSERT(table != NULL); ++ ++ for (vi = table; vi->name; vi++) { ++ if (!strcmp(vi->name, lookup_name)) ++ return vi; ++ } ++ /* ran to end of table */ ++ ++ return NULL; /* var name not found */ ++} ++ ++int ++bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) ++{ ++ int bcmerror = 0; ++ ++ /* length check on io buf */ ++ switch (vi->type) { ++ case IOVT_BOOL: ++ case IOVT_INT8: ++ case IOVT_INT16: ++ case IOVT_INT32: ++ case IOVT_UINT8: ++ case IOVT_UINT16: ++ case IOVT_UINT32: ++ /* all integers are int32 sized args at the ioctl interface */ ++ if (len < (int)sizeof(int)) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_BUFFER: ++ /* buffer must meet minimum length requirement */ ++ if (len < vi->minlen) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_VOID: ++ if (!set) { ++ /* Cannot return nil... */ ++ bcmerror = BCME_UNSUPPORTED; ++ } else if (len) { ++ /* Set is an action w/o parameters */ ++ bcmerror = BCME_BUFTOOLONG; ++ } ++ break; ++ ++ default: ++ /* unknown type for length check in iovar info */ ++ ASSERT(0); ++ bcmerror = BCME_UNSUPPORTED; ++ } ++ ++ return bcmerror; ++} ++ ++#endif /* BCMDRIVER */ ++ ++ ++/******************************************************************************* ++ * crc8 ++ * ++ * Computes a crc8 over the input data using the polynomial: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ * ++ * The caller provides the initial value (either CRC8_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC8_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint8 crc8_table[256] = { ++ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F ++}; ++ ++#define CRC_INNER_LOOP(n, c, x) \ ++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] ++ ++uint8 ++BCMROMFN(hndcrc8)( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ ++) ++{ ++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro ++ * to avoid the undefined and unnecessary (uint8 >> 8) operation. ++ */ ++ while (nbytes-- > 0) ++ crc = crc8_table[(crc ^ *pdata++) & 0xff]; ++ ++ return crc; ++} ++ ++/******************************************************************************* ++ * crc16 ++ * ++ * Computes a crc16 over the input data using the polynomial: ++ * ++ * x^16 + x^12 +x^5 + 1 ++ * ++ * The caller provides the initial value (either CRC16_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC16_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint16 crc16_table[256] = { ++ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, ++ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, ++ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, ++ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, ++ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, ++ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, ++ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, ++ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, ++ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, ++ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, ++ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, ++ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, ++ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, ++ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, ++ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, ++ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, ++ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, ++ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, ++ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, ++ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, ++ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, ++ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, ++ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, ++ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, ++ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, ++ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, ++ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, ++ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, ++ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, ++ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, ++ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, ++ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 ++}; ++ ++uint16 ++BCMROMFN(hndcrc16)( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint16 crc /* either CRC16_INIT_VALUE or previous return value */ ++) ++{ ++ while (nbytes-- > 0) ++ CRC_INNER_LOOP(16, crc, *pdata++); ++ return crc; ++} ++ ++static const uint32 crc32_table[256] = { ++ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, ++ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, ++ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, ++ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, ++ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, ++ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, ++ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, ++ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, ++ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, ++ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, ++ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, ++ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, ++ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, ++ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, ++ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, ++ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, ++ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, ++ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, ++ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, ++ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, ++ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, ++ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, ++ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, ++ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, ++ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, ++ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, ++ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, ++ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, ++ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, ++ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, ++ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, ++ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, ++ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, ++ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, ++ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, ++ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, ++ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, ++ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, ++ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, ++ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, ++ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, ++ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, ++ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, ++ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, ++ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, ++ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, ++ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, ++ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, ++ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, ++ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, ++ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, ++ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, ++ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, ++ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, ++ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, ++ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, ++ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, ++ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, ++ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, ++ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, ++ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, ++ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, ++ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, ++ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D ++}; ++ ++/* ++ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if ++ * accumulating over multiple pieces. ++ */ ++uint32 ++BCMROMFN(hndcrc32)(uint8 *pdata, uint nbytes, uint32 crc) ++{ ++ uint8 *pend; ++#ifdef __mips__ ++ uint8 tmp[4]; ++ ulong *tptr = (ulong *)tmp; ++ ++ if (nbytes > 3) { ++ /* in case the beginning of the buffer isn't aligned */ ++ pend = (uint8 *)((uint)(pdata + 3) & ~0x3); ++ nbytes -= (pend - pdata); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++ } ++ ++ if (nbytes > 3) { ++ /* handle bulk of data as 32-bit words */ ++ pend = pdata + (nbytes & ~0x3); ++ while (pdata < pend) { ++ *tptr = *(ulong *)pdata; ++ pdata += sizeof(ulong *); ++ CRC_INNER_LOOP(32, crc, tmp[0]); ++ CRC_INNER_LOOP(32, crc, tmp[1]); ++ CRC_INNER_LOOP(32, crc, tmp[2]); ++ CRC_INNER_LOOP(32, crc, tmp[3]); ++ } ++ } ++ ++ /* 1-3 bytes at end of buffer */ ++ pend = pdata + (nbytes & 0x03); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#else ++ pend = pdata + nbytes; ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#endif /* __mips__ */ ++ ++ return crc; ++} ++ ++#ifdef notdef ++#define CLEN 1499 /* CRC Length */ ++#define CBUFSIZ (CLEN+4) ++#define CNBUFS 5 /* # of bufs */ ++ ++void ++testcrc32(void) ++{ ++ uint j, k, l; ++ uint8 *buf; ++ uint len[CNBUFS]; ++ uint32 crcr; ++ uint32 crc32tv[CNBUFS] = ++ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; ++ ++ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); ++ ++ /* step through all possible alignments */ ++ for (l = 0; l <= 4; l++) { ++ for (j = 0; j < CNBUFS; j++) { ++ len[j] = CLEN; ++ for (k = 0; k < len[j]; k++) ++ *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; ++ } ++ ++ for (j = 0; j < CNBUFS; j++) { ++ crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); ++ ASSERT(crcr == crc32tv[j]); ++ } ++ } ++ ++ MFREE(buf, CBUFSIZ*CNBUFS); ++ return; ++} ++#endif /* notdef */ ++ ++/* ++ * Advance from the current 1-byte tag/1-byte length/variable-length value ++ * triple, to the next, returning a pointer to the next. ++ * If the current or next TLV is invalid (does not fit in given buffer length), ++ * NULL is returned. ++ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented ++ * by the TLV parameter's length if it is valid. ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen) ++{ ++ int len; ++ ++ /* validate current elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ /* advance to next elt */ ++ len = elt->len; ++ elt = (bcm_tlv_t*)(elt->data + len); ++ *buflen -= (TLV_HDR_LEN + len); ++ ++ /* validate next elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ return elt; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ int len = elt->len; ++ ++ /* validate remaining totlen */ ++ if ((elt->id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag. Stop parsing when we see an element whose ID is greater ++ * than the target key. ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ uint id = elt->id; ++ int len = elt->len; ++ ++ /* Punt if we start seeing IDs > than target key */ ++ if (id > key) ++ return (NULL); ++ ++ /* validate remaining totlen */ ++ if ((id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ return NULL; ++} ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(WLMSG_PRHDRS) || \ ++ defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || defined(DHD_DEBUG) ++int ++bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) ++{ ++ int i; ++ char* p = buf; ++ char hexstr[16]; ++ int slen = 0, nlen = 0; ++ uint32 bit; ++ const char* name; ++ ++ if (len < 2 || !buf) ++ return 0; ++ ++ buf[0] = '\0'; ++ ++ for (i = 0; flags != 0; i++) { ++ bit = bd[i].bit; ++ name = bd[i].name; ++ if (bit == 0 && flags != 0) { ++ /* print any unnamed bits */ ++ snprintf(hexstr, 16, "0x%X", flags); ++ name = hexstr; ++ flags = 0; /* exit loop */ ++ } else if ((flags & bit) == 0) ++ continue; ++ flags &= ~bit; ++ nlen = strlen(name); ++ slen += nlen; ++ /* count btwn flag space */ ++ if (flags != 0) ++ slen += 1; ++ /* need NULL char as well */ ++ if (len <= slen) ++ break; ++ /* copy NULL char but don't count it */ ++ strncpy(p, name, nlen + 1); ++ p += nlen; ++ /* copy btwn flag space and NULL char */ ++ if (flags != 0) ++ p += snprintf(p, 2, " "); ++ } ++ ++ /* indicate the str was too short */ ++ if (flags != 0) { ++ if (len < 2) ++ p -= 2 - len; /* overwrite last char */ ++ p += snprintf(p, 2, ">"); ++ } ++ ++ return (int)(p - buf); ++} ++ ++/* print bytes formatted as hex to a string. return the resulting string length */ ++int ++bcm_format_hex(char *str, const void *bytes, int len) ++{ ++ int i; ++ char *p = str; ++ const uint8 *src = (const uint8*)bytes; ++ ++ for (i = 0; i < len; i++) { ++ p += snprintf(p, 3, "%02X", *src); ++ src++; ++ } ++ return (int)(p - str); ++} ++#endif ++ ++/* pretty hex print a contiguous buffer */ ++void ++prhex(const char *msg, uchar *buf, uint nbytes) ++{ ++ char line[128], *p; ++ int len = sizeof(line); ++ int nchar; ++ uint i; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("%s:\n", msg); ++ ++ p = line; ++ for (i = 0; i < nbytes; i++) { ++ if (i % 16 == 0) { ++ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */ ++ p += nchar; ++ len -= nchar; ++ } ++ if (len > 0) { ++ nchar = snprintf(p, len, "%02x ", buf[i]); ++ p += nchar; ++ len -= nchar; ++ } ++ ++ if (i % 16 == 15) { ++ printf("%s\n", line); /* flush line */ ++ p = line; ++ len = sizeof(line); ++ } ++ } ++ ++ /* flush last partial line */ ++ if (p != line) ++ printf("%s\n", line); ++} ++ ++static const char *crypto_algo_names[] = { ++ "NONE", ++ "WEP1", ++ "TKIP", ++ "WEP128", ++ "AES_CCM", ++ "AES_OCB_MSDU", ++ "AES_OCB_MPDU", ++ "NALG" ++ "UNDEF", ++ "UNDEF", ++ "UNDEF", ++ "UNDEF" ++}; ++ ++const char * ++bcm_crypto_algo_name(uint algo) ++{ ++ return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; ++} ++ ++#ifdef BCMDBG ++void ++deadbeef(void *p, size_t len) ++{ ++ static uint8 meat[] = { 0xde, 0xad, 0xbe, 0xef }; ++ ++ while (len-- > 0) { ++ *(uint8*)p = meat[((uintptr)p) & 3]; ++ p = (uint8*)p + 1; ++ } ++} ++#endif /* BCMDBG */ ++ ++char * ++bcm_chipname(uint chipid, char *buf, uint len) ++{ ++ const char *fmt; ++ ++ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; ++ snprintf(buf, len, fmt, chipid); ++ return buf; ++} ++ ++/* Produce a human-readable string for boardrev */ ++char * ++bcm_brev_str(uint32 brev, char *buf) ++{ ++ if (brev < 0x100) ++ snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); ++ else ++ snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); ++ ++ return (buf); ++} ++ ++#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ ++ ++/* dump large strings to console */ ++void ++printbig(char *buf) ++{ ++ uint len, max_len; ++ char c; ++ ++ len = strlen(buf); ++ ++ max_len = BUFSIZE_TODUMP_ATONCE; ++ ++ while (len > max_len) { ++ c = buf[max_len]; ++ buf[max_len] = '\0'; ++ printf("%s", buf); ++ buf[max_len] = c; ++ ++ buf += max_len; ++ len -= max_len; ++ } ++ /* print the remaining string */ ++ printf("%s\n", buf); ++ return; ++} ++ ++/* routine to dump fields in a fileddesc structure */ ++uint ++bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, ++ char *buf, uint32 bufsize) ++{ ++ uint filled_len; ++ int len; ++ struct fielddesc *cur_ptr; ++ ++ filled_len = 0; ++ cur_ptr = fielddesc_array; ++ ++ while (bufsize > 1) { ++ if (cur_ptr->nameandfmt == NULL) ++ break; ++ len = snprintf(buf, bufsize, cur_ptr->nameandfmt, ++ read_rtn(arg0, arg1, cur_ptr->offset)); ++ /* check for snprintf overflow or error */ ++ if (len < 0 || (uint32)len >= bufsize) ++ len = bufsize - 1; ++ buf += len; ++ bufsize -= len; ++ filled_len += len; ++ cur_ptr++; ++ } ++ return filled_len; ++} ++ ++uint ++bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++{ ++ uint len; ++ ++ len = strlen(name) + 1; ++ ++ if ((len + datalen) > buflen) ++ return 0; ++ ++ strncpy(buf, name, buflen); ++ ++ /* append data onto the end of the name string */ ++ memcpy(&buf[len], data, datalen); ++ len += datalen; ++ ++ return len; ++} ++ ++/* Quarter dBm units to mW ++ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 ++ * Table is offset so the last entry is largest mW value that fits in ++ * a uint16. ++ */ ++ ++#define QDBM_OFFSET 153 /* Offset for first entry */ ++#define QDBM_TABLE_LEN 40 /* Table size */ ++ ++/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. ++ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 ++ */ ++#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ ++ ++/* Largest mW value that will round down to the last table entry, ++ * QDBM_OFFSET + QDBM_TABLE_LEN-1. ++ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. ++ */ ++#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ ++ ++static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { ++/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ ++/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, ++/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, ++/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, ++/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, ++/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 ++}; ++ ++uint16 ++BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm) ++{ ++ uint factor = 1; ++ int idx = qdbm - QDBM_OFFSET; ++ ++ if (idx >= QDBM_TABLE_LEN) { ++ /* clamp to max uint16 mW value */ ++ return 0xFFFF; ++ } ++ ++ /* scale the qdBm index up to the range of the table 0-40 ++ * where an offset of 40 qdBm equals a factor of 10 mW. ++ */ ++ while (idx < 0) { ++ idx += 40; ++ factor *= 10; ++ } ++ ++ /* return the mW value scaled down to the correct factor of 10, ++ * adding in factor/2 to get proper rounding. ++ */ ++ return ((nqdBm_to_mW_map[idx] + factor/2) / factor); ++} ++ ++uint8 ++BCMROMFN(bcm_mw_to_qdbm)(uint16 mw) ++{ ++ uint8 qdbm; ++ int offset; ++ uint mw_uint = mw; ++ uint boundary; ++ ++ /* handle boundary case */ ++ if (mw_uint <= 1) ++ return 0; ++ ++ offset = QDBM_OFFSET; ++ ++ /* move mw into the range of the table */ ++ while (mw_uint < QDBM_TABLE_LOW_BOUND) { ++ mw_uint *= 10; ++ offset -= 40; ++ } ++ ++ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { ++ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - ++ nqdBm_to_mW_map[qdbm])/2; ++ if (mw_uint < boundary) break; ++ } ++ ++ qdbm += (uint8)offset; ++ ++ return (qdbm); ++} ++ ++ ++uint ++BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint length) ++{ ++ uint bitcount = 0, i; ++ uint8 tmp; ++ for (i = 0; i < length; i++) { ++ tmp = bitmap[i]; ++ while (tmp) { ++ bitcount++; ++ tmp &= (tmp - 1); ++ } ++ } ++ return bitcount; ++} ++ ++#ifdef BCMDRIVER ++ ++/* Initialization of bcmstrbuf structure */ ++void ++bcm_binit(struct bcmstrbuf *b, char *buf, uint size) ++{ ++ b->origsize = b->size = size; ++ b->origbuf = b->buf = buf; ++} ++ ++/* Buffer sprintf wrapper to guard against buffer overflow */ ++int ++bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ ++ va_start(ap, fmt); ++ ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ ++ /* Non Ansi C99 compliant returns -1, ++ * Ansi compliant return r >= b->size, ++ * bcmstdlib returns 0, handle all ++ */ ++ /* r == 0 is also the case when strlen(fmt) is zero. ++ * typically the case when "" is passed as argument. ++ */ ++ if ((r == -1) || (r >= (int)b->size)) { ++ b->size = 0; ++ } else { ++ b->size -= r; ++ b->buf += r; ++ } ++ ++ va_end(ap); ++ ++ return r; ++} ++ ++void ++bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len) ++{ ++ int i; ++ ++ if (msg != NULL && msg[0] != '\0') ++ bcm_bprintf(b, "%s", msg); ++ for (i = 0; i < len; i ++) ++ bcm_bprintf(b, "%02X", buf[i]); ++ if (newline) ++ bcm_bprintf(b, "\n"); ++} ++ ++void ++bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) ++{ ++ int i; ++ ++ for (i = 0; i < num_bytes; i++) { ++ num[i] += amount; ++ if (num[i] >= amount) ++ break; ++ amount = 1; ++ } ++} ++ ++int ++bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) ++{ ++ int i; ++ ++ for (i = nbytes - 1; i >= 0; i--) { ++ if (arg1[i] != arg2[i]) ++ return (arg1[i] - arg2[i]); ++ } ++ return 0; ++} ++ ++void ++bcm_print_bytes(const char *name, const uchar *data, int len) ++{ ++ int i; ++ int per_line = 0; ++ ++ printf("%s: %d \n", name ? name : "", len); ++ for (i = 0; i < len; i++) { ++ printf("%02x ", *data++); ++ per_line++; ++ if (per_line == 16) { ++ per_line = 0; ++ printf("\n"); ++ } ++ } ++ printf("\n"); ++} ++#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ ++ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) ++ ++int ++bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) ++{ ++ uint i, c; ++ char *p = buf; ++ char *endp = buf + SSID_FMT_BUF_LEN; ++ ++ if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; ++ ++ for (i = 0; i < ssid_len; i++) { ++ c = (uint)ssid[i]; ++ if (c == '\\') { ++ *p++ = '\\'; ++ *p++ = '\\'; ++ } else if (bcm_isprint((uchar)c)) { ++ *p++ = (char)c; ++ } else { ++ p += snprintf(p, (endp - p), "\\x%02X", c); ++ } ++ } ++ *p = '\0'; ++ ASSERT(p < endp); ++ ++ return (int)(p - buf); ++} ++#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ ++ ++#endif /* BCMDRIVER */ ++ ++/* ++ * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. ++ * also accepts nvram files which are already in the format of =\0\=\0 ++ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. ++ * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. ++*/ ++ ++unsigned int ++process_nvram_vars(char *varbuf, unsigned int len) ++{ ++ char *dp; ++ bool findNewline; ++ int column; ++ unsigned int buf_len, n; ++ unsigned int pad = 0; ++ ++ dp = varbuf; ++ ++ findNewline = FALSE; ++ column = 0; ++ ++ for (n = 0; n < len; n++) { ++ if (varbuf[n] == '\r') ++ continue; ++ if (findNewline && varbuf[n] != '\n') ++ continue; ++ findNewline = FALSE; ++ if (varbuf[n] == '#') { ++ findNewline = TRUE; ++ continue; ++ } ++ if (varbuf[n] == '\n') { ++ if (column == 0) ++ continue; ++ *dp++ = 0; ++ column = 0; ++ continue; ++ } ++ *dp++ = varbuf[n]; ++ column++; ++ } ++ buf_len = (unsigned int)(dp - varbuf); ++ if (buf_len % 4) { ++ pad = 4 - buf_len % 4; ++ if (pad && (buf_len + pad <= len)) { ++ buf_len += pad; ++ } ++ } ++ ++ while (dp < varbuf + n) ++ *dp++ = 0; ++ ++ return buf_len; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/hnddma.c b/drivers/bcmdrivers/gmac/src/shared/hnddma.c +new file mode 100755 +index 0000000..2463d1f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch new file mode 100644 index 00000000..3ec53d24 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch @@ -0,0 +1,3575 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hnddma.c +@@ -0,0 +1,3569 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA module. ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: hnddma.c 328477 2012-04-19 10:57:54Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#include ++#endif ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_RWREG_OPT ++#ifdef R_REG ++#undef R_REG ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r)) : \ ++ (*(volatile unsigned int __force *)(r)) \ ++) ++#endif /* R_REG */ ++ ++#ifdef W_REG ++#undef W_REG ++#define W_REG(osh, r, v) (\ ++ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r) = (v)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r) = (v)) : \ ++ (*(volatile unsigned int __force *)(r) = (v)) \ ++) ++#endif /* W_REG */ ++#endif /* CONFIG_BCM_IPROC_GMAC_RWREG_OPT */ ++ ++/* debug/trace */ ++#ifdef BCMDBG ++#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args ++#define DMA_TRACE(args) if (!(*di->msg_level & 2)); else printf args ++#elif defined(BCMDBG_ERR) ++#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args ++#define DMA_TRACE(args) ++#else ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) ++#endif /* BCMDBG */ ++ ++#define DMA_NONE(args) ++ ++ ++#define d32txregs dregs.d32_u.txregs_32 ++#define d32rxregs dregs.d32_u.rxregs_32 ++#define txd32 dregs.d32_u.txd_32 ++#define rxd32 dregs.d32_u.rxd_32 ++ ++#define d64txregs dregs.d64_u.txregs_64 ++#define d64rxregs dregs.d64_u.rxregs_64 ++#define txd64 dregs.d64_u.txd_64 ++#define rxd64 dregs.d64_u.rxd_64 ++ ++#define DBG(x...) printk(KERN_ERR x) ++ ++/* default dma message level (if input msg_level pointer is null in dma_attach()) */ ++static uint dma_msg_level = ++#ifdef BCMDBG_ERR ++ 1; ++#else ++ 0; ++#endif /* BCMDBG_ERR */ ++ ++#define MAXNAMEL 8 /* 8 char names */ ++ ++#define DI_INFO(dmah) ((dma_info_t *)dmah) ++ ++/* dma engine software state */ ++typedef struct dma_info { ++ struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t, ++ * which could be const ++ */ ++ uint *msg_level; /* message level pointer */ ++ char name[MAXNAMEL]; /* callers name for diag msgs */ ++ ++ void *osh; /* os handle */ ++ si_t *sih; /* sb handle */ ++ ++ bool dma64; /* this dma engine is operating in 64-bit mode */ ++ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ ++ ++ union { ++ struct { ++ dma32regs_t *txregs_32; /* 32-bit dma tx engine registers */ ++ dma32regs_t *rxregs_32; /* 32-bit dma rx engine registers */ ++ dma32dd_t *txd_32; /* pointer to dma32 tx descriptor ring */ ++ dma32dd_t *rxd_32; /* pointer to dma32 rx descriptor ring */ ++ } d32_u; ++ struct { ++ dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */ ++ dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */ ++ dma64dd_t *txd_64; /* pointer to dma64 tx descriptor ring */ ++ dma64dd_t *rxd_64; /* pointer to dma64 rx descriptor ring */ ++ } d64_u; ++ } dregs; ++ ++ uint16 dmadesc_align; /* alignment requirement for dma descriptors */ ++ ++ uint16 ntxd; /* # tx descriptors tunable */ ++ uint16 txin; /* index of next descriptor to reclaim */ ++ uint16 txout; /* index of next descriptor to post */ ++ void **txp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *tx_dmah; /* DMA TX descriptor ring handle */ ++ hnddma_seg_map_t *txp_dmah; /* DMA MAP meta-data handle */ ++ dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */ ++ dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */ ++ uint16 txdalign; /* #bytes added to alloc'd mem to align txd */ ++ uint32 txdalloc; /* #bytes allocated for the ring */ ++ uint32 xmtptrbase; /* When using unaligned descriptors, the ptr register ++ * is not just an index, it needs all 13 bits to be ++ * an offset from the addr register. ++ */ ++ ++ uint16 nrxd; /* # rx descriptors tunable */ ++ uint16 rxin; /* index of next descriptor to reclaim */ ++ uint16 rxout; /* index of next descriptor to post */ ++ void **rxp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *rx_dmah; /* DMA RX descriptor ring handle */ ++ hnddma_seg_map_t *rxp_dmah; /* DMA MAP meta-data handle */ ++ dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */ ++ dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */ ++ uint16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ ++ uint32 rxdalloc; /* #bytes allocated for the ring */ ++ uint32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ ++ ++ /* tunables */ ++ uint16 rxbufsize; /* rx buffer size in bytes, ++ * not including the extra headroom ++ */ ++ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack ++ * e.g. some rx pkt buffers will be bridged to tx side ++ * without byte copying. The extra headroom needs to be ++ * large enough to fit txheader needs. ++ * Some dongle driver may not need it. ++ */ ++ uint nrxpost; /* # rx buffers to keep posted */ ++ uint rxoffset; /* rxcontrol offset */ ++ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ ++ uint ddoffsethigh; /* high 32 bits */ ++ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ ++ uint dataoffsethigh; /* high 32 bits */ ++ bool aligndesc_4k; /* descriptor base need to be aligned or not */ ++ uint8 rxburstlen; /* burstlen field for rx (for cores supporting burstlen) */ ++ uint8 txburstlen; /* burstlen field for tx (for cores supporting burstlen) */ ++ uint8 txmultioutstdrd; /* tx multiple outstanding reads */ ++ uint8 txprefetchctl; /* prefetch control for tx */ ++ uint8 txprefetchthresh; /* prefetch threshold for tx */ ++ uint8 rxprefetchctl; /* prefetch control for rx */ ++ uint8 rxprefetchthresh; /* prefetch threshold for rx */ ++ pktpool_t *pktpool; /* pktpool */ ++ uint dma_avoidance_cnt; ++ ++ uint32 d64_xs0_cd_mask; /* tx current descriptor pointer mask */ ++ uint32 d64_xs1_ad_mask; /* tx active descriptor mask */ ++ uint32 d64_rs0_cd_mask; /* rx current descriptor pointer mask */ ++ uint16 rs0cd; /* cached value of rcvstatus0 currdescr */ ++ uint16 xs0cd; /* cached value of xmtstatus0 currdescr */ ++ uint16 xs0cd_snapshot; /* snapshot of xmtstatus0 currdescr */ ++ spinlock_t des_lock; ++} dma_info_t; ++ ++/* ++ * If BCMDMA32 is defined, hnddma will support both 32-bit and 64-bit DMA engines. ++ * Otherwise it will support only 64-bit. ++ * ++ * DMA32_ENAB indicates whether hnddma is compiled with support for 32-bit DMA engines. ++ * DMA64_ENAB indicates whether hnddma is compiled with support for 64-bit DMA engines. ++ * ++ * DMA64_MODE indicates whether the current DMA engine is running as 64-bit. ++ */ ++#ifdef BCMDMA32 ++#define DMA32_ENAB(di) 1 ++#define DMA64_ENAB(di) 1 ++#define DMA64_MODE(di) ((di)->dma64) ++#else /* !BCMDMA32 */ ++#define DMA32_ENAB(di) 0 ++#define DMA64_ENAB(di) 1 ++#define DMA64_MODE(di) 1 ++#endif /* !BCMDMA32 */ ++ ++/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */ ++#ifdef BCMDMASGLISTOSL ++#define DMASGLIST_ENAB TRUE ++#else ++#define DMASGLIST_ENAB FALSE ++#endif /* BCMDMASGLISTOSL */ ++ ++/* descriptor bumping macros */ ++#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ ++#define TXD(x) XXD((x), di->ntxd) ++#define RXD(x) XXD((x), di->nrxd) ++#define NEXTTXD(i) TXD((i) + 1) ++#define PREVTXD(i) TXD((i) - 1) ++#define NEXTRXD(i) RXD((i) + 1) ++#define PREVRXD(i) RXD((i) - 1) ++ ++#define NTXDACTIVE(h, t) TXD((t) - (h)) ++#define NRXDACTIVE(h, t) RXD((t) - (h)) ++ ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((uint16)((bytes) / sizeof(type))) ++#define I2B(index, type) ((index) * sizeof(type)) ++ ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ ++ ++#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ ++#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ ++ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#define SKB_PREFETCH_LEN (128) ++#endif ++ ++/* Common prototypes */ ++static bool _dma_isaddrext(dma_info_t *di); ++static bool _dma_descriptor_align(dma_info_t *di); ++static bool _dma_alloc(dma_info_t *di, uint direction); ++static void _dma_detach(dma_info_t *di); ++static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa); ++static void _dma_rxinit(dma_info_t *di); ++static void *_dma_rx(dma_info_t *di); ++static bool _dma_rxfill(dma_info_t *di); ++static void _dma_rxreclaim(dma_info_t *di); ++static void _dma_rxenable(dma_info_t *di); ++static void *_dma_getnextrxp(dma_info_t *di, bool forceall); ++static void _dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize); ++ ++static void _dma_txblock(dma_info_t *di); ++static void _dma_txunblock(dma_info_t *di); ++static uint _dma_txactive(dma_info_t *di); ++static uint _dma_rxactive(dma_info_t *di); ++static uint _dma_activerxbuf(dma_info_t *di); ++static uint _dma_txpending(dma_info_t *di); ++static uint _dma_txcommitted(dma_info_t *di); ++ ++static void *_dma_peeknexttxp(dma_info_t *di); ++static int _dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range); ++static void *_dma_peeknextrxp(dma_info_t *di); ++static uintptr _dma_getvar(dma_info_t *di, const char *name); ++static void _dma_counterreset(dma_info_t *di); ++static void _dma_fifoloopbackenable(dma_info_t *di); ++static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags); ++static uint8 dma_align_sizetobits(uint size); ++static void *dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, ++ dmaaddr_t *descpa, osldma_t **dmah); ++static int _dma_pktpool_set(dma_info_t *di, pktpool_t *pool); ++static bool _dma_rxtx_error(dma_info_t *di, bool istx); ++static void _dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen); ++static uint _dma_avoidancecnt(dma_info_t *di); ++static void _dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval); ++static bool _dma_glom_enable(dma_info_t *di, uint32 val); ++ ++ ++/* Prototypes for 32-bit routines */ ++static bool dma32_alloc(dma_info_t *di, uint direction); ++static bool dma32_txreset(dma_info_t *di); ++static bool dma32_rxreset(dma_info_t *di); ++static bool dma32_txsuspendedidle(dma_info_t *di); ++static int dma32_txfast(dma_info_t *di, void *p0, bool commit); ++static void *dma32_getnexttxp(dma_info_t *di, txd_range_t range); ++static void *dma32_getnextrxp(dma_info_t *di, bool forceall); ++static void dma32_txrotate(dma_info_t *di); ++static bool dma32_rxidle(dma_info_t *di); ++static void dma32_txinit(dma_info_t *di); ++static bool dma32_txenabled(dma_info_t *di); ++static void dma32_txsuspend(dma_info_t *di); ++static void dma32_txresume(dma_info_t *di); ++static bool dma32_txsuspended(dma_info_t *di); ++#ifdef WL_MULTIQUEUE ++static void dma32_txflush(dma_info_t *di); ++static void dma32_txflush_clear(dma_info_t *di); ++#endif /* WL_MULTIQUEUE */ ++static void dma32_txreclaim(dma_info_t *di, txd_range_t range); ++static bool dma32_txstopped(dma_info_t *di); ++static bool dma32_rxstopped(dma_info_t *di); ++static bool dma32_rxenabled(dma_info_t *di); ++#if defined(BCMDBG) ++static void dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, ++ uint end, uint max_num); ++static void dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++#endif ++ ++static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs); ++ ++/* Prototypes for 64-bit routines */ ++static bool dma64_alloc(dma_info_t *di, uint direction); ++static bool dma64_txreset(dma_info_t *di); ++static bool dma64_rxreset(dma_info_t *di); ++static bool dma64_txsuspendedidle(dma_info_t *di); ++static int dma64_txfast(dma_info_t *di, void *p0, bool commit); ++static int dma64_txunframed(dma_info_t *di, void *p0, uint len, bool commit); ++static void *dma64_getpos(dma_info_t *di, bool direction); ++static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range); ++static void *dma64_getnextrxp(dma_info_t *di, bool forceall); ++static void dma64_txrotate(dma_info_t *di); ++ ++static bool dma64_rxidle(dma_info_t *di); ++static void dma64_txinit(dma_info_t *di); ++static bool dma64_txenabled(dma_info_t *di); ++static void dma64_txsuspend(dma_info_t *di); ++static void dma64_txresume(dma_info_t *di); ++static bool dma64_txsuspended(dma_info_t *di); ++#ifdef WL_MULTIQUEUE ++static void dma64_txflush(dma_info_t *di); ++static void dma64_txflush_clear(dma_info_t *di); ++#endif /* WL_MULTIQUEUE */ ++static void dma64_txreclaim(dma_info_t *di, txd_range_t range); ++static bool dma64_txstopped(dma_info_t *di); ++static bool dma64_rxstopped(dma_info_t *di); ++static bool dma64_rxenabled(dma_info_t *di); ++static bool _dma64_addrext(osl_t *osh, dma64regs_t *dma64regs); ++static int dma64_rxunframed(dma_info_t *di, void *p0, uint len, bool commit); ++ ++STATIC INLINE uint32 parity32(uint32 data); ++ ++#if defined(BCMDBG) ++static void dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, ++ uint end, uint max_num); ++static void dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++#endif ++ ++ ++const di_fcn_t dma64proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma64_txinit, ++ (di_txreset_t)dma64_txreset, ++ (di_txenabled_t)dma64_txenabled, ++ (di_txsuspend_t)dma64_txsuspend, ++ (di_txresume_t)dma64_txresume, ++ (di_txsuspended_t)dma64_txsuspended, ++ (di_txsuspendedidle_t)dma64_txsuspendedidle, ++#ifdef WL_MULTIQUEUE ++ (di_txflush_t)dma64_txflush, ++ (di_txflush_clear_t)dma64_txflush_clear, ++#endif /* WL_MULTIQUEUE */ ++ (di_txfast_t)dma64_txfast, ++ (di_txunframed_t)dma64_txunframed, ++ (di_getpos_t)dma64_getpos, ++ (di_txstopped_t)dma64_txstopped, ++ (di_txreclaim_t)dma64_txreclaim, ++ (di_getnexttxp_t)dma64_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_peekntxp_t)_dma_peekntxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma64_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma64_rxreset, ++ (di_rxidle_t)dma64_rxidle, ++ (di_rxstopped_t)dma64_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma64_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ (di_peeknextrxp_t)_dma_peeknextrxp, ++ (di_rxparam_get_t)_dma_rx_param_get, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ (di_ctrlflags_t)_dma_ctrlflags, ++ ++#if defined(BCMDBG) ++ (di_dump_t)dma64_dump, ++ (di_dumptx_t)dma64_dumptx, ++ (di_dumprx_t)dma64_dumprx, ++#else ++ NULL, ++ NULL, ++ NULL, ++#endif ++ (di_rxactive_t)_dma_rxactive, ++ (di_txpending_t)_dma_txpending, ++ (di_txcommitted_t)_dma_txcommitted, ++ (di_pktpool_set_t)_dma_pktpool_set, ++ (di_rxtxerror_t)_dma_rxtx_error, ++ (di_burstlen_set_t)_dma_burstlen_set, ++ (di_avoidancecnt_t)_dma_avoidancecnt, ++ (di_param_set_t)_dma_param_set, ++ (dma_glom_enable_t)_dma_glom_enable, ++ (di_rxunframed_t)dma64_rxunframed, ++ (dma_active_rxbuf_t)_dma_activerxbuf, ++ 40 ++}; ++ ++static const di_fcn_t dma32proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma32_txinit, ++ (di_txreset_t)dma32_txreset, ++ (di_txenabled_t)dma32_txenabled, ++ (di_txsuspend_t)dma32_txsuspend, ++ (di_txresume_t)dma32_txresume, ++ (di_txsuspended_t)dma32_txsuspended, ++ (di_txsuspendedidle_t)dma32_txsuspendedidle, ++#ifdef WL_MULTIQUEUE ++ (di_txflush_t)dma32_txflush, ++ (di_txflush_clear_t)dma32_txflush_clear, ++#endif /* WL_MULTIQUEUE */ ++ (di_txfast_t)dma32_txfast, ++ NULL, ++ NULL, ++ (di_txstopped_t)dma32_txstopped, ++ (di_txreclaim_t)dma32_txreclaim, ++ (di_getnexttxp_t)dma32_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_peekntxp_t)_dma_peekntxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma32_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma32_rxreset, ++ (di_rxidle_t)dma32_rxidle, ++ (di_rxstopped_t)dma32_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma32_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ (di_peeknextrxp_t)_dma_peeknextrxp, ++ (di_rxparam_get_t)_dma_rx_param_get, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ (di_ctrlflags_t)_dma_ctrlflags, ++ ++#if defined(BCMDBG) ++ (di_dump_t)dma32_dump, ++ (di_dumptx_t)dma32_dumptx, ++ (di_dumprx_t)dma32_dumprx, ++#else ++ NULL, ++ NULL, ++ NULL, ++#endif ++ (di_rxactive_t)_dma_rxactive, ++ (di_txpending_t)_dma_txpending, ++ (di_txcommitted_t)_dma_txcommitted, ++ (di_pktpool_set_t)_dma_pktpool_set, ++ (di_rxtxerror_t)_dma_rxtx_error, ++ (di_burstlen_set_t)_dma_burstlen_set, ++ (di_avoidancecnt_t)_dma_avoidancecnt, ++ (di_param_set_t)_dma_param_set, ++ NULL, ++ NULL, ++ NULL, ++ 40 ++}; ++ ++EXPORT_SYMBOL(dma_attach); ++EXPORT_SYMBOL(dma64proc); ++ ++hnddma_t * ++dma_attach(osl_t *osh, const char *name, si_t *sih, ++ volatile void *dmaregstx, volatile void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, uint rxoffset, ++ uint *msg_level) ++{ ++ dma_info_t *di; ++ uint size; ++ uint32 mask; ++ ++ /* allocate private info structure */ ++ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { ++#ifdef BCMDBG ++ DMA_ERROR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); ++#endif ++ return (NULL); ++ } ++ ++ bzero(di, sizeof(dma_info_t)); ++ ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ spin_lock_init(&di->des_lock); ++ ++ /* old chips w/o sb is no longer supported */ ++ ASSERT(sih != NULL); ++ ++ if (DMA64_ENAB(di)) ++ di->dma64 = ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); ++ else ++ di->dma64 = 0; ++ ++ /* check arguments */ ++ ASSERT(ISPOWEROF2(ntxd)); ++ ASSERT(ISPOWEROF2(nrxd)); ++ ++ if (nrxd == 0) ++ ASSERT(dmaregsrx == NULL); ++ if (ntxd == 0) ++ ASSERT(dmaregstx == NULL); ++ ++ /* init dma reg pointer */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ di->d64txregs = (dma64regs_t *)dmaregstx; ++ di->d64rxregs = (dma64regs_t *)dmaregsrx; ++ di->hnddma.di_fn = (const di_fcn_t *)&dma64proc; ++ } else if (DMA32_ENAB(di)) { ++ ASSERT(ntxd <= D32MAXDD); ++ ASSERT(nrxd <= D32MAXDD); ++ di->d32txregs = (dma32regs_t *)dmaregstx; ++ di->d32rxregs = (dma32regs_t *)dmaregsrx; ++ di->hnddma.di_fn = (const di_fcn_t *)&dma32proc; ++ } else { ++ DMA_ERROR(("%s: driver doesn't support 32-bit DMA\n", __FUNCTION__)); ++ ASSERT(0); ++ goto fail; ++ } ++ ++ /* Default flags (which can be changed by the driver calling dma_ctrlflags ++ * before enable): For backwards compatibility both Rx Overflow Continue ++ * and Parity are DISABLED. ++ * supports it. ++ */ ++ di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); ++ ++ DMA_TRACE(("%s: %s: %s osh %p flags 0x%x ntxd %d nrxd %d rxbufsize %d " ++ "rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n", ++ name, __FUNCTION__, (DMA64_MODE(di) ? "DMA64" : "DMA32"), ++ osh, di->hnddma.dmactrlflags, ntxd, nrxd, ++ rxbufsize, rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); ++ ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL-1] = '\0'; ++ ++ di->osh = osh; ++ di->sih = sih; ++ ++ /* save tunables */ ++ di->ntxd = (uint16)ntxd; ++ di->nrxd = (uint16)nrxd; ++ ++ /* the actual dma size doesn't include the extra headroom */ ++ di->rxextrahdrroom = (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; ++ if (rxbufsize > BCMEXTRAHDROOM) ++ di->rxbufsize = (uint16)(rxbufsize - di->rxextrahdrroom); ++ else ++ di->rxbufsize = (uint16)rxbufsize; ++ ++ di->nrxpost = (uint16)nrxpost; ++ di->rxoffset = (uint8)rxoffset; ++ ++ /* Get the default values (POR) of the burstlen. This can be overridden by the modules ++ * if this has to be different. Otherwise this value will be used to program the control ++ * register after the reset or during the init. ++ */ ++ if (dmaregsrx) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ /* detect the dma descriptor address mask, ++ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 ++ */ ++ W_REG(di->osh, &di->d64rxregs->addrlow, 0xffffffff); ++ mask = R_REG(di->osh, &di->d64rxregs->addrlow); ++ ++ if (mask & 0xfff) ++ mask = R_REG(di->osh, &di->d64rxregs->ptr) | 0xf; ++ else ++ mask = 0x1fff; ++ ++ DMA_TRACE(("%s: dma_rx_mask: %08x\n", di->name, mask)); ++ di->d64_rs0_cd_mask = mask; ++ ++ if (mask == 0x1fff) ++ ASSERT(nrxd <= D64MAXDD); ++ else ++ ASSERT(nrxd <= D64MAXDD_LARGE); ++ ++ di->rxburstlen = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_BL_MASK) >> D64_RC_BL_SHIFT; ++ di->rxprefetchctl = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_PC_MASK) >> D64_RC_PC_SHIFT; ++ di->rxprefetchthresh = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_PT_MASK) >> D64_RC_PT_SHIFT; ++ } else if (DMA32_ENAB(di)) { ++ di->rxburstlen = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_BL_MASK) >> RC_BL_SHIFT; ++ di->rxprefetchctl = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_PC_MASK) >> RC_PC_SHIFT; ++ di->rxprefetchthresh = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_PT_MASK) >> RC_PT_SHIFT; ++ } ++ } ++ if (dmaregstx) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ++ /* detect the dma descriptor address mask, ++ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 ++ */ ++ W_REG(di->osh, &di->d64txregs->addrlow, 0xffffffff); ++ mask = R_REG(di->osh, &di->d64txregs->addrlow); ++ ++ if (mask & 0xfff) ++ mask = R_REG(di->osh, &di->d64txregs->ptr) | 0xf; ++ else ++ mask = 0x1fff; ++ ++ DMA_TRACE(("%s: dma_tx_mask: %08x\n", di->name, mask)); ++ di->d64_xs0_cd_mask = mask; ++ di->d64_xs1_ad_mask = mask; ++ ++ if (mask == 0x1fff) ++ ASSERT(ntxd <= D64MAXDD); ++ else ++ ASSERT(ntxd <= D64MAXDD_LARGE); ++ ++ di->txburstlen = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_BL_MASK) >> D64_XC_BL_SHIFT; ++ di->txmultioutstdrd = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_MR_MASK) >> D64_XC_MR_SHIFT; ++ di->txprefetchctl = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_PC_MASK) >> D64_XC_PC_SHIFT; ++ di->txprefetchthresh = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_PT_MASK) >> D64_XC_PT_SHIFT; ++ } else if (DMA32_ENAB(di)) { ++ di->txburstlen = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_BL_MASK) >> XC_BL_SHIFT; ++ di->txmultioutstdrd = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_MR_MASK) >> XC_MR_SHIFT; ++ di->txprefetchctl = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_PC_MASK) >> XC_PC_SHIFT; ++ di->txprefetchthresh = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_PT_MASK) >> XC_PT_SHIFT; ++ } ++ } ++ ++ /* force burstlen to 3 */ ++ di->rxburstlen = 3; ++ di->txburstlen = 3; ++ /* ++ * figure out the DMA physical address offset for dd and data ++ * Other bus: use zero ++ */ ++ di->ddoffsetlow = 0; ++ di->dataoffsetlow = 0; ++ ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED; ++#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ ++ ++ /* set addr ext fields */ ++ di->addrext = _dma_isaddrext(di); ++ ++ /* does the descriptors need to be aligned and if yes, on 4K/8K or not */ ++ di->aligndesc_4k = _dma_descriptor_align(di); ++ if (di->aligndesc_4k) { ++ if (DMA64_MODE(di)) { ++ di->dmadesc_align = D64RINGALIGN_BITS; ++ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { ++ /* for smaller dd table, HW relax the alignment requirement */ ++ di->dmadesc_align = D64RINGALIGN_BITS - 1; ++ } ++ } else ++ di->dmadesc_align = D32RINGALIGN_BITS; ++ } else { ++ /* The start address of descriptor table should be algined to cache line size, ++ * or other structure may share a cache line with it, which can lead to memory ++ * overlapping due to cache write-back operation. In the case of MIPS 74k, the ++ * cache line size is 32 bytes. ++ */ ++#ifdef __mips__ ++ di->dmadesc_align = 5; /* 32 byte alignment */ ++#else ++ di->dmadesc_align = 4; /* 16 byte alignment */ ++#endif ++ } ++ ++ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", ++ di->aligndesc_4k, di->dmadesc_align)); ++ ++ /* allocate tx packet pointer vector */ ++ if (ntxd) { ++ size = ntxd * sizeof(void *); ++ if ((di->txp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: %s: out of tx memory, malloced %d bytes\n", ++ di->name, __FUNCTION__, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero(di->txp, size); ++ } ++ ++ /* allocate rx packet pointer vector */ ++ if (nrxd) { ++ size = nrxd * sizeof(void *); ++ if ((di->rxp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: %s: out of rx memory, malloced %d bytes\n", ++ di->name, __FUNCTION__, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero(di->rxp, size); ++ } ++ ++ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ ++ if (ntxd) { ++ if (!_dma_alloc(di, DMA_TX)) ++ goto fail; ++ } ++ ++ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ ++ if (nrxd) { ++ if (!_dma_alloc(di, DMA_RX)) ++ goto fail; ++ } ++ ++ if ((di->ddoffsetlow != 0) && !di->addrext) { ++ if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: %s: txdpa 0x%x: addrext not supported\n", ++ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->txdpa))); ++ goto fail; ++ } ++ if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: %s: rxdpa 0x%x: addrext not supported\n", ++ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->rxdpa))); ++ goto fail; ++ } ++ } ++ ++ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " ++ "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, ++ di->dataoffsethigh, di->addrext)); ++ ++ /* allocate DMA mapping vectors */ ++ if (DMASGLIST_ENAB) { ++ if (ntxd) { ++ size = ntxd * sizeof(hnddma_seg_map_t); ++ if ((di->txp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero(di->txp_dmah, size); ++ } ++ ++ if (nrxd) { ++ size = nrxd * sizeof(hnddma_seg_map_t); ++ if ((di->rxp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero(di->rxp_dmah, size); ++ } ++ } ++ ++ return ((hnddma_t *)di); ++ ++fail: ++ _dma_detach(di); ++ return (NULL); ++} ++ ++/* init the tx or rx descriptor */ ++static INLINE void ++dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, ++ uint32 bufcount) ++{ ++ /* dma32 uses 32-bit control to fit both flags and bufcounter */ ++ *flags = *flags | (bufcount & CTRL_BC_MASK); ++ ++ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } else { ++ /* address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ *flags |= (ae << CTRL_AE_SHIFT); ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } ++} ++ ++/* Check for odd number of 1's */ ++STATIC INLINE uint32 parity32(uint32 data) ++{ ++ data ^= data >> 16; ++ data ^= data >> 8; ++ data ^= data >> 4; ++ data ^= data >> 2; ++ data ^= data >> 1; ++ ++ return (data & 1); ++} ++ ++#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2) ++ ++static INLINE void ++dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, ++ uint32 bufcount) ++{ ++ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ ++ /* PCI bus with big(>1G) physical address, use address extension */ ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ if ((di->dataoffsetlow == SI_SDRAM_SWAPPED) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++#else ++ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ ++ ASSERT((PHYSADDRHI(pa) & PCI64ADDR_HIGH) == 0); ++ ++ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh)); ++ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); ++ } else { ++ /* address extension for 32-bit PCI */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; ++ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(0 + di->dataoffsethigh)); ++ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); ++ } ++ if (di->hnddma.dmactrlflags & DMA_CTRL_PEN) { ++ if (DMA64_DD_PARITY(&ddring[outidx])) { ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY)); ++ } ++ } ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++/* Test */ ++#if defined(__arm__) ++ if (IS_IPROC_CHIP_ID(CHIPID(di->sih->chip))) ++ OSL_CACHE_FLUSH((uint)OSL_CACHED(&ddring[outidx]), sizeof(dma64dd_t)); ++#endif ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++static bool ++_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) ++{ ++ uint32 w; ++ ++ OR_REG(osh, &dma32regs->control, XC_AE); ++ w = R_REG(osh, &dma32regs->control); ++ AND_REG(osh, &dma32regs->control, ~XC_AE); ++ return ((w & XC_AE) == XC_AE); ++} ++ ++static bool ++_dma_alloc(dma_info_t *di, uint direction) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ return dma64_alloc(di, direction); ++ } else if (DMA32_ENAB(di)) { ++ return dma32_alloc(di, direction); ++ } else ++ ASSERT(0); ++} ++ ++/* !! may be called with core in reset */ ++static void ++_dma_detach(dma_info_t *di) ++{ ++ ++ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ ++ /* shouldn't be here if descriptors are unreclaimed */ ++ ASSERT(di->txin == di->txout); ++ ASSERT(di->rxin == di->rxout); ++ ++ /* free dma descriptor rings */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (di->txd64) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd64 - di->txdalign), ++ di->txdalloc, (di->txdpaorig), &di->tx_dmah); ++ if (di->rxd64) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd64 - di->rxdalign), ++ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); ++ } else if (DMA32_ENAB(di)) { ++ if (di->txd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd32 - di->txdalign), ++ di->txdalloc, (di->txdpaorig), &di->tx_dmah); ++ if (di->rxd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd32 - di->rxdalign), ++ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); ++ } else ++ ASSERT(0); ++ ++ /* free packet pointer vectors */ ++ if (di->txp) ++ MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *))); ++ if (di->rxp) ++ MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *))); ++ ++ /* free tx packet DMA handles */ ++ if (di->txp_dmah) ++ MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(hnddma_seg_map_t)); ++ ++ /* free rx packet DMA handles */ ++ if (di->rxp_dmah) ++ MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(hnddma_seg_map_t)); ++ ++ /* free our private info structure */ ++ MFREE(di->osh, (void *)di, sizeof(dma_info_t)); ++ ++} ++ ++static bool ++_dma_descriptor_align(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ uint32 addrl; ++ ++ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ ++ if (di->d64txregs != NULL) { ++ W_REG(di->osh, &di->d64txregs->addrlow, 0xff0); ++ addrl = R_REG(di->osh, &di->d64txregs->addrlow); ++ if (addrl != 0) ++ return FALSE; ++ } else if (di->d64rxregs != NULL) { ++ W_REG(di->osh, &di->d64rxregs->addrlow, 0xff0); ++ addrl = R_REG(di->osh, &di->d64rxregs->addrlow); ++ if (addrl != 0) ++ return FALSE; ++ } ++ } ++ return TRUE; ++} ++ ++/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ ++static bool ++_dma_isaddrext(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ ++ ++ /* not all tx or rx channel are available */ ++ if (di->d64txregs != NULL) { ++ if (!_dma64_addrext(di->osh, di->d64txregs)) { ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", ++ di->name)); ++ ASSERT(0); ++ } ++ return TRUE; ++ } else if (di->d64rxregs != NULL) { ++ if (!_dma64_addrext(di->osh, di->d64rxregs)) { ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", ++ di->name)); ++ ASSERT(0); ++ } ++ return TRUE; ++ } ++ return FALSE; ++ } else if (DMA32_ENAB(di)) { ++ if (di->d32txregs) ++ return (_dma32_addrext(di->osh, di->d32txregs)); ++ else if (di->d32rxregs) ++ return (_dma32_addrext(di->osh, di->d32rxregs)); ++ } else ++ ASSERT(0); ++ ++ return FALSE; ++} ++ ++/* initialize descriptor table base address */ ++static void ++_dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (!di->aligndesc_4k) { ++ if (direction == DMA_TX) ++ di->xmtptrbase = PHYSADDRLO(pa); ++ else ++ di->rcvptrbase = PHYSADDRLO(pa); ++ } ++ ++ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64txregs->addrhigh, (PHYSADDRHI(pa) + ++ di->ddoffsethigh)); ++ } else { ++ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64rxregs->addrhigh, (PHYSADDRHI(pa) + ++ di->ddoffsethigh)); ++ } ++ } else { ++ /* DMA64 32bits address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); ++ SET_REG(di->osh, &di->d64txregs->control, D64_XC_AE, ++ (ae << D64_XC_AE_SHIFT)); ++ } else { ++ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); ++ SET_REG(di->osh, &di->d64rxregs->control, D64_RC_AE, ++ (ae << D64_RC_AE_SHIFT)); ++ } ++ } ++ ++ } else if (DMA32_ENAB(di)) { ++ ASSERT(PHYSADDRHI(pa) == 0); ++ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) ++ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ else ++ W_REG(di->osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ } else { ++ /* dma32 address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <name)); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_LE); ++ else if (DMA32_ENAB(di)) ++ OR_REG(di->osh, &di->d32txregs->control, XC_LE); ++ else ++ ASSERT(0); ++} ++ ++static void ++_dma_rxinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ ++ if (di->nrxd == 0) { ++ return; ++ } ++ ++ /* During the reset procedure, the active rxd may not be zero if pktpool is ++ * enabled, we need to reclaim active rxd to avoid rxd being leaked. ++ */ ++ if ((POOL_ENAB(di->pktpool)) && (NRXDACTIVE(di->rxin, di->rxout))) { ++ _dma_rxreclaim(di); ++ } ++ ++ ASSERT(di->rxin == di->rxout); ++ di->rxin = di->rxout = di->rs0cd = 0; ++ ++ /* clear rx descriptor ring */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ BZERO_SM((void *)(uintptr)di->rxd64, (di->nrxd * sizeof(dma64dd_t))); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) { ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } ++ ++ _dma_rxenable(di); ++ ++ if (di->aligndesc_4k) { ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } ++ } else if (DMA32_ENAB(di)) { ++ BZERO_SM((void *)(uintptr)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); ++ _dma_rxenable(di); ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_rxenable(dma_info_t *di) ++{ ++ uint dmactrlflags = di->hnddma.dmactrlflags; ++ ++ DMA_TRACE(("%s: dma_rxenable\n", di->name)); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ uint32 control = (R_REG(di->osh, &di->d64rxregs->control) & D64_RC_AE) | D64_RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= D64_RC_OC; ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control &= ~D64_RC_BL_MASK; ++ control |= (di->rxburstlen << D64_RC_BL_SHIFT); ++ ++ control &= ~D64_RC_PC_MASK; ++ control |= (di->rxprefetchctl << D64_RC_PC_SHIFT); ++ ++ control &= ~D64_RC_PT_MASK; ++ control |= (di->rxprefetchthresh << D64_RC_PT_SHIFT); ++ ++ W_REG(di->osh, &di->d64rxregs->control, ++ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); ++ } else if (DMA32_ENAB(di)) { ++ uint32 control = (R_REG(di->osh, &di->d32rxregs->control) & RC_AE) | RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= RC_OC; ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control &= ~RC_BL_MASK; ++ control |= (di->rxburstlen << RC_BL_SHIFT); ++ ++ control &= ~RC_PC_MASK; ++ control |= (di->rxprefetchctl << RC_PC_SHIFT); ++ ++ control &= ~RC_PT_MASK; ++ control |= (di->rxprefetchthresh << RC_PT_SHIFT); ++ ++ W_REG(di->osh, &di->d32rxregs->control, ++ ((di->rxoffset << RC_RO_SHIFT) | control)); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize) ++{ ++ /* the normal values fit into 16 bits */ ++ *rxoffset = (uint16)di->rxoffset; ++ *rxbufsize = (uint16)di->rxbufsize; ++} ++ ++/* !! rx entry routine ++ * returns a pointer to the next frame received, or NULL if there are no more ++ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported ++ * with pkts chain ++ * otherwise, it's treated as giant pkt and will be tossed. ++ * The DMA scattering starts with normal DMA header, followed by first buffer data. ++ * After it reaches the max size of buffer, the data continues in next DMA descriptor ++ * buffer WITHOUT DMA header ++ */ ++static void * BCMFASTPATH ++_dma_rx(dma_info_t *di) ++{ ++ void *p, *head, *tail; ++ uint len; ++ uint pkt_len; ++ int resid = 0; ++#ifdef BCM4335 ++ dma64regs_t *dregs = di->d64rxregs; ++#endif ++ ++next_frame: ++ head = _dma_getnextrxp(di, FALSE); ++ if (head == NULL) ++ return (NULL); ++ ++ len = ltoh16(*(uint16 *)(PKTDATA(di->osh, head))); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ ++ /* set actual length */ ++ pkt_len = MIN((di->rxoffset + len), di->rxbufsize); ++ PKTSETLEN(di->osh, head, pkt_len); ++ resid = len - (di->rxbufsize - di->rxoffset); ++ ++ /* check for single or multi-buffer rx */ ++ if (resid <= 0) { ++ /* Single frame, all good */ ++ } else if (di->hnddma.dmactrlflags & DMA_CTRL_RXSINGLE) { ++ DMA_TRACE(("%s: dma_rx: corrupted length (%d)\n", di->name, len)); ++ PKTFREE(di->osh, head, FALSE); ++ di->hnddma.rxgiants++; ++ goto next_frame; ++ } else { ++ /* multi-buffer rx */ ++#ifdef BCMDBG ++ p = NULL; /* get rid of compiler warning */ ++#endif /* BCMDBG */ ++ tail = head; ++ while ((resid > 0) && (p = _dma_getnextrxp(di, FALSE))) { ++ PKTSETNEXT(di->osh, tail, p); ++ pkt_len = MIN(resid, (int)di->rxbufsize); ++ PKTSETLEN(di->osh, p, pkt_len); ++ ++ tail = p; ++ resid -= di->rxbufsize; ++ } ++ ++#ifdef BCMDBG ++ if (resid > 0) { ++ uint16 cur; ++ ASSERT(p == NULL); ++ cur = (DMA64_ENAB(di) && DMA64_MODE(di)) ? ++ B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t) : ++ B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, ++ dma32dd_t); ++ DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n", ++ di->rxin, di->rxout, cur)); ++ } ++#endif /* BCMDBG */ ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { ++ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); ++ PKTFREE(di->osh, head, FALSE); ++ di->hnddma.rxgiants++; ++ goto next_frame; ++ } ++ } ++ ++ return (head); ++} ++ ++/* post receive buffers ++ * return FALSE is refill failed completely and ring is empty ++ * this will stall the rx dma and user might want to call rxfill again asap ++ * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle ++ */ ++static bool BCMFASTPATH ++_dma_rxfill(dma_info_t *di) ++{ ++ void *p; ++ uint16 rxin, rxout; ++ uint32 flags = 0; ++ uint n; ++ uint i; ++ dmaaddr_t pa; ++ uint extra_offset = 0, extra_pad; ++ bool ring_empty; ++ uint alignment_req = (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) ? ++ 16 : 1; /* MUST BE POWER of 2 */ ++ ++ ring_empty = FALSE; ++ ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ ++ ++ rxin = di->rxin; ++ rxout = di->rxout; ++ ++ n = di->nrxpost - NRXDACTIVE(rxin, rxout); ++ ++ if (di->rxbufsize > BCMEXTRAHDROOM) ++ extra_offset = di->rxextrahdrroom; ++ ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ ++ for (i = 0; i < n; i++) { ++ /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the ++ size to be allocated ++ */ ++ if (POOL_ENAB(di->pktpool)) { ++ ASSERT(di->pktpool); ++ p = pktpool_get(di->pktpool); ++#ifdef BCMDBG_POOL ++ if (p) ++ PKTPOOLSETSTATE(p, POOL_RXFILL); ++#endif /* BCMDBG_POOL */ ++ } ++ else { ++ p = PKTGET(di->osh, (di->rxbufsize + extra_offset + alignment_req - 1), ++ FALSE); ++ } ++ if (p == NULL) { ++ DMA_TRACE(("%s: dma_rxfill: out of rxbufs\n", di->name)); ++ if (i == 0) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (dma64_rxidle(di)) { ++ DMA_TRACE(("%s: rxfill64: ring is empty !\n", ++ di->name)); ++ ring_empty = TRUE; ++ } ++ } else if (DMA32_ENAB(di)) { ++ if (dma32_rxidle(di)) { ++ DMA_TRACE(("%s: rxfill32: ring is empty !\n", ++ di->name)); ++ ring_empty = TRUE; ++ } ++ } else ++ ASSERT(0); ++ } ++ di->hnddma.rxnobuf++; ++ break; ++ } ++ /* reserve an extra headroom, if applicable */ ++ if (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) { ++ extra_pad = ((alignment_req - (uint)(((unsigned long)PKTDATA(di->osh, p) - ++ (unsigned long)(uchar *)0))) & (alignment_req - 1)); ++ } else ++ extra_pad = 0; ++ ++ if (extra_offset + extra_pad) ++ PKTPULL(di->osh, p, extra_offset + extra_pad); ++ ++#ifdef CTFMAP ++ /* mark as ctf buffer for fast mapping */ ++ if (CTF_ENAB(kcih)) { ++ ASSERT((((uint32)PKTDATA(di->osh, p)) & 31) == 0); ++ PKTSETCTF(di->osh, p); ++ } ++#endif /* CTFMAP */ ++ ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. ++ */ ++ *(uint16 *)(PKTDATA(di->osh, p)) = 0; ++ ++ if (DMASGLIST_ENAB) ++ bzero(&di->rxp_dmah[rxout], sizeof(hnddma_seg_map_t)); ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(PKTDATA(di->osh, p)); ++#else ++ pa = DMA_MAP(di->osh, PKTDATA(di->osh, p), ++ di->rxbufsize, DMA_RX, p, ++ &di->rxp_dmah[rxout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ ASSERT(ISALIGNED(PHYSADDRLO(pa), 4)); ++ ++ /* save the free packet pointer */ ++ ASSERT(di->rxp[rxout] == NULL); ++ di->rxp[rxout] = p; ++ ++ /* reset flags for each descriptor */ ++ flags = 0; ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (rxout == (di->nrxd - 1)) ++ flags = D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, di->rxbufsize); ++ } else if (DMA32_ENAB(di)) { ++ if (rxout == (di->nrxd - 1)) ++ flags = CTRL_EOT; ++ ++ ASSERT(PHYSADDRHI(pa) == 0); ++ dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); ++ } else ++ ASSERT(0); ++ rxout = NEXTRXD(rxout); ++ } ++ ++ di->rxout = rxout; ++ ++ /* update the chip lastdscr pointer */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ } else if (DMA32_ENAB(di)) { ++ W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); ++ } else ++ ASSERT(0); ++ ++ return ring_empty; ++} ++ ++/* like getnexttxp but no reclaim */ ++static void * ++_dma_peeknexttxp(dma_info_t *di) ++{ ++ uint16 end, i; ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ end = (uint16)B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ di->xs0cd = end; ++ } else if (DMA32_ENAB(di)) { ++ end = (uint16)B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = end; ++ } else ++ ASSERT(0); ++ ++ for (i = di->txin; i != end; i = NEXTTXD(i)) ++ if (di->txp[i]) ++ return (di->txp[i]); ++ ++ return (NULL); ++} ++ ++int ++_dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint act; ++ void *txp = NULL; ++ int k, len_max; ++ ++ DMA_TRACE(("%s: dma_peekntxp\n", di->name)); ++ ++ ASSERT(len); ++ ASSERT(txps); ++ ASSERT(di); ++ if (di->ntxd == 0) { ++ *len = 0; ++ return BCME_ERROR; ++ } ++ ++ len_max = *len; ++ *len = 0; ++ ++ start = di->txin; ++ ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ if (DMA64_ENAB(di)) { ++ end = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ ++ act = (uint)(R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK); ++ act = (act - di->xmtptrbase) & D64_XS0_CD_MASK; ++ act = (uint)B2I(act, dma64dd_t); ++ } else { ++ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ ++ act = (uint)((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> ++ XS_AD_SHIFT); ++ act = (uint)B2I(act, dma32dd_t); ++ } ++ ++ di->xs0cd = end; ++ if (end != act) ++ end = PREVTXD(act); ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ return BCME_ERROR; ++ ++ k = 0; ++ for (i = start; i != end; i = NEXTTXD(i)) { ++ txp = di->txp[i]; ++ if (txp != NULL) { ++ if (k < len_max) ++ txps[k++] = txp; ++ else ++ break; ++ } ++ } ++ *len = k; ++ ++ return BCME_OK; ++} ++ ++/* like getnextrxp but not take off the ring */ ++static void * ++_dma_peeknextrxp(dma_info_t *di) ++{ ++ uint16 end, i; ++ ++ if (di->nrxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ end = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ di->rs0cd = end; ++ } else if (DMA32_ENAB(di)) { ++ end = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); ++ di->rs0cd = end; ++ } else ++ ASSERT(0); ++ ++ for (i = di->rxin; i != end; i = NEXTRXD(i)) ++ if (di->rxp[i]) ++ return (di->rxp[i]); ++ ++ return (NULL); ++} ++ ++static void ++_dma_rxreclaim(dma_info_t *di) ++{ ++ void *p; ++ bool origcb = TRUE; ++ ++#ifndef EFI ++ /* "unused local" warning suppression for OSLs that ++ * define PKTFREE() without using the di->osh arg ++ */ ++ di = di; ++#endif /* EFI */ ++ ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ ++ if (POOL_ENAB(di->pktpool) && ++ ((origcb = pktpool_emptycb_disabled(di->pktpool)) == FALSE)) ++ pktpool_emptycb_disable(di->pktpool, TRUE); ++ ++ while ((p = _dma_getnextrxp(di, TRUE))) ++ PKTFREE(di->osh, p, FALSE); ++ ++ if (origcb == FALSE) ++ pktpool_emptycb_disable(di->pktpool, FALSE); ++} ++ ++static void * BCMFASTPATH ++_dma_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ if (di->nrxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ return dma64_getnextrxp(di, forceall); ++ } else if (DMA32_ENAB(di)) { ++ return dma32_getnextrxp(di, forceall); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_txblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = 0; ++} ++ ++static void ++_dma_txunblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++} ++ ++static uint ++_dma_txactive(dma_info_t *di) ++{ ++ return NTXDACTIVE(di->txin, di->txout); ++} ++ ++static uint ++_dma_txpending(dma_info_t *di) ++{ ++ uint16 curr; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ curr = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ di->xs0cd = curr; ++ } else if (DMA32_ENAB(di)) { ++ curr = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = curr; ++ } else ++ ASSERT(0); ++ ++ return NTXDACTIVE(curr, di->txout); ++} ++ ++static uint ++_dma_txcommitted(dma_info_t *di) ++{ ++ uint16 ptr; ++ uint txin = di->txin; ++ ++ if (txin == di->txout) ++ return 0; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ptr = B2I(R_REG(di->osh, &di->d64txregs->ptr), dma64dd_t); ++ } else if (DMA32_ENAB(di)) { ++ ptr = B2I(R_REG(di->osh, &di->d32txregs->ptr), dma32dd_t); ++ } else ++ ASSERT(0); ++ ++ return NTXDACTIVE(di->txin, ptr); ++} ++ ++static uint ++_dma_rxactive(dma_info_t *di) ++{ ++ return NRXDACTIVE(di->rxin, di->rxout); ++} ++ ++static uint ++_dma_activerxbuf(dma_info_t *di) ++{ ++ uint16 curr, ptr; ++ curr = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ ptr = B2I(((R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ return NRXDACTIVE(curr, ptr); ++} ++ ++ ++static void ++_dma_counterreset(dma_info_t *di) ++{ ++ /* reset all software counter */ ++ di->hnddma.rxgiants = 0; ++ di->hnddma.rxnobuf = 0; ++ di->hnddma.txnobuf = 0; ++} ++ ++static uint ++_dma_ctrlflags(dma_info_t *di, uint mask, uint flags) ++{ ++ uint dmactrlflags; ++ ++ if (!di) { ++ DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n")); ++ return (0); ++ } ++ ++ dmactrlflags = di->hnddma.dmactrlflags; ++ ASSERT((flags & ~mask) == 0); ++ ++ dmactrlflags &= ~mask; ++ dmactrlflags |= flags; ++ ++ /* If trying to enable parity, check if parity is actually supported */ ++ if (dmactrlflags & DMA_CTRL_PEN) { ++ uint32 control; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ control = R_REG(di->osh, &di->d64txregs->control); ++ W_REG(di->osh, &di->d64txregs->control, control | D64_XC_PD); ++ if (R_REG(di->osh, &di->d64txregs->control) & D64_XC_PD) { ++ /* We *can* disable it so it is supported, ++ * restore control register ++ */ ++ W_REG(di->osh, &di->d64txregs->control, control); ++ } else { ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ } else if (DMA32_ENAB(di)) { ++ control = R_REG(di->osh, &di->d32txregs->control); ++ W_REG(di->osh, &di->d32txregs->control, control | XC_PD); ++ if (R_REG(di->osh, &di->d32txregs->control) & XC_PD) { ++ W_REG(di->osh, &di->d32txregs->control, control); ++ } else { ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ } else ++ ASSERT(0); ++ } ++ ++ di->hnddma.dmactrlflags = dmactrlflags; ++ ++ return (dmactrlflags); ++} ++ ++/* get the address of the var in order to change later */ ++static uintptr ++_dma_getvar(dma_info_t *di, const char *name) ++{ ++ if (!strcmp(name, "&txavail")) ++ return ((uintptr) &(di->hnddma.txavail)); ++ else { ++ ASSERT(0); ++ } ++ return (0); ++} ++ ++static uint ++_dma_avoidancecnt(dma_info_t *di) ++{ ++ return (di->dma_avoidance_cnt); ++} ++ ++void ++dma_txpioloopback(osl_t *osh, dma32regs_t *regs) ++{ ++ OR_REG(osh, ®s->control, XC_LE); ++} ++ ++static ++uint8 dma_align_sizetobits(uint size) ++{ ++ uint8 bitpos = 0; ++ ASSERT(size); ++ ASSERT(!(size & (size-1))); ++ while (size >>= 1) { ++ bitpos ++; ++ } ++ return (bitpos); ++} ++ ++/* This function ensures that the DMA descriptor ring will not get allocated ++ * across Page boundary. If the allocation is done across the page boundary ++ * at the first time, then it is freed and the allocation is done at ++ * descriptor ring size aligned location. This will ensure that the ring will ++ * not cross page boundary ++ */ ++static void * ++dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, ++ dmaaddr_t *descpa, osldma_t **dmah) ++{ ++ void * va; ++ uint32 desc_strtaddr; ++ uint32 alignbytes = 1 << *alignbits; ++ ++ if ((va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah)) == NULL) ++ return NULL; ++ ++ /* printk("%s va(0x%x)\n", __FUNCTION__, va); */ ++ desc_strtaddr = (uint32)ROUNDUP((uint)PHYSADDRLO(*descpa), alignbytes); ++ if (((desc_strtaddr + size - 1) & boundary) != ++ (desc_strtaddr & boundary)) { ++ *alignbits = dma_align_sizetobits(size); ++ DMA_FREE_CONSISTENT(osh, va, ++ size, *descpa, dmah); ++ va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah); ++ } ++ return va; ++} ++ ++#if defined(BCMDBG) ++static void ++dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, uint end, ++ uint max_num) ++{ ++ uint i; ++ ++ for (i = start; i != end; i = XXD((i + 1), max_num)) { ++ /* in the format of high->low 8 bytes */ ++ bcm_bprintf(b, "ring index %d: 0x%x %x\n", ++ i, R_SM(&ring[i].addr), R_SM(&ring[i].ctrl)); ++ } ++} ++ ++static void ++dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->ntxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA32: txd32 %p txdpa 0x%lx txp %p txin %d txout %d " ++ "txavail %d txnodesc %d\n", di->txd32, PHYSADDRLO(di->txdpa), di->txp, di->txin, ++ di->txout, di->hnddma.txavail, di->hnddma.txnodesc); ++ ++ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%x\n", ++ R_REG(di->osh, &di->d32txregs->control), ++ R_REG(di->osh, &di->d32txregs->addr), ++ R_REG(di->osh, &di->d32txregs->ptr), ++ R_REG(di->osh, &di->d32txregs->status)); ++ ++ if (dumpring && di->txd32) ++ dma32_dumpring(di, b, di->txd32, di->txin, di->txout, di->ntxd); ++} ++ ++static void ++dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->nrxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA32: rxd32 %p rxdpa 0x%lx rxp %p rxin %d rxout %d\n", ++ di->rxd32, PHYSADDRLO(di->rxdpa), di->rxp, di->rxin, di->rxout); ++ ++ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%x\n", ++ R_REG(di->osh, &di->d32rxregs->control), ++ R_REG(di->osh, &di->d32rxregs->addr), ++ R_REG(di->osh, &di->d32rxregs->ptr), ++ R_REG(di->osh, &di->d32rxregs->status)); ++ if (di->rxd32 && dumpring) ++ dma32_dumpring(di, b, di->rxd32, di->rxin, di->rxout, di->nrxd); ++} ++ ++static void ++dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ dma32_dumptx(di, b, dumpring); ++ dma32_dumprx(di, b, dumpring); ++} ++ ++static void ++dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, uint end, ++ uint max_num) ++{ ++ uint i; ++ ++ for (i = start; i != end; i = XXD((i + 1), max_num)) { ++ /* in the format of high->low 16 bytes */ ++ bcm_bprintf(b, "ring index %d: 0x%x %x %x %x\n", ++ i, R_SM(&ring[i].addrhigh), R_SM(&ring[i].addrlow), ++ R_SM(&ring[i].ctrl2), R_SM(&ring[i].ctrl1)); ++ } ++} ++ ++static void ++dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->ntxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA64: txd64 %p txdpa 0x%lx txdpahi 0x%lx txp %p txin %d txout %d " ++ "txavail %d txnodesc %d\n", di->txd64, PHYSADDRLO(di->txdpa), ++ PHYSADDRHI(di->txdpaorig), di->txp, di->txin, di->txout, di->hnddma.txavail, ++ di->hnddma.txnodesc); ++ ++ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddrlow 0x%x xmtaddrhigh 0x%x " ++ "xmtptr 0x%x xmtstatus0 0x%x xmtstatus1 0x%x\n", ++ R_REG(di->osh, &di->d64txregs->control), ++ R_REG(di->osh, &di->d64txregs->addrlow), ++ R_REG(di->osh, &di->d64txregs->addrhigh), ++ R_REG(di->osh, &di->d64txregs->ptr), ++ R_REG(di->osh, &di->d64txregs->status0), ++ R_REG(di->osh, &di->d64txregs->status1)); ++ ++ bcm_bprintf(b, "DMA64: DMA avoidance applied %d\n", di->dma_avoidance_cnt); ++ ++ if (dumpring && di->txd64) { ++ dma64_dumpring(di, b, di->txd64, di->txin, di->txout, di->ntxd); ++ } ++} ++ ++static void ++dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->nrxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA64: rxd64 %p rxdpa 0x%lx rxdpahi 0x%lx rxp %p rxin %d rxout %d\n", ++ di->rxd64, PHYSADDRLO(di->rxdpa), PHYSADDRHI(di->rxdpaorig), di->rxp, ++ di->rxin, di->rxout); ++ ++ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddrlow 0x%x rcvaddrhigh 0x%x rcvptr " ++ "0x%x rcvstatus0 0x%x rcvstatus1 0x%x\n", ++ R_REG(di->osh, &di->d64rxregs->control), ++ R_REG(di->osh, &di->d64rxregs->addrlow), ++ R_REG(di->osh, &di->d64rxregs->addrhigh), ++ R_REG(di->osh, &di->d64rxregs->ptr), ++ R_REG(di->osh, &di->d64rxregs->status0), ++ R_REG(di->osh, &di->d64rxregs->status1)); ++ if (di->rxd64 && dumpring) { ++ dma64_dumpring(di, b, di->rxd64, di->rxin, di->rxout, di->nrxd); ++ } ++} ++ ++static void ++dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ dma64_dumptx(di, b, dumpring); ++ dma64_dumprx(di, b, dumpring); ++} ++ ++#endif ++ ++ ++/* 32-bit DMA functions */ ++ ++static void ++dma32_txinit(dma_info_t *di) ++{ ++ uint32 control = XC_XE; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = di->xs0cd = 0; ++ di->hnddma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ BZERO_SM(DISCARD_QUAL(di->txd32, void), (di->ntxd * sizeof(dma32dd_t))); ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control |= (di->txburstlen << XC_BL_SHIFT); ++ control |= (di->txmultioutstdrd << XC_MR_SHIFT); ++ control |= (di->txprefetchctl << XC_PC_SHIFT); ++ control |= (di->txprefetchthresh << XC_PT_SHIFT); ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= XC_PD; ++ W_REG(di->osh, &di->d32txregs->control, control); ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++static bool ++dma32_txenabled(dma_info_t *di) ++{ ++ uint32 xc; ++ ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d32txregs->control); ++ return ((xc != 0xffffffff) && (xc & XC_XE)); ++} ++ ++static void ++dma32_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE); ++} ++ ++static void ++dma32_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); ++} ++ ++static bool ++dma32_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); ++} ++ ++#ifdef WL_MULTIQUEUE ++static void ++dma32_txflush(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txflush\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE | XC_FL); ++} ++ ++static void ++dma32_txflush_clear(dma_info_t *di) ++{ ++ uint32 status; ++ ++ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_FL); ++} ++#endif /* WL_MULTIQUEUE */ ++ ++static void ++dma32_txreclaim(dma_info_t *di, txd_range_t range) ++{ ++ void *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma32_getnexttxp(di, range))) ++ PKTFREE(di->osh, p, TRUE); ++} ++ ++static bool ++dma32_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); ++} ++ ++static bool ++dma32_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); ++} ++ ++static bool ++dma32_alloc(dma_info_t *di, uint direction) ++{ ++ uint size; ++ uint ddlen; ++ void *va; ++ uint alloced; ++ uint16 align; ++ uint16 align_bits; ++ ++ ddlen = sizeof(dma32dd_t); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ ++ alloced = 0; ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, ++ &di->txdpaorig, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ ++ PHYSADDRHISET(di->txdpa, 0); ++ ASSERT(PHYSADDRHI(di->txdpaorig) == 0); ++ di->txd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); ++ di->txdalign = (uint)((int8 *)(uintptr)di->txd32 - (int8 *)va); ++ ++ PHYSADDRLOSET(di->txdpa, PHYSADDRLO(di->txdpaorig) + di->txdalign); ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); ++ ++ di->txdalloc = alloced; ++ ASSERT(ISALIGNED(di->txd32, align)); ++ } else { ++ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, ++ &di->rxdpaorig, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ ++ PHYSADDRHISET(di->rxdpa, 0); ++ ASSERT(PHYSADDRHI(di->rxdpaorig) == 0); ++ di->rxd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); ++ di->rxdalign = (uint)((int8 *)(uintptr)di->rxd32 - (int8 *)va); ++ ++ PHYSADDRLOSET(di->rxdpa, PHYSADDRLO(di->rxdpaorig) + di->rxdalign); ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); ++ di->rxdalloc = alloced; ++ ASSERT(ISALIGNED(di->rxd32, align)); ++ } ++ ++ return TRUE; ++} ++ ++static bool ++dma32_txreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d32txregs->control, XC_SE); ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ ++ W_REG(di->osh, &di->d32txregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED), ++ 10000); ++ ++ /* We should be disabled at this point */ ++ if (status != XS_XS_DISABLED) { ++ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); ++ ASSERT(status == XS_XS_DISABLED); ++ OSL_DELAY(300); ++ } ++ ++ return (status == XS_XS_DISABLED); ++} ++ ++static bool ++dma32_rxidle(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == ++ R_REG(di->osh, &di->d32rxregs->ptr)); ++} ++ ++static bool ++dma32_rxreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d32rxregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED), ++ 10000); ++ ++ return (status == RS_RS_DISABLED); ++} ++ ++static bool ++dma32_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d32rxregs->control); ++ return ((rc != 0xffffffff) && (rc & RC_RE)); ++} ++ ++static bool ++dma32_txsuspendedidle(dma_info_t *di) ++{ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) ++ return 0; ++ ++ OSL_DELAY(2); ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); ++} ++ ++/* !! tx entry routine ++ * supports full 32bit dma engine buffer addressing so ++ * dma buffers can cross 4 Kbyte page boundaries. ++ * ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems ++ */ ++static int ++dma32_txfast(dma_info_t *di, void *p0, bool commit) ++{ ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ uint nsegs, j; ++ hnddma_seg_map_t *map; ++ ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++#ifdef BCM_DMAPAD ++ len += PKTDMAPAD(di->osh, p); ++#endif ++ next = PKTNEXT(di->osh, p); ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ if (DMASGLIST_ENAB) ++ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); ++ ++ /* get physical address of buffer start */ ++ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[txout]; ++ ++ /* See if all the segments can be accounted for */ ++ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) ++ goto outoftxd; ++ ++ nsegs = map->nsegs; ++ } else ++ nsegs = 1; ++ ++ for (j = 1; j <= nsegs; j++) { ++ flags = 0; ++ if (p == p0 && j == 1) ++ flags |= CTRL_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when ++ * end of segment list is reached. ++ */ ++ if ((!DMASGLIST_ENAB && next == NULL) || ++ (DMASGLIST_ENAB && j == nsegs)) ++ flags |= (CTRL_IOC | CTRL_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= CTRL_EOT; ++ ++ if (DMASGLIST_ENAB) { ++ len = map->segs[j - 1].length; ++ pa = map->segs[j - 1].addr; ++ } ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ dma32_dd_upd(di, di->txd32, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); ++ } ++ ++ /* See above. No need to loop over individual buffers */ ++ if (DMASGLIST_ENAB) ++ break; ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & CTRL_EOF)) ++ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF)); ++ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ di->hnddma.txnodesc++; ++ return (-1); ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++static void * ++dma32_getnexttxp(dma_info_t *di, txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint16 active_desc; ++ void *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ dma32regs_t *dregs = di->d32txregs; ++ ++ if (di->txin == di->xs0cd) { ++ end = (uint16)B2I(R_REG(di->osh, &dregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = end; ++ } else ++ end = di->xs0cd; ++ ++ if (range == HNDDMA_RANGE_TRANSFERED) { ++ active_desc = (uint16)((R_REG(di->osh, &dregs->status) & XS_AD_MASK) >> ++ XS_AD_SHIFT); ++ active_desc = (uint16)B2I(active_desc, dma32dd_t); ++ if (end != active_desc) ++ end = PREVTXD(active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ dmaaddr_t pa; ++ hnddma_seg_map_t *map = NULL; ++ uint size, j, nsegs; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, 0); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[i]; ++ size = map->origsize; ++ nsegs = map->nsegs; ++ } else { ++ size = (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK); ++ nsegs = 1; ++ } ++ ++ for (j = nsegs; j > 0; j--) { ++ W_SM(&di->txd32[i].addr, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ if (j > 1) ++ i = NEXTTXD(i); ++ } ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (txp); ++ ++bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++ return (NULL); ++} ++ ++static void * ++dma32_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ uint16 i, curr; ++ void *rxp; ++ dmaaddr_t pa; ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma32_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++ if (di->rxin == di->rs0cd) { ++ curr = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); ++ di->rs0cd = curr; ++ } else ++ curr = di->rs0cd; ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, 0); ++ ++ /* clear this packet from the descriptor ring */ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, ++ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ W_SM(&di->rxd32[i].addr, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); ++} ++ ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma32_txrotate(dma_info_t *di) ++{ ++ uint16 ad; ++ uint nactive; ++ uint rot; ++ uint16 old, new; ++ uint32 w; ++ uint16 first, last; ++ ++ ASSERT(dma32_txsuspendedidle(di)); ++ ++ nactive = _dma_txactive(di); ++ ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); ++ rot = TXD(ad - di->txin); ++ ++ ASSERT(rot < di->ntxd); ++ ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } ++ ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= CTRL_EOT; ++ W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w)); ++ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); ++ ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef)); ++ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ ++ /* Move the segment map as well */ ++ if (DMASGLIST_ENAB) { ++ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); ++ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); ++ } ++ ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); ++} ++ ++/* 64-bit DMA functions */ ++ ++static void ++dma64_txinit(dma_info_t *di) ++{ ++ uint32 control; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = di->xs0cd = di->xs0cd_snapshot = 0; ++ di->hnddma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ BZERO_SM((void *)(uintptr)di->txd64, (di->ntxd * sizeof(dma64dd_t))); ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control = R_REG(di->osh, &di->d64txregs->control); ++ control = (control & ~D64_XC_BL_MASK) | (di->txburstlen << D64_XC_BL_SHIFT); ++ control = (control & ~D64_XC_MR_MASK) | (di->txmultioutstdrd << D64_XC_MR_SHIFT); ++ control = (control & ~D64_XC_PC_MASK) | (di->txprefetchctl << D64_XC_PC_SHIFT); ++ control = (control & ~D64_XC_PT_MASK) | (di->txprefetchthresh << D64_XC_PT_SHIFT); ++ W_REG(di->osh, &di->d64txregs->control, control); ++ ++ control = D64_XC_XE; ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_XC_PD; ++ OR_REG(di->osh, &di->d64txregs->control, control); ++ ++ /* DMA engine with alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++static bool ++dma64_txenabled(dma_info_t *di) ++{ ++ uint32 xc; ++ ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d64txregs->control); ++ return ((xc != 0xffffffff) && (xc & D64_XC_XE)); ++} ++ ++static void ++dma64_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE); ++} ++ ++static void ++dma64_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_SE); ++} ++ ++static bool ++dma64_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ++ ((R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); ++} ++ ++#ifdef WL_MULTIQUEUE ++static void ++dma64_txflush(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txflush\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE | D64_XC_FL); ++} ++ ++static void ++dma64_txflush_clear(dma_info_t *di) ++{ ++ uint32 status; ++ ++ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED) && ++ (status != D64_XS0_XS_IDLE) && ++ (status != D64_XS0_XS_STOPPED), ++ 10000); ++ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_FL); ++} ++#endif /* WL_MULTIQUEUE */ ++ ++static void BCMFASTPATH ++dma64_txreclaim(dma_info_t *di, txd_range_t range) ++{ ++ void *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma64_getnexttxp(di, range))) { ++ /* For unframed data, we don't have any packets to free */ ++ if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED)) ++ PKTFREE(di->osh, p, TRUE); ++ } ++} ++ ++static bool ++dma64_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); ++} ++ ++static bool ++dma64_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); ++} ++ ++static bool ++dma64_alloc(dma_info_t *di, uint direction) ++{ ++ uint32 size; ++ uint ddlen; ++ void *va; ++ uint alloced = 0; ++ uint32 align; ++ uint16 align_bits; ++ ++ ddlen = sizeof(dma64dd_t); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ if ((va = dma_ringalloc(di->osh, ++ (di->d64_xs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, ++ size, &align_bits, &alloced, ++ &di->txdpaorig, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ align = (1 << align_bits); ++ ++ /* adjust the pa by rounding up to the alignment */ ++ PHYSADDRLOSET(di->txdpa, ROUNDUP(PHYSADDRLO(di->txdpaorig), align)); ++ PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig)); ++ ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); ++ ++ /* find the alignment offset that was used */ ++ di->txdalign = (uint)(PHYSADDRLO(di->txdpa) - PHYSADDRLO(di->txdpaorig)); ++ ++ /* adjust the va by the same offset */ ++ di->txd64 = (dma64dd_t *)((uintptr)va + di->txdalign); ++ ++ /* printk("%s di->txd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txd64), PHYSADDRLO(di->txd64)); */ ++ /* printk("%s di->txdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txdpa), PHYSADDRLO(di->txdpa)); */ ++ di->txdalloc = alloced; ++ ASSERT(ISALIGNED(PHYSADDRLO(di->txdpa), align)); ++ } else { ++ if ((va = dma_ringalloc(di->osh, ++ (di->d64_rs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, ++ size, &align_bits, &alloced, ++ &di->rxdpaorig, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ align = (1 << align_bits); ++ ++ /* adjust the pa by rounding up to the alignment */ ++ PHYSADDRLOSET(di->rxdpa, ROUNDUP(PHYSADDRLO(di->rxdpaorig), align)); ++ PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig)); ++ ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); ++ ++ /* find the alignment offset that was used */ ++ di->rxdalign = (uint)(PHYSADDRLO(di->rxdpa) - PHYSADDRLO(di->rxdpaorig)); ++ ++ /* adjust the va by the same offset */ ++ di->rxd64 = (dma64dd_t *)((uintptr)va + di->rxdalign); ++ ++ /* printk("%s di->rxd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxd64), PHYSADDRLO(di->rxd64)); */ ++ /* printk("%s di->rxdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxdpa), PHYSADDRLO(di->rxdpa)); */ ++ di->rxdalloc = alloced; ++ ASSERT(ISALIGNED(PHYSADDRLO(di->rxdpa), align)); ++ } ++ ++ return TRUE; ++} ++ ++static bool ++dma64_txreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d64txregs->control, D64_XC_SE); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED) && ++ (status != D64_XS0_XS_IDLE) && ++ (status != D64_XS0_XS_STOPPED), ++ 10000); ++ ++ W_REG(di->osh, &di->d64txregs->control, 0); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED), ++ 10000); ++ ++ /* We should be disabled at this point */ ++ if (status != D64_XS0_XS_DISABLED) { ++ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); ++ ASSERT(status == D64_XS0_XS_DISABLED); ++ OSL_DELAY(300); ++ } ++ ++ return (status == D64_XS0_XS_DISABLED); ++} ++ ++static bool ++dma64_rxidle(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) == ++ (R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK)); ++} ++ ++static bool ++dma64_rxreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d64rxregs->control, 0); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK)) != ++ D64_RS0_RS_DISABLED), 10000); ++ ++ return (status == D64_RS0_RS_DISABLED); ++} ++ ++static bool ++dma64_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d64rxregs->control); ++ return ((rc != 0xffffffff) && (rc & D64_RC_RE)); ++} ++ ++static bool ++dma64_txsuspendedidle(dma_info_t *di) ++{ ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) ++ return 1; ++ ++ return 0; ++} ++ ++/* Useful when sending unframed data. This allows us to get a progress report from the DMA. ++ * We return a pointer to the beginning of the data buffer of the current descriptor. ++ * If DMA is idle, we return NULL. ++ */ ++static void* ++dma64_getpos(dma_info_t *di, bool direction) ++{ ++ void *va; ++ bool idle; ++ uint16 cur_idx; ++ ++ if (direction == DMA_TX) { ++ cur_idx = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ idle = !NTXDACTIVE(di->txin, di->txout); ++ va = di->txp[cur_idx]; ++ } else { ++ cur_idx = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ idle = !NRXDACTIVE(di->rxin, di->rxout); ++ va = di->rxp[cur_idx]; ++ } ++ ++ /* If DMA is IDLE, return NULL */ ++ if (idle) { ++ DMA_TRACE(("%s: DMA idle, return NULL\n", __FUNCTION__)); ++ va = NULL; ++ } ++ ++ return va; ++} ++ ++/* TX of unframed data ++ * ++ * Adds a DMA ring descriptor for the data pointed to by "buf". ++ * This is for DMA of a buffer of data and is unlike other hnddma TX functions ++ * that take a pointer to a "packet" ++ * Each call to this is results in a single descriptor being added for "len" bytes of ++ * data starting at "buf", it doesn't handle chained buffers. ++ */ ++static int ++dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit) ++{ ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; /* phys addr */ ++ ++ txout = di->txout; ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ return 0; ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(buf); ++#else ++ pa = DMA_MAP(di->osh, buf, len, DMA_TX, NULL, &di->txp_dmah[txout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ /* save the buffer pointer - used by dma_getpos */ ++ di->txp[txout] = buf; ++ ++ txout = NEXTTXD(txout); ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) { ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); ++ } ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __FUNCTION__)); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); ++} ++ ++/* RX of unframed data ++ * ++ * Adds a DMA ring descriptor for the data pointed to by "buf". ++ * This is for DMA of a buffer of data and is unlike other hnddma TX functions ++ * that take a pointer to a "packet" ++ * Each call to this is results in a single descriptor being added for "len" bytes of ++ * data starting at "buf", it doesn't handle chained buffers. ++ */ ++static int ++dma64_rxunframed(dma_info_t *di, void *buf, uint len, bool commit) ++{ ++ uint16 rxout; ++ uint32 flags = 0; ++ dmaaddr_t pa; /* phys addr */ ++ ++ rxout = di->rxout; ++ ++ /* return nonzero if out of rx descriptors */ ++ if (NEXTRXD(rxout) == di->rxin) ++ goto outofrxd; ++ ++ if (len == 0) ++ return 0; ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(buf); ++#else ++ pa = DMA_MAP(di->osh, buf, len, DMA_RX, NULL, &di->rxp_dmah[rxout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ if (rxout == (di->nrxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, len); ++ ASSERT(di->rxp[rxout] == NULL); ++ ++ /* save the buffer pointer - used by dma_getpos */ ++ di->rxp[rxout] = buf; ++ ++ rxout = NEXTRXD(rxout); ++ /* bump the tx descriptor index */ ++ di->rxout = rxout; ++ ++ /* kick the chip */ ++ if (commit) { ++ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ //DBG("%s (Control Reg)W_REG: 0x%x Value: 0x%x\n", __FUNCTION__, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ } ++ ++ /* tx flow control */ ++ //di->hnddma.rxavail = di->nrxd - NRXDACTIVE(di->rxin, di->rxout) - 1; ++ ++ return (0); ++ ++outofrxd: ++ DMA_ERROR(("%s: %s: out of rxds !!!\n", di->name, __FUNCTION__)); ++ //di->hnddma.rxavail = 0; ++ di->hnddma.rxnobuf++; ++ return (-1); ++} ++ ++/* !! tx entry routine ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems ++ */ ++static int BCMFASTPATH ++dma64_txfast(dma_info_t *di, void *p0, bool commit) ++{ ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; ++ bool war; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ war = (di->hnddma.dmactrlflags & DMA_CTRL_DMA_AVOIDANCE_WAR) ? TRUE : FALSE; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ uint nsegs, j, segsadd; ++ hnddma_seg_map_t *map = NULL; ++ ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++#ifdef BCM_DMAPAD ++ len += PKTDMAPAD(di->osh, p); ++#endif /* BCM_DMAPAD */ ++ next = PKTNEXT(di->osh, p); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(next, SKB_PREFETCH_LEN); ++#endif ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ /* get physical address of buffer start */ ++ if (DMASGLIST_ENAB) ++ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(data); ++#else ++ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[txout]; ++ ++ /* See if all the segments can be accounted for */ ++ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) ++ goto outoftxd; ++ ++ nsegs = map->nsegs; ++ } else ++ nsegs = 1; ++ ++ segsadd = 0; ++ for (j = 1; j <= nsegs; j++) { ++ flags = 0; ++ if (p == p0 && j == 1) ++ flags |= D64_CTRL1_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when ++ * end of segment list is reached. ++ */ ++ if ((!DMASGLIST_ENAB && next == NULL) || ++ (DMASGLIST_ENAB && j == nsegs)) ++ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ if (DMASGLIST_ENAB) { ++ len = map->segs[j - 1].length; ++ pa = map->segs[j - 1].addr; ++ if (len > 128 && war) { ++ uint remain, new_len, align64; ++ /* check for 64B aligned of pa */ ++ align64 = (uint)(PHYSADDRLO(pa) & 0x3f); ++ align64 = (64 - align64) & 0x3f; ++ new_len = len - align64; ++ remain = new_len % 128; ++ if (remain > 0 && remain <= 4) { ++ uint32 buf_addr_lo; ++ uint32 tmp_flags = ++ flags & (~(D64_CTRL1_EOF | D64_CTRL1_IOC)); ++ flags &= ~(D64_CTRL1_SOF | D64_CTRL1_EOT); ++ remain += 64; ++ dma64_dd_upd(di, di->txd64, pa, txout, ++ &tmp_flags, len-remain); ++ ASSERT(di->txp[txout] == NULL); ++ txout = NEXTTXD(txout); ++ /* return nonzero if out of tx descriptors */ ++ if (txout == di->txin) { ++ DMA_ERROR(("%s: dma_txfast: Out-of-DMA" ++ " descriptors (txin %d txout %d" ++ " nsegs %d)\n", __FUNCTION__, ++ di->txin, di->txout, nsegs)); ++ goto outoftxd; ++ } ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ buf_addr_lo = PHYSADDRLO(pa); ++ PHYSADDRLOSET(pa, (PHYSADDRLO(pa) + (len-remain))); ++ if (PHYSADDRLO(pa) < buf_addr_lo) { ++ PHYSADDRHISET(pa, (PHYSADDRHI(pa) + 1)); ++ } ++ len = remain; ++ segsadd++; ++ di->dma_avoidance_cnt++; ++ } ++ } ++ } ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); ++ /* return nonzero if out of tx descriptors */ ++ if (txout == di->txin) { ++ DMA_ERROR(("%s: dma_txfast: Out-of-DMA descriptors" ++ " (txin %d txout %d nsegs %d)\n", __FUNCTION__, ++ di->txin, di->txout, nsegs)); ++ goto outoftxd; ++ } ++ } ++ if (segsadd && DMASGLIST_ENAB) ++ map->nsegs += segsadd; ++ ++ /* See above. No need to loop over individual buffers */ ++ if (DMASGLIST_ENAB) ++ break; ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & D64_CTRL1_EOF)) { ++ W_SM(&di->txd64[PREVTXD(txout)].ctrl1, ++ BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); ++ } ++ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* Spin lock to prevent TX discriptor protocol errors when using SG lists */ ++ spin_lock(&di->des_lock); ++ spin_unlock(&di->des_lock); ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++static void * BCMFASTPATH ++dma64_getnexttxp(dma_info_t *di, txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint16 active_desc; ++ void *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ dma64regs_t *dregs = di->d64txregs; ++ ++ if (di->txin == di->xs0cd) { ++ end = (uint16)(B2I(((R_REG(di->osh, &dregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t)); ++ di->xs0cd = end; ++ } else ++ end = di->xs0cd; ++ ++ if (range == HNDDMA_RANGE_TRANSFERED) { ++ active_desc = (uint16)(R_REG(di->osh, &dregs->status1) & D64_XS1_AD_MASK); ++ active_desc = (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; ++ active_desc = B2I(active_desc, dma64dd_t); ++ if (end != active_desc) ++ end = PREVTXD(active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ dmaaddr_t pa; ++ hnddma_seg_map_t *map = NULL; ++ uint size, j, nsegs; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(di->txp[NEXTTXD(i)], SKB_PREFETCH_LEN); ++#endif ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) - di->dataoffsethigh)); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[i]; ++ size = map->origsize; ++ nsegs = map->nsegs; ++ if (nsegs > (uint)NTXDACTIVE(i, end)) { ++ di->xs0cd = i; ++ break; ++ } ++ } else { ++ size = (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK); ++ nsegs = 1; ++ } ++ ++ for (j = nsegs; j > 0; j--) { ++ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ if (j > 1) ++ i = NEXTTXD(i); ++ } ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (txp); ++ ++bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++ return (NULL); ++} ++ ++static void * BCMFASTPATH ++dma64_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ uint16 i, curr; ++ void *rxp; ++ dmaaddr_t pa; ++ ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma64_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(di->rxp[NEXTRXD(i)], SKB_PREFETCH_LEN); ++#endif ++ ++ if (di->rxin == di->rs0cd) { ++ curr = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ di->rs0cd = curr; ++ } else ++ curr = di->rs0cd; ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) - di->dataoffsethigh)); ++ ++ /* clear this packet from the descriptor ring */ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, ++ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); ++} ++ ++static bool ++_dma64_addrext(osl_t *osh, dma64regs_t *dma64regs) ++{ ++ uint32 w; ++ OR_REG(osh, &dma64regs->control, D64_XC_AE); ++ w = R_REG(osh, &dma64regs->control); ++ AND_REG(osh, &dma64regs->control, ~D64_XC_AE); ++ return ((w & D64_XC_AE) == D64_XC_AE); ++} ++ ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma64_txrotate(dma_info_t *di) ++{ ++ uint16 ad; ++ uint nactive; ++ uint rot; ++ uint16 old, new; ++ uint32 w; ++ uint16 first, last; ++ ++ ASSERT(dma64_txsuspendedidle(di)); ++ ++ nactive = _dma_txactive(di); ++ ad = B2I((((R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK) ++ - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t); ++ rot = TXD(ad - di->txin); ++ ++ ASSERT(rot < di->ntxd); ++ ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } ++ ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= D64_CTRL1_EOT; ++ W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w)); ++ ++ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2)); ++ W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w)); ++ ++ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); ++ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); ++ ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef)); ++ W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef)); ++ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ ++ /* Move the map */ ++ if (DMASGLIST_ENAB) { ++ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); ++ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); ++ } ++ ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(di->txout, dma64dd_t)); ++} ++ ++uint ++BCMATTACHFN(dma_addrwidth)(si_t *sih, void *dmaregs) ++{ ++ dma32regs_t *dma32regs; ++ osl_t *osh; ++ ++ osh = si_osh(sih); ++ ++ /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */ ++ /* DMA engine is 64-bit capable */ ++ if ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) { ++ /* backplane are 64-bit capable */ ++ if (si_backplane64(sih)) ++ /* If bus is System Backplane or PCIE then we can access 64-bits */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) || ++ ((BUSTYPE(sih->bustype) == PCI_BUS) && ++ ((sih->buscoretype == PCIE_CORE_ID) || ++ (sih->buscoretype == PCIE2_CORE_ID)))) ++ return (DMADDRWIDTH_64); ++ ++ /* DMA64 is always 32-bit capable, AE is always TRUE */ ++ ASSERT(_dma64_addrext(osh, (dma64regs_t *)dmaregs)); ++ ++ return (DMADDRWIDTH_32); ++ } ++ ++ /* Start checking for 32-bit / 30-bit addressing */ ++ dma32regs = (dma32regs_t *)dmaregs; ++ ++ /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) || ++ ((BUSTYPE(sih->bustype) == PCI_BUS) && ++ ((sih->buscoretype == PCIE_CORE_ID) || ++ (sih->buscoretype == PCIE2_CORE_ID))) || ++ (_dma32_addrext(osh, dma32regs))) ++ return (DMADDRWIDTH_32); ++ ++ /* Fallthru */ ++ return (DMADDRWIDTH_30); ++} ++ ++static int ++_dma_pktpool_set(dma_info_t *di, pktpool_t *pool) ++{ ++ ASSERT(di); ++ ASSERT(di->pktpool == NULL); ++ di->pktpool = pool; ++ return 0; ++} ++ ++static bool ++_dma_rxtx_error(dma_info_t *di, bool istx) ++{ ++ uint32 status1 = 0; ++ uint16 curr; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ++ if (istx) { ++ ++ status1 = R_REG(di->osh, &di->d64txregs->status1); ++ ++ if ((status1 & D64_XS1_XE_MASK) != D64_XS1_XE_NOERR) ++ return TRUE; ++ else if (si_coreid(di->sih) == GMAC_CORE_ID && si_corerev(di->sih) >= 4) { ++ curr = (uint16)(B2I(((R_REG(di->osh, &di->d64txregs->status0) & ++ D64_XS0_CD_MASK) - di->xmtptrbase) & ++ D64_XS0_CD_MASK, dma64dd_t)); ++ ++ if (NTXDACTIVE(di->txin, di->txout) != 0 && ++ curr == di->xs0cd_snapshot) { ++ ++ /* suspicious */ ++ return TRUE; ++ } ++ di->xs0cd_snapshot = di->xs0cd = curr; ++ ++ return FALSE; ++ } ++ else ++ return FALSE; ++ } ++ else { ++ ++ status1 = R_REG(di->osh, &di->d64rxregs->status1); ++ ++ if ((status1 & D64_RS1_RE_MASK) != D64_RS1_RE_NOERR) ++ return TRUE; ++ else ++ return FALSE; ++ } ++ ++ } else if (DMA32_ENAB(di)) { ++ return FALSE; ++ ++ } else { ++ ASSERT(0); ++ return FALSE; ++ } ++ ++} ++ ++void ++_dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen) ++{ ++ di->rxburstlen = rxburstlen; ++ di->txburstlen = txburstlen; ++} ++ ++void ++_dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval) ++{ ++ switch (paramid) { ++ case HNDDMA_PID_TX_MULTI_OUTSTD_RD: ++ di->txmultioutstdrd = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_PREFETCH_CTL: ++ di->txprefetchctl = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_PREFETCH_THRESH: ++ di->txprefetchthresh = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_BURSTLEN: ++ di->txburstlen = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_PREFETCH_CTL: ++ di->rxprefetchctl = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_PREFETCH_THRESH: ++ di->rxprefetchthresh = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_BURSTLEN: ++ di->rxburstlen = (uint8)paramval; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static bool ++_dma_glom_enable(dma_info_t *di, uint32 val) ++{ ++ dma64regs_t *dregs = di->d64rxregs; ++ bool ret = TRUE; ++ if (val) { ++ OR_REG(di->osh, &dregs->control, D64_RC_GE); ++ if (!(R_REG(di->osh, &dregs->control) & D64_RC_GE)) ++ ret = FALSE; ++ } else { ++ AND_REG(di->osh, &dregs->control, ~D64_RC_GE); ++ } ++ return ret; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/hndfwd.c b/drivers/bcmdrivers/gmac/src/shared/hndfwd.c +new file mode 100755 +index 0000000..5dddaf6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch new file mode 100644 index 00000000..cbd0df8a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch @@ -0,0 +1,231 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hndfwd.c +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND GMAC Forwarder ++ * ++ * $Id$ ++ */ ++ ++#if defined(GMAC3) ++ ++#include ++#include ++#include ++ ++#if defined(CONFIG_SMP) ++#define _FWDER_GET(fwder_instance, unit) &per_cpu(fwder_instance, unit) ++#else /* !CONFIG_SMP */ ++#define _FWDER_GET(fwder_instance, unit) &fwder_instance[unit] ++#endif /* !CONFIG_SMP */ ++ ++ ++static int /* default dummy xmit handler when tx device is down */ ++_fwder_default(struct sk_buff * skb, struct net_device * dev, int cnt) ++{ ++ return FWDER_FAILURE; ++} ++ ++#if defined(CONFIG_SMP) ++DEFINE_PER_CPU(struct fwder, fwd_upstream) = { ++ .lock = __SPIN_LOCK_UNLOCKED(.lock), /* static init */ ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .error = 0U ++}; ++ ++DEFINE_PER_CPU(struct fwder, fwd_dnstream) = { ++ .lock = __SPIN_LOCK_UNLOCKED(.lock), ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .error = 0U ++}; ++#else /* !CONFIG_SMP */ ++struct fwder fwd_upstream[FWDER_MAX_UNITS] = { ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 0, ++ .error = 0U ++ }, ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 1, ++ .error = 0U ++ } ++}; ++struct fwder fwd_dnstream[FWDER_MAX_UNITS] = { ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 0, ++ .error = 0U ++ }, ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 1, ++ .error = 0U ++ } ++}; ++#endif /* !CONFIG_SMP */ ++ ++static inline ++struct fwder * _get_other(struct fwder * fwder_p) ++{ ++ struct fwder * other_p; ++ ++ other_p = _FWDER_GET(fwd_upstream, fwder_p->unit); ++ if (other_p == fwder_p) ++ return _FWDER_GET(fwd_dnstream, fwder_p->unit); ++ else ++ return other_p; ++} ++ ++int /* Initialization of fwder in et_module_init */ ++fwder_init(void) ++{ ++ int dir; ++ fwder_t * fwder_p; ++ int unit; ++ ++#if defined(CONFIG_SMP) ++ for_each_online_cpu(unit) ++#else /* !CONFIG_SMP */ ++ for (unit = 0; unit < FWDER_MAX_UNITS; unit++) ++#endif /* !CONFIG_SMP */ ++ { ++ for (dir = (int)FWD_UPSTREAM; dir < (int)FWD_MAX_DIRS; dir++) { ++ if (dir == (int)FWD_UPSTREAM) ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ else ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ fwder_p->dev = (struct net_device *)fwder_p; ++ fwder_p->forward = (fwder_start_t)_fwder_default; ++ fwder_p->unit = unit; ++ fwder_p->error = 0U; ++ } ++ ++ } /* for_each_online_cpu / for unit = 0 .. FWDER_MAX_UNITS */ ++ ++printk("===FWD: fwder_init\n"); // DELETE ME ++ return 0; ++} ++ ++struct fwder * /* Driver registers its xx_start_xmit() handler on netdev open */ ++fwder_attach(fwder_start_t forward, const struct net_device * dev, ++ const int unit, const enum fwder_dir dir) ++{ ++ fwder_t * fwder_p; ++ fwder_t * other_p; /* reverse direction forwarder */ ++ ++ printk("fwder_attach forward<%p> dev<%p> unit<%d> dir<%d>\n", ++ forward, dev, unit, dir); ++ ++ ASSERT((dir < (int)FWD_MAX_DIRS) && (dev != (struct net_device *)NULL) ++ && (forward != (fwder_start_t)NULL)); ++ ++#if defined(CONFIG_SMP) ++ ASSERT(unit < NR_CPUS); ++#else /* !CONFIG_SMP */ ++ ASSERT(unit < FWDER_MAX_UNITS); ++#endif /* !CONFIG_SMP */ ++ ++ if (dir == (int)FWD_UPSTREAM) { ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ other_p = _FWDER_GET(fwd_dnstream, unit); ++ } else { ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ other_p = _FWDER_GET(fwd_upstream, unit); ++ } ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ fwder_p->dev = (struct net_device *)dev; ++ fwder_p->forward = forward; ++ ++ _FWDER_UNLOCK(fwder_p); /* ++LOCK */ ++ ++printk("===FWD: ATTACH<%d,%d>: <%p> unit<%d> dir<%d> dev<%p> xmit<%p>\n", unit, (int)dir, fwder_p, fwder_p->unit, dir, fwder_p->dev, fwder_p->forward); // DELETE ME ++printk("===FWD: RETURN<%d,%d>: <%p> unit<%d> dir<%d> dev<%p> xmit<%p>\n", unit, (int)dir, other_p, other_p->unit, dir^1, other_p->dev, other_p->forward); // DELETE ME ++ ++ return other_p; ++} ++ ++struct fwder * /* A driver deregisters itself on netdev close */ ++fwder_dettach(struct fwder * fwder_p) ++{ ++ ++ if (fwder_p == (fwder_t *)NULL) ++ return (fwder_t *)NULL; ++ ++ printk("fwder_dettach <%p>\n", fwder_p); ++ ++ fwder_p = _get_other(fwder_p); ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ fwder_p->dev = (struct net_device *)NULL; ++ fwder_p->forward = (fwder_start_t)_fwder_default; ++ ++ _FWDER_UNLOCK(fwder_p); /* ++LOCK */ ++ ++ return (fwder_t *)NULL; ++} ++ ++void ++fwder_dump(const struct fwder * fwder_p) ++{ ++ if (fwder_p == (fwder_t *)NULL) ++ return; ++ ++ printk("FWD<%p>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++} ++ ++void ++fwder_dump_all(void) ++{ ++ int unit; ++ struct fwder * fwder_p; ++ ++ printk("FWDER DUMP ALL default<%p>\n", _fwder_default); ++#if defined(CONFIG_SMP) ++ for_each_online_cpu(unit) ++#else /* !CONFIG_SMP */ ++ for (unit = 0; unit < FWDER_MAX_UNITS; unit++) ++#endif /* !CONFIG_SMP */ ++ { ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ printk("FWD[UP]<%p> CPU<%d>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, unit, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++ ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ printk("FWD[DN]<%p> CPU<%d>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, unit, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++ ++ } /* for_each_online_cpu / for unit = 0 .. FWDER_MAX_UNITS */ ++} ++ ++#endif /* GMAC3 */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c +new file mode 100755 +index 0000000..4c93c3a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch new file mode 100644 index 00000000..4cb1532e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch @@ -0,0 +1,70 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 hr2_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h +new file mode 100755 +index 0000000..f7354c6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch new file mode 100644 index 00000000..eb643cc9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _hr2_erom_h_ ++#define _hr2_erom_h_ ++ ++extern uint32 hr2_erom[]; ++ ++#endif //_hr2_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c +new file mode 100755 +index 0000000..0f83e7f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch new file mode 100644 index 00000000..a8c6066e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch @@ -0,0 +1,71 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 hx4_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h +new file mode 100755 +index 0000000..4170fb4 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch new file mode 100644 index 00000000..e13f5896 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _hx4_erom_h_ ++#define _hx4_erom_h_ ++ ++extern uint32 hx4_erom[]; ++ ++#endif //_hx4_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c +new file mode 100755 +index 0000000..ddd9494 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch new file mode 100644 index 00000000..890fab3b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch @@ -0,0 +1,71 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 kt2_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h +new file mode 100755 +index 0000000..b2b6095 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch new file mode 100644 index 00000000..81057fe7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _kt2_erom_h_ ++#define _kt2_erom_h_ ++ ++extern uint32 kt2_erom[]; ++ ++#endif //_kt2_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/linux_osl.c b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c +new file mode 100755 +index 0000000..aa06749 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch new file mode 100644 index 00000000..58984b12 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch @@ -0,0 +1,1719 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c +@@ -0,0 +1,1713 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux OS Independent Layer ++ * ++ * $Id: linux_osl.c 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#define LINUX_PORT ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef mips ++#include ++#endif /* mips */ ++#include ++ ++ ++ ++#include ++#include ++ ++#define PCI_CFG_RETRY 10 ++ ++#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ ++#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ ++ ++#ifdef DHD_USE_STATIC_BUF ++#define STATIC_BUF_MAX_NUM 16 ++#define STATIC_BUF_SIZE (PAGE_SIZE*2) ++#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) ++ ++typedef struct bcm_static_buf { ++ struct semaphore static_sem; ++ unsigned char *buf_ptr; ++ unsigned char buf_use[STATIC_BUF_MAX_NUM]; ++} bcm_static_buf_t; ++ ++static bcm_static_buf_t *bcm_static_buf = 0; ++ ++#define STATIC_PKT_MAX_NUM 8 ++ ++typedef struct bcm_static_pkt { ++ struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; ++ struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM]; ++ struct semaphore osl_pkt_sem; ++ unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2]; ++} bcm_static_pkt_t; ++ ++static bcm_static_pkt_t *bcm_static_skb = 0; ++#endif /* DHD_USE_STATIC_BUF */ ++ ++typedef struct bcm_mem_link { ++ struct bcm_mem_link *prev; ++ struct bcm_mem_link *next; ++ uint size; ++ int line; ++ void *osh; ++ char file[BCM_MEM_FILENAME_LEN]; ++} bcm_mem_link_t; ++ ++struct osl_info { ++ osl_pubinfo_t pub; ++#ifdef CTFPOOL ++ ctfpool_t *ctfpool; ++#endif /* CTFPOOL */ ++ uint magic; ++ void *pdev; ++ atomic_t malloced; ++ atomic_t pktalloced; /* Number of allocated packet buffers */ ++ uint failed; ++ uint bustype; ++ bcm_mem_link_t *dbgmem_list; ++#if defined(DSLCPE_DELAY) ++ shared_osl_t *oshsh; /* osh shared */ ++#endif ++ spinlock_t dbgmem_lock; ++ spinlock_t pktalloc_lock; ++}; ++ ++#define OSL_PKTTAG_CLEAR(p) \ ++do { \ ++ struct sk_buff *s = (struct sk_buff *)(p); \ ++ ASSERT(OSL_PKTTAG_SZ == 32); \ ++ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ ++ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ ++ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ ++ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ ++} while (0) ++ ++/* PCMCIA attribute space access macros */ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++struct pcmcia_dev { ++ dev_link_t link; /* PCMCIA device pointer */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ dev_node_t node; /* PCMCIA node structure */ ++#endif ++ void *base; /* Mapped attribute memory window */ ++ size_t size; /* Size of window */ ++ void *drv; /* Driver data */ ++}; ++#endif /* defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) */ ++ ++/* Global ASSERT type flag */ ++uint32 g_assert_type = FALSE; ++ ++static int16 linuxbcmerrormap[] = ++{ 0, /* 0 */ ++ -EINVAL, /* BCME_ERROR */ ++ -EINVAL, /* BCME_BADARG */ ++ -EINVAL, /* BCME_BADOPTION */ ++ -EINVAL, /* BCME_NOTUP */ ++ -EINVAL, /* BCME_NOTDOWN */ ++ -EINVAL, /* BCME_NOTAP */ ++ -EINVAL, /* BCME_NOTSTA */ ++ -EINVAL, /* BCME_BADKEYIDX */ ++ -EINVAL, /* BCME_RADIOOFF */ ++ -EINVAL, /* BCME_NOTBANDLOCKED */ ++ -EINVAL, /* BCME_NOCLK */ ++ -EINVAL, /* BCME_BADRATESET */ ++ -EINVAL, /* BCME_BADBAND */ ++ -E2BIG, /* BCME_BUFTOOSHORT */ ++ -E2BIG, /* BCME_BUFTOOLONG */ ++ -EBUSY, /* BCME_BUSY */ ++ -EINVAL, /* BCME_NOTASSOCIATED */ ++ -EINVAL, /* BCME_BADSSIDLEN */ ++ -EINVAL, /* BCME_OUTOFRANGECHAN */ ++ -EINVAL, /* BCME_BADCHAN */ ++ -EFAULT, /* BCME_BADADDR */ ++ -ENOMEM, /* BCME_NORESOURCE */ ++ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ ++ -EMSGSIZE, /* BCME_BADLENGTH */ ++ -EINVAL, /* BCME_NOTREADY */ ++ -EPERM, /* BCME_EPERM */ ++ -ENOMEM, /* BCME_NOMEM */ ++ -EINVAL, /* BCME_ASSOCIATED */ ++ -ERANGE, /* BCME_RANGE */ ++ -EINVAL, /* BCME_NOTFOUND */ ++ -EINVAL, /* BCME_WME_NOT_ENABLED */ ++ -EINVAL, /* BCME_TSPEC_NOTFOUND */ ++ -EINVAL, /* BCME_ACM_NOTSUPPORTED */ ++ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ ++ -EIO, /* BCME_SDIO_ERROR */ ++ -ENODEV, /* BCME_DONGLE_DOWN */ ++ -EINVAL, /* BCME_VERSION */ ++ -EIO, /* BCME_TXFAIL */ ++ -EIO, /* BCME_RXFAIL */ ++ -ENODEV, /* BCME_NODEVICE */ ++ -EINVAL, /* BCME_NMODE_DISABLED */ ++ -ENODATA, /* BCME_NONRESIDENT */ ++ ++/* When an new error code is added to bcmutils.h, add os ++ * specific error translation here as well ++ */ ++/* check if BCME_LAST changed since the last time this function was updated */ ++#if BCME_LAST != -42 ++#error "You need to add a OS error translation in the linuxbcmerrormap \ ++ for new error code defined in bcmutils.h" ++#endif ++}; ++ ++/* translate bcmerrors into linux errors */ ++int ++osl_error(int bcmerror) ++{ ++ if (bcmerror > 0) ++ bcmerror = 0; ++ else if (bcmerror < BCME_LAST) ++ bcmerror = BCME_ERROR; ++ ++ /* Array bounds covered by ASSERT in osl_attach */ ++ return linuxbcmerrormap[-bcmerror]; ++} ++ ++extern uint8* dhd_os_prealloc(void *osh, int section, int size); ++ ++EXPORT_SYMBOL(osl_attach); ++osl_t * ++osl_attach(void *pdev, uint bustype, bool pkttag) ++{ ++ osl_t *osh; ++ ++ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); ++ ASSERT(osh); ++ ++ bzero(osh, sizeof(osl_t)); ++ ++ /* Check that error map has the right number of entries in it */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); ++ ++ osh->magic = OS_HANDLE_MAGIC; ++ atomic_set(&osh->malloced, 0); ++ osh->failed = 0; ++ osh->dbgmem_list = NULL; ++ spin_lock_init(&(osh->dbgmem_lock)); ++ osh->pdev = pdev; ++ osh->pub.pkttag = pkttag; ++ osh->bustype = bustype; ++ ++ switch (bustype) { ++ case PCI_BUS: ++ case SI_BUS: ++ case PCMCIA_BUS: ++ osh->pub.mmbus = TRUE; ++ break; ++ case JTAG_BUS: ++ case SDIO_BUS: ++ case USB_BUS: ++ case SPI_BUS: ++ case RPC_BUS: ++ osh->pub.mmbus = FALSE; ++ break; ++ default: ++ ASSERT(FALSE); ++ break; ++ } ++ ++#if defined(DHD_USE_STATIC_BUF) ++ if (!bcm_static_buf) { ++ if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ ++ STATIC_BUF_TOTAL_LEN))) { ++ printk("can not alloc static buf!\n"); ++ } ++ else ++ printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); ++ ++ ++ sema_init(&bcm_static_buf->static_sem, 1); ++ ++ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; ++ } ++ ++ if (!bcm_static_skb) { ++ int i; ++ void *skb_buff_ptr = 0; ++ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); ++ skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); ++ ++ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); ++ for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) ++ bcm_static_skb->pkt_use[i] = 0; ++ ++ sema_init(&bcm_static_skb->osl_pkt_sem, 1); ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ spin_lock_init(&(osh->pktalloc_lock)); ++ ++#ifdef BCMDBG ++ if (pkttag) { ++ struct sk_buff *skb; ++ ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb)); ++ } ++#endif ++ return osh; ++} ++ ++void ++osl_detach(osl_t *osh) ++{ ++ if (osh == NULL) ++ return; ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif ++ ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ kfree(osh); ++} ++ ++static struct sk_buff *osl_alloc_skb(unsigned int len) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) ++ gfp_t flags = GFP_ATOMIC; ++ ++ return __dev_alloc_skb(len, flags); ++#else ++ return dev_alloc_skb(len); ++#endif ++} ++ ++#ifdef CTFPOOL ++ ++#ifdef CTFPOOL_SPINLOCK ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_irqsave(&(ctfpool)->lock, flags) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_irqrestore(&(ctfpool)->lock, flags) ++#else ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_bh(&(ctfpool)->lock) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_bh(&(ctfpool)->lock) ++#endif /* CTFPOOL_SPINLOCK */ ++/* ++ * Allocate and add an object to packet pool. ++ */ ++void * ++osl_ctfpool_add(osl_t *osh) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj); ++ ++ /* No need to allocate more objects */ ++ if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Allocate a new skb and add it to the ctfpool */ ++ skb = osl_alloc_skb(osh->ctfpool->obj_size); ++ if (skb == NULL) { ++ printk("%s: skb alloc of len %d failed\n", __FUNCTION__, ++ osh->ctfpool->obj_size); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Add to ctfpool */ ++ skb->next = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = skb; ++ osh->ctfpool->fast_frees++; ++ osh->ctfpool->curr_obj++; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#ifdef SKB_RECYCLING_DEBUG ++ if ((osh->ctfpool->unit == 2)) { ++ static int count = 0; ++ printk("<%d>allocated skb=%p\n", count, skb); ++ count++; ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ /* Fot reset during release to pool */ ++ skb->reset_size = skb->truesize; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ /* Hijack a skb member to store ptr to ctfpool */ ++ CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool; ++ ++ /* Use bit flag to indicate skb from fast ctfpool */ ++ PKTFAST(osh, skb) = FASTBUF; ++ ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ return skb; ++} ++ ++/* ++ * Add new objects to the pool. ++ */ ++void ++osl_ctfpool_replenish(osl_t *osh, uint thresh) ++{ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ /* Do nothing if no refills are required */ ++ while ((osh->ctfpool->refills > 0) && (thresh--)) { ++ osl_ctfpool_add(osh); ++ osh->ctfpool->refills--; ++ } ++} ++ ++/* ++ * Initialize the packet pool with specified number of objects. ++ */ ++int32 ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size) ++#else ++osl_ctfpool_init(osl_t *osh, uint numobj, uint size) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++{ ++ osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); ++ ASSERT(osh->ctfpool); ++ bzero(osh->ctfpool, sizeof(ctfpool_t)); ++ ++ osh->ctfpool->max_obj = numobj; ++ osh->ctfpool->obj_size = size; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ osh->ctfpool->unit = unit; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ spin_lock_init(&osh->ctfpool->lock); ++ ++ while (numobj--) { ++ if (!osl_ctfpool_add(osh)) ++ return -1; ++ osh->ctfpool->fast_frees--; ++ } ++ ++#ifdef SKB_RECYCLING_DEBUG ++ printk("ctfpool = %p\n", osh->ctfpool); ++#endif /* SKB_RECYCLING_DEBUG */ ++ return 0; ++} ++ ++/* ++ * Cleanup the packet pool objects. ++ */ ++void ++osl_ctfpool_cleanup(osl_t *osh) ++{ ++ struct sk_buff *skb, *nskb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ++ skb = osh->ctfpool->head; ++ ++ while (skb != NULL) { ++ nskb = skb->next; ++ dev_kfree_skb(skb); ++ skb = nskb; ++ osh->ctfpool->curr_obj--; ++ } ++ ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->head = NULL; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ kfree(osh->ctfpool); ++ osh->ctfpool = NULL; ++} ++ ++void ++osl_ctfpool_stats(osl_t *osh, void *b) ++{ ++ struct bcmstrbuf *bb; ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ bb = b; ++ ++ ASSERT((osh != NULL) && (bb != NULL)); ++ ++ bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n", ++ osh->ctfpool->max_obj, osh->ctfpool->obj_size, ++ osh->ctfpool->curr_obj, osh->ctfpool->refills); ++ bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n", ++ osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees, ++ osh->ctfpool->slow_allocs); ++} ++ ++static inline struct sk_buff * ++osl_pktfastget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ /* Try to do fast allocate. Return null if ctfpool is not in use ++ * or if there are no items in the ctfpool. ++ */ ++ if (osh->ctfpool == NULL) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ if (osh->ctfpool->head == NULL) { ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->slow_allocs++; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++#ifdef SKB_RECYCLING_DEBUG ++ WARN_ON_ONCE(1); ++#endif /* SKB_RECYCLING_DEBUG */ ++ return NULL; ++ } ++ ++ ASSERT(len <= osh->ctfpool->obj_size); ++ if (len > osh->ctfpool->obj_size) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Get an object from ctfpool */ ++ skb = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = (void *)skb->next; ++ ++#ifdef SKB_RECYCLING_DEBUG ++ { ++ if (skb->next == NULL) { ++ printk("Get a skb whose next is empty: osh->ctfpool=%p, \ ++ skb=%p, skb->next=%p, osh->ctfpool->head=%p\n", ++ osh->ctfpool, skb, skb->next, osh->ctfpool->head); ++ } ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ ++ ++ osh->ctfpool->fast_allocs++; ++ osh->ctfpool->curr_obj--; ++ ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ /* Init skb struct */ ++ skb->next = skb->prev = NULL; ++ skb->data = skb->head + 16; ++ skb->tail = skb->head + 16; ++ ++ skb->len = 0; ++ skb->cloned = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) ++ skb->list = NULL; ++#endif ++ atomic_set(&skb->users, 1); ++ ++ PKTSETCLINK(skb, NULL); ++ PKTCCLRATTR(skb); ++#ifdef HNDCTF ++ PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED); ++#endif ++ return skb; ++} ++#endif /* CTFPOOL */ ++/* Convert a driver packet to native(OS) packet ++ * In the process, packettag is zeroed out before sending up ++ * IP code depends on skb->cb to be setup correctly with various options ++ * In our case, that means it should be 0 ++ */ ++struct sk_buff * BCMFASTPATH ++osl_pkt_tonative(osl_t *osh, void *pkt) ++{ ++ struct sk_buff *nskb; ++ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(pkt); ++ ++ /* Decrement the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); ++ } ++ return (struct sk_buff *)pkt; ++} ++ ++/* Convert a native(OS) packet to driver packet. ++ * In the process, native packet is destroyed, there is no copying ++ * Also, a packettag is zeroed out ++ */ ++void * BCMFASTPATH ++osl_pkt_frmnative(osl_t *osh, void *pkt) ++{ ++ struct sk_buff *nskb; ++ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(pkt); ++ ++ /* Increment the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); ++ } ++ return (void *)pkt; ++} ++ ++/* Return a new packet. zero out pkttag */ ++void * BCMFASTPATH ++osl_pktget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++ ++#ifdef CTFPOOL ++ /* Allocate from local pool */ ++ skb = osl_pktfastget(osh, len); ++ ++#ifdef SKB_RECYCLING_DEBUG ++ if (skb == NULL) { ++ printk("<%s> osl_pktfastget fail! ctfpool=%p, ctfpool->head=%p, \ ++ ctfpool->curr_obj=%u, ctfpool->fast_allocs=%u, \ ++ ctfpool->fast_frees=%u, ctfpool->slow_allocs=%u\n", ++ __FUNCTION__, osh->ctfpool, osh->ctfpool->head, ++ osh->ctfpool->curr_obj, osh->ctfpool->fast_allocs, ++ osh->ctfpool->fast_frees, osh->ctfpool->slow_allocs); ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ ++ if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { ++#else /* CTFPOOL */ ++ if ((skb = osl_alloc_skb(len))) { ++#endif /* CTFPOOL */ ++ skb_put(skb, len); ++ skb->priority = 0; ++ ++ atomic_inc(&osh->pktalloced); ++ } ++ ++ PKTSETCLINK(skb, NULL); ++ ++ return ((void*) skb); ++} ++ ++#ifdef CTFPOOL ++static inline void ++osl_pktfastfree(osl_t *osh, struct sk_buff *skb) ++{ ++ ctfpool_t *ctfpool; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ ++ if (skb->destructor) { ++ WARN_ON(in_irq()); ++ skb->destructor(skb); ++ } ++ ++ skb->data_len = 0; ++ skb->truesize = skb->reset_size; ++ ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR) ++ skb->tstamp.tv.sec = 0; /*ING*/ ++#else ++ skb->tstamp.tv64 = 0; ++#endif ++#else ++ skb->stamp.tv_sec = 0; ++#endif ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ /* We only need to init the fields that we change */ ++ skb->dev = NULL; ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ skb->dst = NULL; ++#endif ++#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ OSL_PKTTAG_CLEAR(skb); ++ skb->ip_summed = 0; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ skb_orphan(skb); ++#else ++ skb->destructor = NULL; ++#endif ++ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ ++ /* Add object to the ctfpool */ ++ CTFPOOL_LOCK(ctfpool, flags); ++ skb->next = (struct sk_buff *)ctfpool->head; ++ ctfpool->head = (void *)skb; ++ ++ ctfpool->fast_frees++; ++ ctfpool->curr_obj++; ++ ++ ASSERT(ctfpool->curr_obj <= ctfpool->max_obj); ++ CTFPOOL_UNLOCK(ctfpool, flags); ++} ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++bool pktfastfree_wrapper(struct sk_buff *skb) ++{ ++ int rval = FALSE; ++ ++ if (PKTISFAST(NULL, skb)) { ++ osl_pktfastfree(NULL, skb); ++ rval = TRUE; ++ } ++ ++ return rval; ++} ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#endif /* CTFPOOL */ ++ ++/* Free the driver packet. Free the tag if present */ ++void BCMFASTPATH ++osl_pktfree(osl_t *osh, void *p, bool send) ++{ ++ struct sk_buff *skb, *nskb; ++ ++ skb = (struct sk_buff*) p; ++ ++ if (send && osh->pub.tx_fn) ++ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); ++ ++ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); ++ ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; ++ ++ ++#ifdef CTFMAP ++ /* Clear the map ptr before freeing */ ++ PKTCLRCTF(osh, skb); ++ CTFMAPPTR(osh, skb) = NULL; ++#endif /* CTFMAP */ ++ ++#ifdef CTFPOOL ++ if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1)) ++ osl_pktfastfree(osh, skb); ++ else { ++#else /* CTFPOOL */ ++ { ++#endif /* CTFPOOL */ ++ ++ if (skb->destructor) ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if ++ * destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ else ++ /* can free immediately (even in_irq()) if destructor ++ * does not exist ++ */ ++ dev_kfree_skb(skb); ++ } ++ atomic_dec(&osh->pktalloced); ++ skb = nskb; ++ } ++} ++ ++#ifdef DHD_USE_STATIC_BUF ++void* ++osl_pktget_static(osl_t *osh, uint len) ++{ ++ int i = 0; ++ struct sk_buff *skb; ++ ++ if (len > (PAGE_SIZE*2)) { ++ printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); ++ return osl_pktget(osh, len); ++ } ++ ++ down(&bcm_static_skb->osl_pkt_sem); ++ ++ if (len <= PAGE_SIZE) { ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i] = 1; ++ up(&bcm_static_skb->osl_pkt_sem); ++ skb = bcm_static_skb->skb_4k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ return skb; ++ } ++ } ++ ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; ++ up(&bcm_static_skb->osl_pkt_sem); ++ skb = bcm_static_skb->skb_8k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ return skb; ++ } ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ printk("%s: all static pkt in use!\n", __FUNCTION__); ++ return osl_pktget(osh, len); ++} ++ ++void ++osl_pktfree_static(osl_t *osh, void *p, bool send) ++{ ++ int i; ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_4k[i]) { ++ down(&bcm_static_skb->osl_pkt_sem); ++ bcm_static_skb->pkt_use[i] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_8k[i]) { ++ down(&bcm_static_skb->osl_pkt_sem); ++ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ return osl_pktfree(osh, p, send); ++} ++#endif /* DHD_USE_STATIC_BUF */ ++ ++uint32 ++osl_pci_read_config(osl_t *osh, uint offset, uint size) ++{ ++ uint val = 0; ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_read_config_dword(osh->pdev, offset, &val); ++ if (val != 0xffffffff) ++ break; ++ } while (retry--); ++ ++#ifdef BCMDBG ++ if (retry < PCI_CFG_RETRY) ++ printk("PCI CONFIG READ access to %d required %d retries\n", offset, ++ (PCI_CFG_RETRY - retry)); ++#endif /* BCMDBG */ ++ ++ return (val); ++} ++ ++void ++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++{ ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_write_config_dword(osh->pdev, offset, val); ++ if (offset != PCI_BAR0_WIN) ++ break; ++ if (osl_pci_read_config(osh, offset, size) == val) ++ break; ++ } while (retry--); ++ ++#ifdef BCMDBG ++ if (retry < PCI_CFG_RETRY) ++ printk("PCI CONFIG WRITE access to %d required %d retries\n", offset, ++ (PCI_CFG_RETRY - retry)); ++#endif /* BCMDBG */ ++} ++ ++/* return bus # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_bus(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return ((struct pci_dev *)osh->pdev)->bus->number; ++} ++ ++/* return slot # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_slot(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++} ++ ++/* return the pci device pointed by osh->pdev */ ++struct pci_dev * ++osl_pci_device(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return osh->pdev; ++} ++ ++static void ++osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) ++{ ++} ++ ++void ++osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); ++} ++ ++void ++osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); ++} ++ ++void * ++osl_malloc(osl_t *osh, uint size) ++{ ++ void *addr; ++ ++ /* only ASSERT if osh is defined */ ++ if (osh) ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ int i = 0; ++ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) ++ { ++ down(&bcm_static_buf->static_sem); ++ ++ for (i = 0; i < STATIC_BUF_MAX_NUM; i++) ++ { ++ if (bcm_static_buf->buf_use[i] == 0) ++ break; ++ } ++ ++ if (i == STATIC_BUF_MAX_NUM) ++ { ++ up(&bcm_static_buf->static_sem); ++ printk("all static buff in use!\n"); ++ goto original; ++ } ++ ++ bcm_static_buf->buf_use[i] = 1; ++ up(&bcm_static_buf->static_sem); ++ ++ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); ++ } ++ } ++original: ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { ++ if (osh) ++ osh->failed++; ++ return (NULL); ++ } ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return (addr); ++} ++ ++void ++osl_mfree(osl_t *osh, void *addr, uint size) ++{ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr ++ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) ++ { ++ int buf_idx = 0; ++ ++ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; ++ ++ down(&bcm_static_buf->static_sem); ++ bcm_static_buf->buf_use[buf_idx] = 0; ++ up(&bcm_static_buf->static_sem); ++ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ return; ++ } ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ kfree(addr); ++} ++ ++uint ++osl_malloced(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (atomic_read(&osh->malloced)); ++} ++ ++uint ++osl_malloc_failed(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->failed); ++} ++ ++ ++uint ++osl_dma_consistent_align(void) ++{ ++ return (PAGE_SIZE); ++} ++ ++void* ++osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) ++{ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ void *va; ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO); ++ if (va) ++ *pap = (ulong)__virt_to_phys((ulong)va); ++ return va; ++ ++#else ++ void *ret; ++// int gfp = GFP_KERNEL; //GFP_ATOMIC | GFP_DMA; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++// ret = (void *)__get_free_pages(gfp, get_order(size)); ++// if (ret != NULL) { ++// memset(ret, 0, size); ++// *pap = virt_to_phys(ret); ++// } ++ pdev = (struct platform_device *)osh->pdev; ++ ret = dma_alloc_coherent(&pdev->dev, size, (dma_addr_t*)pap, GFP_KERNEL); ++ return ret; ++ ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++void ++osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++{ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ kfree(va); ++#else ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++// free_pages((unsigned long)va, get_order(size)); ++ pdev = (struct platform_device *)osh->pdev; ++ dma_free_coherent(&pdev->dev, size, va, (dma_addr_t)pa); ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++uint BCMFASTPATH ++osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) ++{ ++ int dir; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ pdev = (struct platform_device *)osh->pdev; ++ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; ++ ++#if defined(BCMDMASGLISTOSL) ++ if (dmah != NULL) { ++ int32 nsegs, i, totsegs = 0, totlen = 0; ++ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2]; ++ struct sk_buff *skb; ++ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { ++ sg = &_sg[totsegs]; ++ if (skb_is_nonlinear(skb)) { ++ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); ++ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS)); ++ #ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ dma_map_sg(&pdev->dev, sg, nsegs, dir); ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } else { ++ nsegs = 1; ++ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS); ++ sg->page_link = 0; ++ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); ++ #ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ dma_map_single(&pdev->dev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir); ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ totsegs += nsegs; ++ totlen += PKTLEN(osh, skb); ++ } ++ dmah->nsegs = totsegs; ++ dmah->origsize = totlen; ++ for (i = 0, sg = _sg; i < totsegs; i++, sg++) { ++ dmah->segs[i].addr = sg_phys(sg); ++ dmah->segs[i].length = sg->length; ++ } ++ #ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ return virt_to_phys(va); ++ #else ++ return dmah->segs[0].addr; ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ return virt_to_phys(va); ++#else ++ return dma_map_single(&pdev->dev, va, size, dir); ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++void BCMFASTPATH ++osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) ++{ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ int dir; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ pdev = (struct platform_device *)osh->pdev; ++ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; ++ dma_unmap_single(&pdev->dev, (uint32)pa, size, dir); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++ ++void ++osl_delay(uint usec) ++{ ++ uint d; ++ ++ while (usec > 0) { ++ d = MIN(usec, 1000); ++ udelay(d); ++ usec -= d; ++ } ++} ++ ++#if defined(DSLCPE_DELAY) ++ ++void ++osl_oshsh_init(osl_t *osh, shared_osl_t* oshsh) ++{ ++ extern unsigned long loops_per_jiffy; ++ osh->oshsh = oshsh; ++ osh->oshsh->MIPS = loops_per_jiffy / (500000/HZ); ++} ++ ++int ++in_long_delay(osl_t *osh) ++{ ++ return osh->oshsh->long_delay; ++} ++ ++void ++osl_long_delay(osl_t *osh, uint usec, bool yield) ++{ ++ uint d; ++ bool yielded = TRUE; ++ int usec_to_delay = usec; ++ unsigned long tick1, tick2, tick_diff = 0; ++ ++ /* delay at least requested usec */ ++ while (usec_to_delay > 0) { ++ if (!yield || !yielded) { ++ d = MIN(usec_to_delay, 10); ++ udelay(d); ++ usec_to_delay -= d; ++ } ++ if (usec_to_delay > 0) { ++ osh->oshsh->long_delay++; ++ OSL_GETCYCLES(tick1); ++ spin_unlock_bh(osh->oshsh->lock); ++ if (usec_to_delay > 0 && !in_irq() && !in_softirq() && !in_interrupt()) { ++ schedule(); ++ yielded = TRUE; ++ } else { ++ yielded = FALSE; ++ } ++ spin_lock_bh(osh->oshsh->lock); ++ OSL_GETCYCLES(tick2); ++ ++ if (yielded) { ++ tick_diff = TICKDIFF(tick2, tick1); ++ tick_diff = (tick_diff * 2)/(osh->oshsh->MIPS); ++ if (tick_diff) { ++ usec_to_delay -= tick_diff; ++ } else ++ yielded = 0; ++ } ++ osh->oshsh->long_delay--; ++ ASSERT(osh->oshsh->long_delay >= 0); ++ } ++ } ++} ++#endif /* DSLCPE_DELAY */ ++ ++/* Clone a packet. ++ * The pkttag contents are NOT cloned. ++ */ ++void * ++osl_pktdup(osl_t *osh, void *skb) ++{ ++ void * p; ++ ++ /* clear the CTFBUF flag if set and map the rest of the buffer ++ * before cloning. ++ */ ++ PKTCTFMAP(osh, skb); ++ ++ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) ++ return NULL; ++ ++#ifdef CTFPOOL ++ if (PKTISFAST(osh, skb)) { ++ ctfpool_t *ctfpool; ++ ++ /* if the buffer allocated from ctfpool is cloned then ++ * we can't be sure when it will be freed. since there ++ * is a chance that we will be losing a buffer ++ * from our pool, we increment the refill count for the ++ * object to be alloced later. ++ */ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ PKTCLRFAST(osh, p); ++ PKTCLRFAST(osh, skb); ++ ctfpool->refills++; ++ } ++#endif /* CTFPOOL */ ++ ++ /* skb_clone copies skb->cb.. we don't want that */ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(p); ++ ++ /* Increment the packet counter */ ++ atomic_inc(&osh->pktalloced); ++ return (p); ++} ++ ++ ++/* ++ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access ++ */ ++#ifdef OSLREGOPS ++uint8 ++osl_readb(osl_t *osh, volatile uint8 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint8)((rreg)(ctx, (void*)r, sizeof(uint8))); ++} ++ ++ ++uint16 ++osl_readw(osl_t *osh, volatile uint16 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint16)((rreg)(ctx, (void*)r, sizeof(uint16))); ++} ++ ++uint32 ++osl_readl(osl_t *osh, volatile uint32 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint32)((rreg)(ctx, (void*)r, sizeof(uint32))); ++} ++ ++void ++osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint8))); ++} ++ ++ ++void ++osl_writew(osl_t *osh, volatile uint16 *r, uint16 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint16))); ++} ++ ++void ++osl_writel(osl_t *osh, volatile uint32 *r, uint32 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint32))); ++} ++#endif /* OSLREGOPS */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ */ ++#ifdef BINOSL ++ ++uint32 ++osl_sysuptime(void) ++{ ++ return ((uint32)jiffies * (1000 / HZ)); ++} ++ ++int ++osl_printf(const char *format, ...) ++{ ++ va_list args; ++ static char printbuf[1024]; ++ int len; ++ ++ /* sprintf into a local buffer because there *is* no "vprintk()".. */ ++ va_start(args, format); ++ len = vsnprintf(printbuf, 1024, format, args); ++ va_end(args); ++ ++ if (len > sizeof(printbuf)) { ++ printk("osl_printf: buffer overrun\n"); ++ return (0); ++ } ++ ++ return (printk("%s", printbuf)); ++} ++ ++int ++osl_sprintf(char *buf, const char *format, ...) ++{ ++ va_list args; ++ int rc; ++ ++ va_start(args, format); ++ rc = vsprintf(buf, format, args); ++ va_end(args); ++ return (rc); ++} ++ ++int ++osl_snprintf(char *buf, size_t n, const char *format, ...) ++{ ++ va_list args; ++ int rc; ++ ++ va_start(args, format); ++ rc = vsnprintf(buf, n, format, args); ++ va_end(args); ++ return (rc); ++} ++ ++int ++osl_vsprintf(char *buf, const char *format, va_list ap) ++{ ++ return (vsprintf(buf, format, ap)); ++} ++ ++int ++osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap) ++{ ++ return (vsnprintf(buf, n, format, ap)); ++} ++ ++int ++osl_strcmp(const char *s1, const char *s2) ++{ ++ return (strcmp(s1, s2)); ++} ++ ++int ++osl_strncmp(const char *s1, const char *s2, uint n) ++{ ++ return (strncmp(s1, s2, n)); ++} ++ ++int ++osl_strlen(const char *s) ++{ ++ return (strlen(s)); ++} ++ ++char* ++osl_strcpy(char *d, const char *s) ++{ ++ return (strcpy(d, s)); ++} ++ ++char* ++osl_strncpy(char *d, const char *s, uint n) ++{ ++ return (strncpy(d, s, n)); ++} ++ ++char* ++osl_strchr(const char *s, int c) ++{ ++ return (strchr(s, c)); ++} ++ ++char* ++osl_strrchr(const char *s, int c) ++{ ++ return (strrchr(s, c)); ++} ++ ++void* ++osl_memset(void *d, int c, size_t n) ++{ ++ return memset(d, c, n); ++} ++ ++void* ++osl_memcpy(void *d, const void *s, size_t n) ++{ ++ return memcpy(d, s, n); ++} ++ ++void* ++osl_memmove(void *d, const void *s, size_t n) ++{ ++ return memmove(d, s, n); ++} ++ ++int ++osl_memcmp(const void *s1, const void *s2, size_t n) ++{ ++ return memcmp(s1, s2, n); ++} ++ ++uint32 ++osl_readl(volatile uint32 *r) ++{ ++ return (readl(r)); ++} ++ ++uint16 ++osl_readw(volatile uint16 *r) ++{ ++ return (readw(r)); ++} ++ ++uint8 ++osl_readb(volatile uint8 *r) ++{ ++ return (readb(r)); ++} ++ ++void ++osl_writel(uint32 v, volatile uint32 *r) ++{ ++ writel(v, r); ++} ++ ++void ++osl_writew(uint16 v, volatile uint16 *r) ++{ ++ writew(v, r); ++} ++ ++void ++osl_writeb(uint8 v, volatile uint8 *r) ++{ ++ writeb(v, r); ++} ++ ++void * ++osl_uncached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG1ADDR(va)); ++#else ++ return ((void*)va); ++#endif /* mips */ ++} ++ ++void * ++osl_cached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG0ADDR(va)); ++#else ++ return ((void*)va); ++#endif /* mips */ ++} ++ ++uint ++osl_getcycles(void) ++{ ++ uint cycles; ++ ++#if defined(mips) ++ cycles = read_c0_count() * 2; ++#elif defined(__i386__) ++ rdtscl(cycles); ++#else ++ cycles = 0; ++#endif /* defined(mips) */ ++ return cycles; ++} ++ ++void * ++osl_reg_map(uint32 pa, uint size) ++{ ++ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); ++} ++ ++void ++osl_reg_unmap(void *va) ++{ ++ iounmap(va); ++} ++ ++int ++osl_busprobe(uint32 *val, uint32 addr) ++{ ++#ifdef mips ++ return get_dbe(*val, (uint32 *)addr); ++#else ++ *val = readl((uint32 *)(uintptr)addr); ++ return 0; ++#endif /* mips */ ++} ++ ++bool ++osl_pktshared(void *skb) ++{ ++ return (((struct sk_buff*)skb)->cloned); ++} ++ ++uchar* ++osl_pktdata(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->data); ++} ++ ++uint ++osl_pktlen(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->len); ++} ++ ++uint ++osl_pktheadroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_headroom((struct sk_buff *) skb); ++} ++ ++uint ++osl_pkttailroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_tailroom((struct sk_buff *) skb); ++} ++ ++void* ++osl_pktnext(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->next); ++} ++ ++void ++osl_pktsetnext(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; ++} ++ ++void ++osl_pktsetlen(osl_t *osh, void *skb, uint len) ++{ ++ __pskb_trim((struct sk_buff*)skb, len); ++} ++ ++uchar* ++osl_pktpush(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_push((struct sk_buff*)skb, bytes)); ++} ++ ++uchar* ++osl_pktpull(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_pull((struct sk_buff*)skb, bytes)); ++} ++ ++void* ++osl_pkttag(void *skb) ++{ ++ return ((void*)(((struct sk_buff*)skb)->cb)); ++} ++ ++void* ++osl_pktlink(void *skb) ++{ ++ return (((struct sk_buff*)skb)->prev); ++} ++ ++void ++osl_pktsetlink(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; ++} ++ ++uint ++osl_pktprio(void *skb) ++{ ++ return (((struct sk_buff*)skb)->priority); ++} ++ ++void ++osl_pktsetprio(void *skb, uint x) ++{ ++ ((struct sk_buff*)skb)->priority = x; ++} ++#endif /* BINOSL */ ++ ++uint ++osl_pktalloced(osl_t *osh) ++{ ++ return (atomic_read(&osh->pktalloced)); ++} ++ ++/* Linux Kernel: File Operations: start */ ++void * ++osl_os_open_image(char *filename) ++{ ++ struct file *fp; ++ ++ fp = filp_open(filename, O_RDONLY, 0); ++ /* ++ * 2.6.11 (FC4) supports filp_open() but later revs don't? ++ * Alternative: ++ * fp = open_namei(AT_FDCWD, filename, O_RD, 0); ++ * ??? ++ */ ++ if (IS_ERR(fp)) ++ fp = NULL; ++ ++ return fp; ++} ++ ++int ++osl_os_get_image_block(char *buf, int len, void *image) ++{ ++ struct file *fp = (struct file *)image; ++ int rdlen; ++ ++ if (!image) ++ return 0; ++ ++ rdlen = kernel_read(fp, fp->f_pos, buf, len); ++ if (rdlen > 0) ++ fp->f_pos += rdlen; ++ ++ return rdlen; ++} ++ ++void ++osl_os_close_image(void *image) ++{ ++ if (image) ++ filp_close((struct file *)image, NULL); ++} ++/* Linux Kernel: File Operations: end */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c +new file mode 100755 +index 0000000..9ad67a0 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch new file mode 100644 index 00000000..be506634 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch @@ -0,0 +1,73 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Northstar+ sudo EROM ++ * ++ */ ++#include ++ ++uint32 nsp_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ 0x4bf82d01, 0x04004211, 0x00000303, 0x18024005, 0x181120c5, ++ 0x4bf82d01, 0x04004211, 0x00000403, 0x18025005, 0x181130c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h +new file mode 100755 +index 0000000..98cf29e diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch new file mode 100644 index 00000000..0d6f74ca --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _nsp_erom_h_ ++#define _snp_erom_h_ ++ ++extern uint32 nsp_erom[]; ++ ++#endif //_nsp_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c +new file mode 100755 +index 0000000..d5b400d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch new file mode 100644 index 00000000..cbeb1ff7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch @@ -0,0 +1,371 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c +@@ -0,0 +1,365 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Stubs for NVRAM functions for platforms without flash ++ * ++ * $Id: nvramstubs.c 325991 2012-04-05 10:16:42Z $ ++ */ ++ ++#include ++#include ++#include ++#undef strcmp ++#define strcmp(s1,s2) 0 /* always match */ ++#include ++#include ++#include ++ ++int brcm_get_hx4_model(void); ++ ++int ++nvram_init(void *sih) ++{ ++ return 0; ++} ++ ++int ++nvram_append(void *sb, char *vars, uint varsz) ++{ ++ return 0; ++} ++ ++void ++nvram_exit(void *sih) ++{ ++} ++ ++/* fake nvram tuples */ ++typedef struct { ++ char *name; ++ char *value; ++} nvram_t; ++ ++static nvram_t fake_nvram[] = { ++ {"boardtype", "0x058d"}, ++ {"boardnum", "0x010"}, ++ {"boardrev", "0x1100"}, ++ {"boardflags", "0x710"}, ++ {"boardflags2", "0"}, ++ {"sromrev", "8"}, ++ {"clkfreq", "133,133,133"}, ++ {"xtalfreq", "125000"}, ++ {"et_txq_thresh", "1024"}, ++ {"et_rx_rate_limit","1"}, ++ {"sdram_config", "0x103"}, ++ {"swgmacet", "et2"}, ++ {"brcmtag", "1"}, ++ //{"ethaddr", "00:90:4c:06:a5:72"}, ++#ifdef FOUR_PORT_CONFIG ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 8*"}, ++ {"vlan2hwname", "et2"}, ++ {"vlan2ports", "3 8*"}, ++ {"wanport", "3"}, ++#else ++#if (defined(CONFIG_ROOT_NFS) && defined(CONFIG_MACH_NSP)) ++ ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 3 8u"}, ++ {"wanport", "4"}, ++#else ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 3 8*"}, ++ {"vlan2hwname", "et2"}, ++ {"vlan2ports", "4 8*"}, ++ {"wanport", "4"}, ++#endif //(defined(CONFIG_ROOT_NFS) && defined(CONFIG_MACH_NSP)) ++#endif ++ {"landevs", "vlan1"}, ++ {"wandevs", "et0"}, ++ {"lan_ipaddr", "192.168.1.1"}, ++ {"lan_netmask", "255.255.255.0"}, ++ {"boot_wait", "on"}, ++ {"wait_time", "3"}, ++ {"watchdog", "0"}, ++ {"et_msglevel", "0xFFFFFFFF"} ++}; ++ ++#define fake_nvram_size sizeof(fake_nvram)/sizeof(fake_nvram[0]) ++ ++#ifndef FAKE_NVRAM ++ ++#define CONFIG_SPI_BASE 0x1e000000 ++#define CONFIG_NAND_BASE 0x1c000000 ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define CONFIG_ENV_OFFSET 0xa0000 /* 30000-b0000 - use last 10000 for env */ ++#else ++#define CONFIG_ENV_OFFSET 0xc0000 /* 30000-b0000 - use last 10000 for env */ ++#endif ++#define CONFIG_ENV_SIZE 0x20000 /* 128K */ ++#define CONFIG_ENV_MAX_ENTRIES 512 ++ ++#define UBOOT_ENV_ADDR CONFIG_SPI_BASE+CONFIG_ENV_OFFSET ++#define UBOOT_ENV_SIZE CONFIG_ENV_SIZE ++#define UBOOT_ENV_MAX_NUM CONFIG_ENV_MAX_ENTRIES ++ ++static uint8 u_boot_env[UBOOT_ENV_SIZE]; ++static bool u_boot_env_loaded=false; ++static nvram_t env_list[UBOOT_ENV_MAX_NUM]; ++static int uboot_vars_start = UBOOT_ENV_ADDR; ++static int uboot_nvram_max = UBOOT_ENV_SIZE; ++ ++/* pass envaddr= in bootargs */ ++static int __init envaddr_setup(char *str) ++{ ++ int ret =0; ++ unsigned long ul=0; ++ ++ //printk("NVRAM: %s\n", str); ++ ++ ret = strict_strtoul(str, 16, &ul); ++ ++ if (!ret) { ++ uboot_vars_start = ul; ++ printk("NVRAM: assign 0x%08x\n", uboot_vars_start); ++ } ++ ++ return !ret; ++} ++__setup("envaddr=", envaddr_setup); ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++static void ++setup_uboot_vars(void) { ++ int modelnum; ++ int env_offset; ++ ++ modelnum = brcm_get_hx4_model(); ++ if (modelnum == HX4_DNI_3448P) { ++ env_offset = 0x00100000; ++ uboot_vars_start = CONFIG_NAND_BASE + env_offset; ++ } else if (modelnum == HX4_ACCTON_AS4610_54) { ++ env_offset = 0x000f0000; ++ uboot_vars_start = CONFIG_SPI_BASE + env_offset; ++ } ++} ++ ++/* ++APIs for access into uboot env vars ++*/ ++ ++int ++nvram_env_init(void) ++{ ++ volatile void *envbuf; ++ char *dp, *sp, *name, *value, *dp_end; ++ char sep = '\0'; ++ int idx=0; ++ ++ setup_uboot_vars(); ++ ++ printk("NVRAM: map 0x%08x\n", uboot_vars_start); ++ ++ /* map uboot env */ ++ if ((envbuf = (uint8*)ioremap(uboot_vars_start, UBOOT_ENV_SIZE)) == NULL) { ++ printk("%s: ioremap() failed\n", __FUNCTION__); ++ return -ENOMEM; ++ } ++ ++ /* copy memory into buffer */ ++ memcpy((void*)u_boot_env, (void *) envbuf, uboot_nvram_max); ++ ++ /* clear fake entry set */ ++ memset(env_list, 0, sizeof(env_list)); ++ ++ /* load uboot fake nvram buffer */ ++ /* point to first data */ ++ dp = (char*)u_boot_env; ++ /* point to data buffer */ ++ dp += 4; ++ dp_end = (char*)((uint32)u_boot_env+UBOOT_ENV_SIZE); ++ ++ /* point to first data */ ++ do { ++ ++ /* skip leading white space */ ++ while ((*dp == ' ') || (*dp == '\t')) ++ ++dp; ++ ++ /* skip comment lines */ ++ if (*dp == '#') { ++ while (*dp && (*dp != sep)) ++ ++dp; ++ ++dp; ++ continue; ++ } ++ ++ /* parse name */ ++ for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp) ++ ; ++ ++ *dp++ = '\0'; /* terminate name */ ++ ++ /* parse value; deal with escapes */ ++ for (value = sp = dp; *dp && (*dp != sep); ++dp) { ++ if ((*dp == '\\') && *(dp + 1)) ++ ++dp; ++ *sp++ = *dp; ++ } ++ *sp++ = '\0'; /* terminate value */ ++ ++dp; ++ ++ /* enter into hash table */ ++ env_list[idx].name = name; ++ env_list[idx].value = value; ++ //printk("entry%d %s=%s\n", idx, name, value); ++ idx++; ++ ++ /* check if table is full */ ++ if (idx >= UBOOT_ENV_MAX_NUM ) { ++ printk("%s: WARNING - UBoot environment table is full\n", __FUNCTION__); ++ break; ++ } ++ ++ /* check if end of table */ ++ } while ((dp < dp_end) && *dp); /* size check needed for text */ ++ ++ u_boot_env_loaded = true; ++ ++ /* unmap uboot env */ ++ iounmap(envbuf); ++ ++ return 0; ++} ++#endif ++ ++int ++nvram_env_gmac_name(int gmac, char *name) ++{ ++ int ret=0; ++ switch (gmac) ++ { ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ case 0: ++ case 1: ++ sprintf(name, "eth%daddr", gmac+1); ++ break; ++ case 2: ++ strcpy(name, "ethaddr"); ++ break; ++ case 3: ++ sprintf(name, "eth%daddr", gmac); ++ break; ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ case 0: ++ strcpy(name, "ethaddr"); ++ break; ++ case 1: ++ sprintf(name, "eth1addr"); ++ break; ++#elif defined(CONFIG_MACH_HR2) ++ case 0: ++ strcpy(name, "ethaddr"); ++ break; ++#endif ++ default: ++ strcpy(name, "unknown"); ++ ret = -1; ++ break; ++ } ++ return ret; ++ ++} ++ ++char * ++nvram_get(const char *name) ++{ ++ int i, len; ++ nvram_t *tuple; ++ int num_entries; ++ ++ if (!name) ++ return (char *) 0; ++ ++ len = strlen(name); ++ if (len == 0) ++ return (char *) 0; ++ ++#ifndef FAKE_NVRAM ++ tuple = &env_list[0]; ++ num_entries = sizeof(env_list)/sizeof(nvram_t); ++ ++ if (!u_boot_env_loaded) ++ nvram_env_init(); ++ ++ /* first check the uboot NVRAM variables */ ++ for (i = 0; i < num_entries; i++) { ++ ++ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { ++ /*printf("%s (NVRAM) %s: %s\n", __FUNCTION__, name, tuple->value);*/ ++ return tuple->value; ++ } ++ tuple++; ++ } ++#endif ++ ++ /* if cant find then check fake table above */ ++ tuple = &fake_nvram[0]; ++ num_entries = fake_nvram_size; ++ for (i = 0; i < num_entries; i++) { ++ ++ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { ++ /*printf("%s (STUBS) %s: %s\n", __FUNCTION__, name, tuple->value);*/ ++ return tuple->value; ++ } ++ tuple++; ++ } ++ ++ return (char *) 0; ++} ++ ++int ++nvram_set(const char *name, const char *value) ++{ ++ return 0; ++} ++ ++int ++nvram_unset(const char *name) ++{ ++ return 0; ++} ++ ++int ++nvram_commit(void) ++{ ++ return 0; ++} ++ ++int ++nvram_getall(char *buf, int count) ++{ ++ /* add null string as terminator */ ++ if (count < 1) ++ return BCME_BUFTOOSHORT; ++ *buf = '\0'; ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/siutils.c b/drivers/bcmdrivers/gmac/src/shared/siutils.c +new file mode 100755 +index 0000000..23f84ac diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch new file mode 100644 index 00000000..80b67dbd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils.c.patch @@ -0,0 +1,1542 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/siutils.c +@@ -0,0 +1,1536 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * $Id: siutils.c 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) ++#include ++#endif /* !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) */ ++ ++#include "siutils_priv.h" ++ ++/* local prototypes */ ++static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz); ++static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); ++static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs); ++ ++static void si_nvram_process(si_info_t *sii, char *pvars); ++/* dev path concatenation util */ ++static char *si_devpathvar(si_t *sih, char *var, int len, const char *name); ++static bool _si_clkctl_cc(si_info_t *sii, uint mode); ++ ++ ++/* global variable to indicate reservation/release of gpio's */ ++static uint32 si_gpioreservation = 0; ++ ++/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ ++ ++EXPORT_SYMBOL(si_attach); ++EXPORT_SYMBOL(si_setcore); ++ ++/* ++ * Allocate a si handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ * bustype - pci/pcmcia/sb/sdio/etc ++ * vars - pointer to a pointer area for "environment" variables ++ * varsz - pointer to int to return the size of the vars ++ */ ++si_t * ++BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ si_info_t *sii; ++ si_t *sih; ++ ++ /* alloc si_info_t */ ++ if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { ++ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); ++ return (NULL); ++ } ++ ++ if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { ++ MFREE(osh, sii, sizeof(si_info_t)); ++ SI_ERROR(("%s si_doattach() failed\n", __FUNCTION__)); ++ return (NULL); ++ } ++ sii->vars = vars ? *vars : NULL; ++ sii->varsz = varsz ? *varsz : 0; ++ ++ sih = (si_t*)sii; ++ printk("%s socitype(0x%x) chip(0x%x) chiprev(0x%x) chippkg(0x%x)\n", ++ __FUNCTION__, sih->socitype, sih->chip, sih->chiprev, sih->chippkg); ++ ++ return (si_t *)sii; ++} ++ ++/* global kernel resource */ ++static si_info_t ksii; ++ ++static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ ++ ++/* generic kernel variant of si_attach() */ ++si_t * ++BCMATTACHFN(si_kattach)(osl_t *osh) ++{ ++ static bool ksii_attached = FALSE; ++ ++ if (!ksii_attached) { ++ void *regs; ++#ifndef SI_ENUM_BASE_VARIABLE ++ regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++#endif ++ ++ if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, ++ SI_BUS, NULL, ++ osh != SI_OSH ? &ksii.vars : NULL, ++ osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { ++ SI_ERROR(("si_kattach: si_doattach failed\n")); ++ REG_UNMAP(regs); ++ return NULL; ++ } ++ REG_UNMAP(regs); ++ ++ /* save ticks normalized to ms for si_watchdog_ms() */ ++ if (PMUCTL_ENAB(&ksii.pub)) { ++ /* based on 32KHz ILP clock */ ++ wd_msticks = 32; ++ } else { ++ if (ksii.pub.ccrev < 18) ++ wd_msticks = si_clock(&ksii.pub) / 1000; ++ else ++ wd_msticks = si_alp_clock(&ksii.pub) / 1000; ++ } ++ ++ ksii_attached = TRUE; ++ SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", ++ ksii.pub.ccrev, wd_msticks)); ++ } ++ ++ return &ksii.pub; ++} ++ ++static bool ++BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh) ++{ ++ return TRUE; ++} ++ ++static bool ++BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs) ++{ ++ bool pci, pcie; ++ uint i; ++ uint pciidx, pcieidx, pcirev, pcierev; ++ ++ cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ++ ASSERT((uintptr)cc); ++ ++ /* get chipcommon rev */ ++ sii->pub.ccrev = (int)si_corerev(&sii->pub); ++ ++ /* get chipcommon chipstatus */ ++ if (sii->pub.ccrev >= 11) ++ sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); ++ ++ /* get chipcommon capabilites */ ++ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); ++ /* get chipcommon extended capabilities */ ++ ++ if (sii->pub.ccrev >= 35) ++ sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); ++ ++ /* get pmu rev and caps */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); ++ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; ++ } ++ ++ SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", ++ sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, ++ sii->pub.pmucaps)); ++ ++ /* figure out bus/orignal core idx */ ++ sii->pub.buscoretype = NODEV_CORE_ID; ++ sii->pub.buscorerev = (uint)NOREV; ++ sii->pub.buscoreidx = BADIDX; ++ ++ pci = pcie = FALSE; ++ pcirev = pcierev = (uint)NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ uint cid, crev; ++ ++ si_setcoreidx(&sii->pub, i); ++ cid = si_coreid(&sii->pub); ++ crev = si_corerev(&sii->pub); ++ ++ /* Display cores found */ ++ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", ++ i, cid, crev, sii->coresba[i], sii->regs[i])); ++ ++ /* find the core idx before entering this func. */ ++ if ((savewin && (savewin == sii->coresba[i])) || ++ (regs == sii->regs[i])) ++ *origidx = i; ++ } ++ ++ SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, ++ sii->pub.buscorerev)); ++ ++ /* return to the original core */ ++ si_setcoreidx(&sii->pub, *origidx); ++ ++ return TRUE; ++} ++ ++static void ++BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars) ++{ ++ /* get boardtype and boardrev */ ++ switch (BUSTYPE(sii->pub.bustype)) { ++ case SI_BUS: ++ sii->pub.boardvendor = VENDOR_BROADCOM; ++ if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0)) ++ if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0) ++ sii->pub.boardtype = 0xffff; ++ break; ++ } ++ ++ if (sii->pub.boardtype == 0) { ++ SI_ERROR(("si_doattach: unknown board type\n")); ++ ASSERT(sii->pub.boardtype); ++ } ++ ++ sii->pub.boardrev = getintvar(pvars, "boardrev"); ++ sii->pub.boardflags = getintvar(pvars, "boardflags"); ++} ++ ++ ++static si_info_t * ++BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ struct si_pub *sih = &sii->pub; ++ uint32 w, savewin; ++ chipcregs_t *cc; ++ char *pvars = NULL; ++ uint origidx; ++ ASSERT(GOODREGS(regs)); ++ ++ bzero((uchar*)sii, sizeof(si_info_t)); ++ ++ savewin = 0; ++ ++ sih->buscoreidx = BADIDX; ++ ++ sii->curmap = regs; ++ sii->sdh = sdh; ++ sii->osh = osh; ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++ si_enum_base_init(sih, bustype); ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++ /* check to see if we are a si core mimic'ing a pci core */ ++ if ((bustype == PCI_BUS)) { ++ SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " ++ "devid:0x%x\n", __FUNCTION__, devid)); ++ bustype = SI_BUS; ++ } ++ ++ /* find Chipcommon address */ ++ cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++ ++ sih->bustype = bustype; ++ if (bustype != BUSTYPE(bustype)) { ++ SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", ++ bustype, BUSTYPE(bustype))); ++ return NULL; ++ } ++ ++ /* bus/core/clk setup for register access */ ++ if (!si_buscore_prep(sii, bustype, devid, sdh)) { ++ SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); ++ return NULL; ++ } ++ ++ /* ChipID recognition. ++ * We assume we can read chipid at offset 0 from the regs arg. ++ * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), ++ * some way of recognizing them needs to be added here. ++ */ ++ if (!cc) { ++ SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__)); ++ return NULL; ++ } ++ w = R_REG(osh, &cc->chipid); ++ printk("%s chipid: 0x%x\n", __FUNCTION__, w); ++ sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; ++ /* Might as wll fill in chip id rev & pkg */ ++ sih->chip = w & CID_ID_MASK; ++ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; ++ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ /* printk("%s chip: 0x%x; chiprev: 0x%x; chippkg: 0x%x\n", __FUNCTION__, sih->chip, sih->chiprev, sih->chippkg); */ ++ ++ sih->issim = IS_SIM(sih->chippkg); ++ ++ /* scan for cores */ ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { ++ SI_MSG(("Found chip type SB (0x%08x)\n", w)); ++ sb_scan(&sii->pub, regs, devid); ++ } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || (CHIPTYPE(sii->pub.socitype) == SOCI_NS)) { ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) ++ SI_MSG(("Found chip type AI (0x%08x)\n", w)); ++ else ++ SI_MSG(("Found chip type NS (0x%08x)\n", w)); ++ /* pass chipc address instead of original core base */ ++ ai_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { ++ SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); ++ /* pass chipc address instead of original core base */ ++ ub_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else { ++ SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); ++ return NULL; ++ } ++ /* no cores found, bail out */ ++ if (sii->numcores == 0) { ++ SI_ERROR(("si_doattach: could not find any cores\n")); ++ return NULL; ++ } ++ /* bus/core/clk setup */ ++ origidx = SI_CC_IDX; ++ if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { ++ SI_ERROR(("si_doattach: si_buscore_setup failed\n")); ++ goto exit; ++ } ++ ++#ifdef SI_SPROM_PROBE ++ si_sprom_init(sih); ++#endif /* SI_SPROM_PROBE */ ++ ++#if !defined(BCMHIGHSDIO) ++ /* Init nvram from flash if it exists */ ++ nvram_init((void *)&(sii->pub)); ++ ++ pvars = vars ? *vars : NULL; ++ ++ si_nvram_process(sii, pvars); ++ ++ /* === NVRAM, clock is ready === */ ++#else ++ pvars = NULL; ++ BCM_REFERENCE(pvars); ++#endif ++ ++ ++ /* bootloader should retain default pulls */ ++#ifndef BCM_BOOTLOADER ++ if (sii->pub.ccrev >= 20) { ++ uint32 gpiopullup = 0, gpiopulldown = 0; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ /* 4314/43142 has pin muxing, don't clear gpio bits */ ++ if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { ++ gpiopullup |= 0x402e0; ++ gpiopulldown |= 0x20500; ++ } ++ ++ W_REG(osh, &cc->gpiopullup, gpiopullup); ++ W_REG(osh, &cc->gpiopulldown, gpiopulldown); ++ si_setcoreidx(sih, origidx); ++ } ++#endif /* !BCM_BOOTLOADER */ ++ ++ ++ /* setup the GPIO based LED powersave register */ ++ if (sii->pub.ccrev >= 16) { ++ if ((w = getintvar(pvars, "leddc")) == 0) ++ w = DEFAULT_GPIOTIMERVAL; ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); ++ } ++ ++ if (PCI_FORCEHT(sii)) { ++ SI_MSG(("si_doattach: force HT\n")); ++ sih->pci_pr32414 = TRUE; ++ si_clkctl_init(sih); ++ _si_clkctl_cc(sii, CLK_FAST); ++ } ++ ++#if !defined(_CFE_) || defined(CFG_WL) ++ /* enable GPIO interrupts when clocks are off */ ++ if (sii->pub.ccrev >= 21) { ++ uint32 corecontrol; ++ corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), ++ 0, 0); ++ corecontrol |= CC_ASYNCGPIO; ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), ++ corecontrol, corecontrol); ++ } ++ ++#endif /* !_CFE_ || CFG_WL */ ++ ++#if defined(SAVERESTORE) ++ sr_save_restore_init(sih); ++#endif ++ ++ ++ return (sii); ++ ++exit: ++ ++ return NULL; ++} ++ ++/* may be called with core in reset */ ++void ++BCMATTACHFN(si_detach)(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ ++#if defined(STA) ++ struct si_pub *si_local = NULL; ++ bcopy(&sih, &si_local, sizeof(si_t*)); ++#endif ++ ++ sii = SI_INFO(sih); ++ ++ if (sii == NULL) ++ return; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) ++ for (idx = 0; idx < SI_MAXCORES; idx++) ++ if (sii->regs[idx]) { ++ REG_UNMAP(sii->regs[idx]); ++ sii->regs[idx] = NULL; ++ } ++ ++#if defined(STA) ++#if !defined(BCMHIGHSDIO) ++ srom_var_deinit((void *)si_local); ++#endif ++ nvram_exit((void *)si_local); /* free up nvram buffers */ ++#endif ++ ++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) ++ if (sii != &ksii) ++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ ++ MFREE(sii->osh, sii, sizeof(si_info_t)); ++} ++ ++void * ++si_osh(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->osh; ++} ++ ++void ++si_setosh(si_t *sih, osl_t *osh) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (sii->osh != NULL) { ++ SI_ERROR(("osh is already set....\n")); ++ ASSERT(!sii->osh); ++ } ++ sii->osh = osh; ++} ++ ++uint ++si_intflag(si_t *sih) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_intflag(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return R_REG(sii->osh, ((uint32 *)(uintptr) ++ (sii->oob_router + OOB_STATUSA))); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint ++si_flag(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_flag(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_flag(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_flag(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_setint(si_t *sih, int siflag) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_setint(sih, siflag); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_setint(sih, siflag); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_setint(sih, siflag); ++ else ++ ASSERT(0); ++} ++ ++uint ++si_coreid(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->coreid[sii->curidx]; ++} ++ ++uint ++si_coreidx(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->curidx; ++} ++ ++/* return the core-type instantiation # of the current core */ ++uint ++si_coreunit(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ uint coreid; ++ uint coreunit; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ coreunit = 0; ++ ++ idx = sii->curidx; ++ ++ ASSERT(GOODREGS(sii->curmap)); ++ coreid = si_coreid(sih); ++ ++ /* count the cores of our type */ ++ for (i = 0; i < idx; i++) ++ if (sii->coreid[i] == coreid) ++ coreunit++; ++ ++ return (coreunit); ++} ++ ++uint ++si_corevendor(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corevendor(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corevendor(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corevendor(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_backplane64(si_t *sih) ++{ ++ return ((sih->cccaps & CC_CAP_BKPLN64) != 0); ++} ++ ++uint ++si_corerev(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corerev(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corerev(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corerev(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++/* return index of coreid or BADIDX if not found */ ++uint ++si_findcoreidx(si_t *sih, uint coreid, uint coreunit) ++{ ++ si_info_t *sii; ++ uint found; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ ++ found = 0; ++ ++ for (i = 0; i < sii->numcores; i++) ++ if (sii->coreid[i] == coreid) { ++ if (found == coreunit) ++ return (i); ++ found++; ++ } ++ ++ return (BADIDX); ++} ++ ++/* return list of found cores */ ++uint ++si_corelist(si_t *sih, uint coreid[]) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); ++ return (sii->numcores); ++} ++ ++/* return current register mapping */ ++void * ++si_coreregs(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curmap)); ++ ++ return (sii->curmap); ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void * ++si_setcore(si_t *sih, uint coreid, uint coreunit) ++{ ++ uint idx; ++ ++ idx = si_findcoreidx(sih, coreid, coreunit); ++ if (!GOODIDX(idx)) ++ return (NULL); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, idx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_setcoreidx(sih, idx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, idx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++void * ++si_setcoreidx(si_t *sih, uint coreidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, coreidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_setcoreidx(sih, coreidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, coreidx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++/* Turn off interrupt as required by sb_setcore, before switch core */ ++void * ++si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) ++{ ++ void *cc; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ if (SI_FAST(sii)) { ++ /* Overloading the origidx variable to remember the coreid, ++ * this works because the core ids cannot be confused with ++ * core indices. ++ */ ++ *origidx = coreid; ++ if (coreid == CC_CORE_ID) ++ return (void *)CCREGS_FAST(sii); ++ else if (coreid == sih->buscoretype) ++ return (void *)PCIEREGS(sii); ++ } ++ INTR_OFF(sii, *intr_val); ++ *origidx = sii->curidx; ++ cc = si_setcore(sih, coreid, 0); ++ ASSERT(cc != NULL); ++ ++ return cc; ++} ++ ++/* restore coreidx and restore interrupt */ ++void ++si_restore_core(si_t *sih, uint coreid, uint intr_val) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) ++ return; ++ ++ si_setcoreidx(sih, coreid); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++int ++si_numaddrspaces(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_numaddrspaces(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_numaddrspaces(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_numaddrspaces(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspace(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspace(sih, asidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_addrspace(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspace(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspacesize(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspacesize(sih, asidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_addrspacesize(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspacesize(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ /* Only supported for SOCI_AI */ ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_coreaddrspaceX(sih, asidx, addr, size); ++ else ++ *size = 0; ++} ++ ++uint32 ++si_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_cflags(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_core_cflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_cflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_cflags_wo(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_cflags_wo(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_cflags_wo(sih, mask, val); ++ else ++ ASSERT(0); ++} ++ ++uint32 ++si_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_sflags(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_core_sflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_sflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_iscoreup(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_iscoreup(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_iscoreup(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_iscoreup(sih); ++ else { ++ ASSERT(0); ++ return FALSE; ++ } ++} ++ ++uint ++si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ /* only for AI back plane chips */ ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return (ai_wrap_reg(sih, offset, mask, val)); ++ return 0; ++} ++ ++uint ++si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corereg(sih, coreidx, regoff, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corereg(sih, coreidx, regoff, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corereg(sih, coreidx, regoff, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_disable(si_t *sih, uint32 bits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_disable(sih, bits); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_disable(sih, bits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_disable(sih, bits); ++} ++ ++void ++si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_reset(sih, bits, resetbits); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_reset(sih, bits, resetbits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_reset(sih, bits, resetbits); ++} ++ ++/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ ++int ++si_corebist(si_t *sih) ++{ ++ uint32 cflags; ++ int result = 0; ++ ++ /* Read core control flags */ ++ cflags = si_core_cflags(sih, 0, 0); ++ ++ /* Set bist & fgc */ ++ si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); ++ ++ /* Wait for bist done */ ++ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); ++ ++ if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) ++ result = BCME_ERROR; ++ ++ /* Reset core control flags */ ++ si_core_cflags(sih, 0xffff, cflags); ++ ++ return result; ++} ++ ++static uint32 ++BCMINITFN(factor6)(uint32 x) ++{ ++ switch (x) { ++ case CC_F6_2: return 2; ++ case CC_F6_3: return 3; ++ case CC_F6_4: return 4; ++ case CC_F6_5: return 5; ++ case CC_F6_6: return 6; ++ case CC_F6_7: return 7; ++ default: return 0; ++ } ++} ++ ++/* calculate the speed the SI would run at given a set of clockcontrol values */ ++uint32 ++BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m) ++{ ++ uint32 n1, n2, clock, m1, m2, m3, mc; ++ ++ n1 = n & CN_N1_MASK; ++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; ++ ++ if (pll_type == PLL_TYPE6) { ++ if (m & CC_T6_MMASK) ++ return CC_T6_M1; ++ else ++ return CC_T6_M0; ++ } else if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ n1 = factor6(n1); ++ n2 += CC_F5_BIAS; ++ } else if (pll_type == PLL_TYPE2) { ++ n1 += CC_T2_BIAS; ++ n2 += CC_T2_BIAS; ++ ASSERT((n1 >= 2) && (n1 <= 7)); ++ ASSERT((n2 >= 5) && (n2 <= 23)); ++ } else if (pll_type == PLL_TYPE5) { ++ return (100000000); ++ } else ++ ASSERT(0); ++ /* PLL types 3 and 7 use BASE2 (25Mhz) */ ++ if ((pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE7)) { ++ clock = CC_CLOCK_BASE2 * n1 * n2; ++ } else ++ clock = CC_CLOCK_BASE1 * n1 * n2; ++ ++ if (clock == 0) ++ return 0; ++ ++ m1 = m & CC_M1_MASK; ++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; ++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; ++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; ++ ++ if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ m1 = factor6(m1); ++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) ++ m2 += CC_F5_BIAS; ++ else ++ m2 = factor6(m2); ++ m3 = factor6(m3); ++ ++ switch (mc) { ++ case CC_MC_BYPASS: return (clock); ++ case CC_MC_M1: return (clock / m1); ++ case CC_MC_M1M2: return (clock / (m1 * m2)); ++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); ++ case CC_MC_M1M3: return (clock / (m1 * m3)); ++ default: return (0); ++ } ++ } else { ++ ASSERT(pll_type == PLL_TYPE2); ++ ++ m1 += CC_T2_BIAS; ++ m2 += CC_T2M2_BIAS; ++ m3 += CC_T2_BIAS; ++ ASSERT((m1 >= 2) && (m1 <= 7)); ++ ASSERT((m2 >= 3) && (m2 <= 10)); ++ ASSERT((m3 >= 2) && (m3 <= 7)); ++ ++ if ((mc & CC_T2MC_M1BYP) == 0) ++ clock /= m1; ++ if ((mc & CC_T2MC_M2BYP) == 0) ++ clock /= m2; ++ if ((mc & CC_T2MC_M3BYP) == 0) ++ clock /= m3; ++ ++ return (clock); ++ } ++} ++ ++uint32 ++BCMINITFN(si_clock)(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint32 n, m; ++ uint idx; ++ uint32 pll_type, rate; ++ uint intr_val = 0; ++ ++ if (IS_IPROC_CHIP_ID(CHIPID(sih->chip))) { ++ if (sih->chippkg == BCM4709_PKG_ID) { ++ return NS_SI_CLOCK; ++ } else ++ return NS_SLOW_SI_CLOCK; ++ } ++ ++ sii = SI_INFO(sih); ++ INTR_OFF(sii, intr_val); ++ ++ idx = sii->curidx; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ n = R_REG(sii->osh, &cc->clockcontrol_n); ++ pll_type = sih->cccaps & CC_CAP_PLL_MASK; ++ if (pll_type == PLL_TYPE6) ++ m = R_REG(sii->osh, &cc->clockcontrol_m3); ++ else if (pll_type == PLL_TYPE3) ++ m = R_REG(sii->osh, &cc->clockcontrol_m2); ++ else ++ m = R_REG(sii->osh, &cc->clockcontrol_sb); ++ ++ /* calculate rate */ ++ rate = si_clock_rate(pll_type, n, m); ++ ++ if (pll_type == PLL_TYPE3) ++ rate = rate / 2; ++ ++ /* switch back to previous core */ ++ si_setcoreidx(sih, idx); ++ ++ INTR_RESTORE(sii, intr_val); ++ ++ return rate; ++} ++ ++uint32 ++BCMINITFN(si_alp_clock)(si_t *sih) ++{ ++ if (IS_IPROC_CHIP_ID(CHIPID(sih->chip))) { ++ if (sih->chippkg == BCM4709_PKG_ID) ++ return NS_ALP_CLOCK; ++ else ++ return NS_SLOW_ALP_CLOCK; ++ } ++ ++ return NS_ALP_CLOCK; ++} ++ ++ ++#if defined(BCMDBG) ++/* print interesting sbconfig registers */ ++void ++si_dumpregs(si_t *sih, struct bcmstrbuf *b) ++{ ++ si_info_t *sii; ++ uint origidx, intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ origidx = sii->curidx; ++ ++ INTR_OFF(sii, intr_val); ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_dumpregs(sih, b); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_dumpregs(sih, b); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_dumpregs(sih, b); ++ else ++ ASSERT(0); ++ ++ si_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++} ++#endif ++ ++#ifdef BCMDBG ++void ++si_view(si_t *sih, bool verbose) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_view(sih, verbose); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_view(sih, verbose); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_view(sih, verbose); ++ else ++ ASSERT(0); ++} ++ ++void ++si_viewall(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ uint curidx, i; ++ uint intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ curidx = sii->curidx; ++ ++ INTR_OFF(sii, intr_val); ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_viewall(sih, verbose); ++ else { ++ SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores)); ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(sih, i); ++ si_view(sih, verbose); ++ } ++ } ++ si_setcoreidx(sih, curidx); ++ INTR_RESTORE(sii, intr_val); ++} ++#endif /* BCMDBG */ ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ++si_slowclk_src(si_info_t *sii) ++{ ++ chipcregs_t *cc; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ if (sii->pub.ccrev < 6) { ++ return (SCC_SS_XTAL); ++ } else if (sii->pub.ccrev < 10) { ++ cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); ++ return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); ++ } else /* Insta-clock */ ++ return (SCC_SS_XTAL); ++} ++ ++/* return the ILP (slowclock) min or max frequency */ ++static uint ++si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) ++{ ++ uint32 slowclk; ++ uint div; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ /* shouldn't be here unless we've established the chip has dynamic clk control */ ++ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); ++ ++ slowclk = si_slowclk_src(sii); ++ if (sii->pub.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); ++ else ++ return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); ++ } else if (sii->pub.ccrev < 10) { ++ div = 4 * ++ (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return (max_freq ? LPOMAXFREQ : LPOMINFREQ); ++ else if (slowclk == SCC_SS_XTAL) ++ return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); ++ else if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); ++ else ++ ASSERT(0); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); ++ } ++ return (0); ++} ++ ++static void ++BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs) ++{ ++ chipcregs_t *cc = (chipcregs_t *)chipcregs; ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; ++ ++ pll_delay = PLL_DELAY; ++ ++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay ++ * since the xtal will also be powered down by dynamic clk control logic. ++ */ ++ ++ slowclk = si_slowclk_src(sii); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; ++ ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); ++ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ ++ W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); ++ W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); ++} ++ ++/* initialize power control delay registers */ ++void ++BCMINITFN(si_clkctl_init)(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx = 0; ++ chipcregs_t *cc; ++ bool fast; ++ ++ if (!CCCTL_ENAB(sih)) ++ return; ++ ++ sii = SI_INFO(sih); ++ fast = SI_FAST(sii); ++ if (!fast) { ++ origidx = sii->curidx; ++ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) ++ return; ++ } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) ++ return; ++ ASSERT(cc != NULL); ++ ++ /* set all Instaclk chip ILP to 1 MHz */ ++ if (sih->ccrev >= 10) ++ SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); ++ ++ si_clkctl_setdelay(sii, (void *)(uintptr)cc); ++ ++ if (!fast) ++ si_setcoreidx(sih, origidx); ++} ++ ++/* turn primary xtal and/or pll off/on */ ++int ++si_clkctl_xtal(si_t *sih, uint what, bool on) ++{ ++ switch (BUSTYPE(sih->bustype)) { ++ ++ default: ++ return (-1); ++ } ++ ++} ++ ++/* ++ * clock control policy function throught chipcommon ++ * ++ * set dynamic clk control mode (forceslow, forcefast, dynamic) ++ * returns true if we are forcing fast clock ++ * this is a wrapper over the next internal function ++ * to allow flexible policy settings for outside caller ++ */ ++bool ++si_clkctl_cc(si_t *sih, uint mode) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sih->ccrev < 6) ++ return FALSE; ++ ++ if (PCI_FORCEHT(sii)) ++ return (mode == CLK_FAST); ++ ++ return _si_clkctl_cc(sii, mode); ++} ++ ++/* clk control mechanism through chipcommon, no policy checking */ ++static bool ++_si_clkctl_cc(si_info_t *sii, uint mode) ++{ ++ uint origidx = 0; ++ chipcregs_t *cc; ++ uint32 scc; ++ uint intr_val = 0; ++ bool fast = SI_FAST(sii); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sii->pub.ccrev < 6) ++ return (FALSE); ++ ++ /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ ++ ASSERT(sii->pub.ccrev != 10); ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ origidx = sii->curidx; ++ ++ if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && ++ si_setcore(&sii->pub, MIPS33_CORE_ID, 0) && ++ (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10)) ++ goto done; ++ ++ cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0); ++ } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL) ++ goto done; ++ ASSERT(cc != NULL); ++ ++ if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20)) ++ goto done; ++ ++ switch (mode) { ++ case CLK_FAST: /* FORCEHT, fast (pll) clock */ ++ if (sii->pub.ccrev < 10) { ++ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ ++ si_clkctl_xtal(&sii->pub, XTAL, ON); ++ SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ } else if (sii->pub.ccrev < 20) { ++ OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR); ++ } else { ++ OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT); ++ } ++ ++ /* wait for the PLL */ ++ if (PMUCTL_ENAB(&sii->pub)) { ++ uint32 htavail = CCS_HTAVAIL; ++ if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID) ++ htavail = CCS0_HTAVAIL; ++ SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0), ++ PMU_MAX_TRANSITION_DLY); ++ ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail); ++ } else { ++ OSL_DELAY(PLL_DELAY); ++ } ++ break; ++ ++ case CLK_DYNAMIC: /* enable dynamic clock control */ ++ if (sii->pub.ccrev < 10) { ++ scc = R_REG(sii->osh, &cc->slow_clk_ctl); ++ scc &= ~(SCC_FS | SCC_IP | SCC_XC); ++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) ++ scc |= SCC_XC; ++ W_REG(sii->osh, &cc->slow_clk_ctl, scc); ++ ++ /* for dynamic control, we have to release our xtal_pu "force on" */ ++ if (scc & SCC_XC) ++ si_clkctl_xtal(&sii->pub, XTAL, OFF); ++ } else if (sii->pub.ccrev < 20) { ++ /* Instaclock */ ++ AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR); ++ } else { ++ AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT); ++ } ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++done: ++ if (!fast) { ++ si_setcoreidx(&sii->pub, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return (mode == CLK_FAST); ++} ++ ++/* Build device path. Support SI, PCI, and JTAG for now. */ ++int ++BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size) ++{ ++ int slen; ++ ++ ASSERT(path != NULL); ++ ASSERT(size >= SI_DEVPATH_BUFSZ); ++ ++ if (!path || size <= 0) ++ return -1; ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih)); ++ break; ++ default: ++ slen = -1; ++ ASSERT(0); ++ break; ++ } ++ ++ if (slen < 0 || slen >= size) { ++ path[0] = '\0'; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++char * ++BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name) ++{ ++ char pathname[SI_DEVPATH_BUFSZ + 32]; ++ char devpath[SI_DEVPATH_BUFSZ + 32]; ++ char *p; ++ int idx; ++ int len; ++ ++ /* try to get compact devpath if it exist */ ++ if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) { ++ len = strlen(devpath); ++ devpath[len - 1] = '\0'; ++ for (idx = 0; idx < SI_MAXCORES; idx++) { ++ snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx); ++ if ((p = getvar(NULL, pathname)) == NULL) ++ continue; ++ ++ if (strncmp(p, devpath, len) == 0) { ++ snprintf(varname, var_len, "%d:%s", idx, name); ++ return varname; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/* Get a variable, but only if it has a devpath prefix */ ++int ++BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name) ++{ ++#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS) ++ return (getintvar(NULL, name)); ++#else ++ char varname[SI_DEVPATH_BUFSZ + 32]; ++ int val; ++ ++ si_devpathvar(sih, varname, sizeof(varname), name); ++ ++ if ((val = getintvar(NULL, varname)) != 0) ++ return val; ++ ++ /* try to get compact devpath if it exist */ ++ if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL) ++ return 0; ++ ++ return (getintvar(NULL, varname)); ++#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */ ++} ++ ++/* Concatenate the dev path with a varname into the given 'var' buffer ++ * and return the 'var' pointer. ++ * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned. ++ * On overflow, the first char will be set to '\0'. ++ */ ++static char * ++BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name) ++{ ++ uint path_len; ++ ++ if (!var || len <= 0) ++ return var; ++ ++ if (si_devpath(sih, var, len) == 0) { ++ path_len = strlen(var); ++ ++ if (strlen(name) + 1 > (uint)(len - path_len)) ++ var[0] = '\0'; ++ else ++ strncpy(var + path_len, name, len - path_len - 1); ++ } ++ ++ return var; ++} ++ ++ ++#if defined(BCMDBG) ++#endif ++ ++ ++/* mask&set gpio output enable bits */ ++uint32 ++si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioouten); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* mask&set gpio output bits */ ++uint32 ++si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioout); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h b/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h +new file mode 100755 +index 0000000..56650d1 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch new file mode 100644 index 00000000..15ce4216 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch @@ -0,0 +1,265 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h +@@ -0,0 +1,259 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Include file private to the SOC Interconnect support files. ++ * ++ * $Id: siutils_priv.h 302333 2011-12-11 01:47:49Z $ ++ */ ++ ++#ifndef _siutils_priv_h_ ++#define _siutils_priv_h_ ++ ++#ifdef BCMDBG_ERR ++#define SI_ERROR(args) printf args ++#else ++#define SI_ERROR(args) ++#endif /* BCMDBG_ERR */ ++ ++#ifdef BCMDBG ++#define SI_MSG(args) printf args ++#else ++#define SI_MSG(args) ++#endif /* BCMDBG */ ++ ++#ifdef BCMDBG_SI ++#define SI_VMSG(args) printf args ++#else ++#define SI_VMSG(args) ++#endif ++ ++#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) ++ ++ ++typedef uint32 (*si_intrsoff_t)(void *intr_arg); ++typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); ++typedef bool (*si_intrsenabled_t)(void *intr_arg); ++ ++typedef struct gpioh_item { ++ void *arg; ++ bool level; ++ gpio_handler_t handler; ++ uint32 event; ++ struct gpioh_item *next; ++} gpioh_item_t; ++ ++/* misc si info needed by some of the routines */ ++typedef struct si_info { ++ struct si_pub pub; /* back plane public state (must be first field) */ ++ ++ void *osh; /* osl os handle */ ++ void *sdh; /* bcmsdh handle */ ++ ++ uint dev_coreid; /* the core provides driver functions */ ++ void *intr_arg; /* interrupt callback function arg */ ++ si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ ++ si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ ++ si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ ++ ++ void *pch; /* PCI/E core handle */ ++ ++ gpioh_item_t *gpioh_head; /* GPIO event handlers list */ ++ ++ bool memseg; /* flag to toggle MEM_SEG register */ ++ ++ char *vars; ++ uint varsz; ++ ++ void *curmap; /* current regs va */ ++ void *regs[SI_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SI_MAXCORES]; /* id of each core */ ++ uint32 coresba[SI_MAXCORES]; /* backplane address of each core */ ++ void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */ ++ uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */ ++ uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */ ++ uint32 coresba2_size[SI_MAXCORES]; /* second address space size */ ++ ++ void *curwrap; /* current wrapper va */ ++ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ ++ uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ ++ ++ uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 oob_router; /* oob router registers for axi */ ++} si_info_t; ++ ++#define SI_INFO(sih) (si_info_t *)(uintptr)sih ++ ++#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ ++ ISALIGNED((x), SI_CORE_SIZE)) ++#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE)) ++#define BADCOREADDR 0 ++#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES) ++#define NOREV -1 /* Invalid rev */ ++ ++#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCI_CORE_ID)) ++ ++#define PCIE_GEN1(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE_CORE_ID)) ++ ++#define PCIE_GEN2(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE2_CORE_ID)) ++ ++#define PCIE(si) (PCIE_GEN1(si) || PCIE_GEN2(si)) ++ ++#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE)) ++ ++/* Newer chips can access PCI/PCIE and CC core without requiring to change ++ * PCI BAR0 WIN ++ */ ++#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13))) ++ ++#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET)) ++#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET)) ++ ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ ++ * after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } ++ ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++#define PCI_FORCEHT(si) \ ++ (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ ++ ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4716_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4748_CHIP_ID))) ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ ++ ++#ifndef DEFAULT_GPIOTIMERVAL ++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++#endif ++ ++#define sb_scan(a, b, c) do {} while (0) ++#define sb_coreid(a) (0) ++#define sb_intflag(a) (0) ++#define sb_flag(a) (0) ++#define sb_setint(a, b) do {} while (0) ++#define sb_corevendor(a) (0) ++#define sb_corerev(a) (0) ++#define sb_corereg(a, b, c, d, e) (0) ++#define sb_iscoreup(a) (false) ++#define sb_setcoreidx(a, b) (0) ++#define sb_core_cflags(a, b, c) (0) ++#define sb_core_cflags_wo(a, b, c) do {} while (0) ++#define sb_core_sflags(a, b, c) (0) ++#define sb_commit(a) do {} while (0) ++#define sb_base(a) (0) ++#define sb_size(a) (0) ++#define sb_core_reset(a, b, c) do {} while (0) ++#define sb_core_disable(a, b) do {} while (0) ++#define sb_addrspace(a, b) (0) ++#define sb_addrspacesize(a, b) (0) ++#define sb_numaddrspaces(a) (0) ++#define sb_set_initiator_to(a, b, c) (0) ++#define sb_taclear(a, b) (false) ++#define sb_view(a, b) do {} while (0) ++#define sb_viewall(a, b) do {} while (0) ++#define sb_dump(a, b) do {} while (0) ++#define sb_dumpregs(a, b) do {} while (0) ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool sb_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool sb_pci_fastpmecap(struct osl_info *osh); ++extern bool sb_pci_pmeclr(si_t *sih); ++extern void sb_pci_pmeen(si_t *sih); ++extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset); ++ ++/* AMBA Interconnect exported externs */ ++extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *ai_kattach(osl_t *osh); ++extern void ai_scan(si_t *sih, void *regs, uint devid); ++ ++extern uint ai_flag(si_t *sih); ++extern void ai_setint(si_t *sih, int siflag); ++extern uint ai_coreidx(si_t *sih); ++extern uint ai_corevendor(si_t *sih); ++extern uint ai_corerev(si_t *sih); ++extern bool ai_iscoreup(si_t *sih); ++extern void *ai_setcoreidx(si_t *sih, uint coreidx); ++extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); ++extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void ai_core_disable(si_t *sih, uint32 bits); ++extern int ai_numaddrspaces(si_t *sih); ++extern uint32 ai_addrspace(si_t *sih, uint asidx); ++extern uint32 ai_addrspacesize(si_t *sih, uint asidx); ++extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++ ++#ifdef BCMDBG ++extern void ai_view(si_t *sih, bool verbose); ++extern void ai_viewall(si_t *sih, bool verbose); ++#endif ++#if defined(BCMDBG) ++extern void ai_dumpregs(si_t *sih, struct bcmstrbuf *b); ++#endif ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++extern void si_enum_base_init(si_t *sih, uint bustype); ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++#define ub_scan(a, b, c) do {} while (0) ++#define ub_flag(a) (0) ++#define ub_setint(a, b) do {} while (0) ++#define ub_coreidx(a) (0) ++#define ub_corevendor(a) (0) ++#define ub_corerev(a) (0) ++#define ub_iscoreup(a) (0) ++#define ub_setcoreidx(a, b) (0) ++#define ub_core_cflags(a, b, c) (0) ++#define ub_core_cflags_wo(a, b, c) do {} while (0) ++#define ub_core_sflags(a, b, c) (0) ++#define ub_corereg(a, b, c, d, e) (0) ++#define ub_core_reset(a, b, c) do {} while (0) ++#define ub_core_disable(a, b) do {} while (0) ++#define ub_numaddrspaces(a) (0) ++#define ub_addrspace(a, b) (0) ++#define ub_addrspacesize(a, b) (0) ++#define ub_view(a, b) do {} while (0) ++#define ub_dumpregs(a, b) do {} while (0) ++ ++#endif /* _siutils_priv_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/wl_config b/drivers/bcmdrivers/gmac/src/shared/wl_config +new file mode 100755 +index 0000000..aded587 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch new file mode 100644 index 00000000..d97df5b0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gmac_src_shared_wl_config.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/wl_config +@@ -0,0 +1,26 @@ ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# wl driver config shared hnd files ++# ++ ++HNDDMA=1 ++BCMUTILS=1 ++SIUTILS=1 ++#BCMSROM=1 ++#BCMOTP=1 ++BCMDMA32=1 ++ ++# OSL shared ++OSLLX=1 +diff --git a/drivers/bcmdrivers/gpio/.gitignore b/drivers/bcmdrivers/gpio/.gitignore +new file mode 100644 +index 0000000..9463d48 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch new file mode 100644 index 00000000..cabe97c8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_.gitignore.patch @@ -0,0 +1,18 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/.gitignore +@@ -0,0 +1,12 @@ ++/.built-in.o.cmd ++/.gpio_cfg.o.cmd ++/.gpio.o.cmd ++/.gpiolib.o.cmd ++/.iproc_gpio.o.cmd ++/built-in.o ++/gpio_cfg.o ++/gpio.o ++/gpiolib.o ++/iproc_gpio.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gpio/Kconfig b/drivers/bcmdrivers/gpio/Kconfig +new file mode 100644 +index 0000000..0bcd76f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch new file mode 100644 index 00000000..943286e0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Kconfig.patch @@ -0,0 +1,17 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/Kconfig +@@ -0,0 +1,11 @@ ++config IPROC_GPIO ++ tristate "GPIO support" ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select GPIOLIB ++ depends on ARCH_IPROC ++ default y ++ help ++ Add GPIO support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/gpio/Makefile b/drivers/bcmdrivers/gpio/Makefile +new file mode 100644 +index 0000000..edbecf6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch new file mode 100644 index 00000000..af195cbb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_GPIO) += iproc_gpio.o ++iproc_gpio-objs := gpio.o gpio_cfg.o gpiolib.o +diff --git a/drivers/bcmdrivers/gpio/gpio.c b/drivers/bcmdrivers/gpio/gpio.c +new file mode 100644 +index 0000000..cd41cf6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch new file mode 100644 index 00000000..2fd2834a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.c.patch @@ -0,0 +1,750 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio.c +@@ -0,0 +1,744 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#include "gpio.h" ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) ++#define irq_get_chip_data get_irq_chip_data ++#define irq_set_chip_data set_irq_chip_data ++#define irq_set_chip set_irq_chip ++#define irq_set_handler set_irq_handler ++#define status_use_accessors status ++#endif ++ ++ ++static struct iproc_gpio_chip *iproc_gpio_dev[MAX_NS_GPIO] = {}; ++static int dev = 0; ++ ++static unsigned int _iproc_gpio_readl(struct iproc_gpio_chip *chip, int reg) ++{ ++ return readl(chip->ioaddr + reg); ++} ++ ++static void _iproc_gpio_writel(struct iproc_gpio_chip *chip, unsigned int val, int reg) ++{ ++ writel(val, chip->ioaddr + reg); ++} ++ ++ ++/* ++@ pin : the actual pin number of the gpiochip ++*/ ++static int iproc_gpio_to_irq(struct iproc_gpio_chip *chip, unsigned int pin) { ++ return (chip->irq_base + pin - chip->pin_offset); ++} ++ ++/* ++returns the actual pin number of the gpiochip ++*/ ++static int iproc_irq_to_gpio(struct iproc_gpio_chip *chip, unsigned int irq) { ++ return (irq - chip->irq_base + chip->pin_offset); ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_ack(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_ack(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->ack) ++ irqcfg->ack(irq); ++ ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_unmask(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_unmask(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->unmask) ++ irqcfg->unmask(irq); ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_mask(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_mask(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->mask) ++ irqcfg->mask(irq); ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static int iproc_gpio_irq_set_type(unsigned int irq, unsigned int type) ++{ ++#else ++static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->set_type) ++ return irqcfg->set_type(irq, type); ++ } ++ return -EINVAL; ++} ++ ++#if defined(IPROC_GPIO_CCA) ++static irqreturn_t ++iproc_gpio_irq_handler_cca(int irq, void *dev) ++ ++{ ++ unsigned int val, irq_type; ++ unsigned int int_mask, int_pol, in; ++ unsigned int event_mask, event, event_pol, tmp = 0; ++ int iter, g_irq, max_pin; ++ struct iproc_gpio_chip *ourchip = dev; ++ ++ ++ val = readl(ourchip->intr_ioaddr + IPROC_CCA_INT_STS); ++ ++ if (val & IPROC_CCA_INT_F_GPIOINT) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); ++ in = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_DIN); ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ event = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT); ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ ++ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { ++ g_irq = iproc_gpio_to_irq(ourchip, iter); ++ irq_type = irq_desc[g_irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ switch(irq_type) { ++ case IRQ_TYPE_EDGE_RISING: ++ tmp = event_mask; ++ tmp &= event; ++ tmp &= ~event_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ tmp = event_mask; ++ tmp &= event; ++ tmp &= event_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ tmp = in ^ int_pol; ++ tmp &= int_mask; ++ tmp &= int_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ tmp = in ^ int_pol; ++ tmp &= int_mask; ++ tmp &= ~int_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ }else { ++ return IRQ_NONE; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_status, irq_type; ++ ++ event_status = 0; ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) ++ { ++ event_status |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_status, ++ IPROC_GPIO_CCA_INT_EVENT); ++ } ++ ++ } ++} ++ ++static void iproc_gpio_irq_unmask_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask, irq_type; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_mask; ++ ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, event_mask, ++ IPROC_GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, int_mask, ++ IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ } ++ } ++ ++} ++ ++static void iproc_gpio_irq_mask_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int irq_type, int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_mask; ++ ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_mask, ++ IPROC_GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, ++ IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ } ++ } ++} ++ ++static int iproc_gpio_irq_set_type_cca(unsigned int irq, unsigned int type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_pol, int_pol; ++ ++ switch (type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_RISING: ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ event_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ event_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); ++ int_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_pol = _iproc_gpio_readl(ourchip,IPROC_GPIO_CCA_INT_LEVEL); ++ int_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); ++ break; ++ default: ++ printk(KERN_ERR "unsupport irq type !\n"); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg cca_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND|IRQF_SHARED, ++ .handler = iproc_gpio_irq_handler_cca, ++ .ack = iproc_gpio_irq_ack_cca, ++ .mask = iproc_gpio_irq_mask_cca, ++ .unmask = iproc_gpio_irq_unmask_cca, ++ .set_type = iproc_gpio_irq_set_type_cca, ++}; ++#endif /* IPROC_GPIO_CCA */ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++static irqreturn_t ++iproc_gpio_irq_handler_ccb(int irq, void *dev) ++{ ++ struct iproc_gpio_chip *ourchip = dev; ++ int iter, max_pin; ++ unsigned int val; ++ ++ val = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MSTAT); ++ if(!val){ ++ return IRQ_NONE; ++ } ++ ++ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { ++ if (val & (1 << iter)) { ++ generic_handle_irq(iproc_gpio_to_irq(ourchip, iter)); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned int int_clear = 0; ++ ++ int_clear |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_clear, IPROC_GPIO_CCB_INT_CLR); ++ ++ } ++} ++ ++static void iproc_gpio_irq_unmask_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); ++ int_mask |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, IPROC_GPIO_CCB_INT_MASK); ++ } ++ ++} ++ ++static void iproc_gpio_irq_mask_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask,IPROC_GPIO_CCB_INT_MASK); ++ } ++} ++ ++static int iproc_gpio_irq_set_type_ccb(unsigned int irq, unsigned int type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned int int_type, int_de, int_edge; ++ int_type = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_TYPE); ++ int_edge = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_EDGE); ++ switch (type) { ++ case IRQ_TYPE_EDGE_BOTH: ++ int_type &= ~(1 << pin); ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ int_type &= ~(1 << pin); ++ int_edge |= (1 << pin); ++ ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ int_type &= ~(1 << pin); ++ int_edge &= ~(1 << pin); ++ ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_type |= (1 << pin); ++ int_edge |= (1 << pin); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_type |= (1 << pin); ++ int_edge &= ~(1 << pin); ++ break; ++ default: ++ printk(KERN_ERR "unsupport irq type !\n"); ++ return -EINVAL; ++ } ++ _iproc_gpio_writel(ourchip, int_type, IPROC_GPIO_CCB_INT_TYPE); ++ _iproc_gpio_writel(ourchip, int_edge, IPROC_GPIO_CCB_INT_EDGE); ++ } ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg ccb_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND, ++ .handler = iproc_gpio_irq_handler_ccb, ++ .ack = iproc_gpio_irq_ack_ccb, ++ .mask = iproc_gpio_irq_mask_ccb, ++ .unmask = iproc_gpio_irq_unmask_ccb, ++ .set_type = iproc_gpio_irq_set_type_ccb, ++}; ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG*/ ++ ++ ++static struct irq_chip iproc_gpio_irq_chip = { ++ .name = "IPROC-GPIO", ++#if 0 ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++ .ack = (void *) iproc_gpio_irq_ack, ++ .mask = (void *) iproc_gpio_irq_mask, ++ .unmask = (void *) iproc_gpio_irq_unmask, ++ .set_type = (void *) iproc_gpio_irq_set_type, ++//#else ++#endif ++ .irq_ack = (void *) iproc_gpio_irq_ack, ++ .irq_mask = (void *) iproc_gpio_irq_mask, ++ .irq_unmask = (void *) iproc_gpio_irq_unmask, ++ .irq_set_type = (void *) iproc_gpio_irq_set_type, ++//#endif ++}; ++ ++struct iproc_gpio_chip *iproc_gpios[IPROC_GPIO_END]; ++ ++static __init void iproc_gpiolib_track(struct iproc_gpio_chip *chip) ++{ ++ unsigned int gpn; ++ int i; ++ ++ gpn = chip->chip.base; ++ for (i = 0; i < chip->chip.ngpio; i++, gpn++) { ++ BUG_ON(gpn >= ARRAY_SIZE(iproc_gpios)); ++ iproc_gpios[gpn] = chip; ++ } ++} ++ ++static int iproc_gpiolib_input(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned int val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val &= ~nBitMask; ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_EN); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ return 0; ++} ++ ++static int iproc_gpiolib_output(struct gpio_chip *chip, ++ unsigned gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned long val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val |= nBitMask; ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_EN); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ return 0; ++} ++ ++static void iproc_gpiolib_set(struct gpio_chip *chip, ++ unsigned gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned long val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ ++ /* determine the GPIO pin direction ++ */ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val &= nBitMask; ++ ++ /* this function only applies to output pin ++ */ ++ if (!val) ++ return; ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ ++ if ( value == 0 ){ ++ /* Set the pin to zero */ ++ val &= ~nBitMask; ++ }else{ ++ /* Set the pin to 1 */ ++ val |= nBitMask; ++ } ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_DOUT); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ ++} ++ ++ ++static int iproc_gpiolib_get(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned int val, offset; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ /* determine the GPIO pin direction ++ */ ++ offset = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ offset &= nBitMask; ++ ++ if (offset){ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ } else { ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DIN); ++ } ++ val >>= pin_offset; ++ val &= 1; ++ iproc_gpio_unlock(ourchip, flags); ++ ++ return val; ++} ++ ++/* ++@offset : the gpio pin index number from gpiolib view (minus gpio base only) ++*/ ++static int iproc_gpiolib_to_irq(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ return iproc_gpio_to_irq(ourchip, offset + ourchip->pin_offset); ++} ++void __init iproc_gpiolib_add(struct iproc_gpio_chip *chip) ++{ ++ struct resource *res; ++ struct gpio_chip *gc = &chip->chip; ++ int ret, i; ++ ++ BUG_ON(!gc->label); ++ BUG_ON(!gc->ngpio); ++ ++ spin_lock_init(&chip->lock); ++ ++ if (!gc->direction_input) ++ gc->direction_input = iproc_gpiolib_input; ++ if (!gc->direction_output) ++ gc->direction_output = iproc_gpiolib_output; ++ if (!gc->set) ++ gc->set = iproc_gpiolib_set; ++ if (!gc->get) ++ gc->get = iproc_gpiolib_get; ++ if (!gc->to_irq) ++ gc->to_irq = iproc_gpiolib_to_irq; ++ ++ /* gpiochip_add() prints own failure message on error. */ ++ ret = gpiochip_add(gc); ++ if (ret >= 0) ++ iproc_gpiolib_track(chip); ++ ++ printk(KERN_INFO "iproc gpiochip add %s\n", gc->label); ++ /* io remap */ ++ res = chip->resource; ++ ++ chip->ioaddr = ioremap_nocache(res->start, (res->end - res->start) + 1); ++ printk(KERN_INFO "%s:ioaddr %p \n", gc->label, chip->ioaddr); ++ chip->intr_ioaddr = NULL; ++ chip->dmu_ioaddr = NULL; ++ if(res->child){ ++ for (i=0; i< 2; i++){ ++ if (!strcmp("intr", res->child[i].name)){ ++ chip->intr_ioaddr = ++ ioremap_nocache(res->child[i].start, ++ (res->child[i].end - res->child[i].start) + 1); ++ } ++ if (!strcmp("dmu", res->child[i].name)){ ++ chip->dmu_ioaddr = ++ ioremap_nocache(res->child[i].start, ++ (res->child[i].end - res->child[i].start) + 1); ++ } ++ } ++ printk(KERN_INFO "%s:intr_ioaddr %p dmu_ioaddr %p\n", ++ gc->label, chip->intr_ioaddr,chip->dmu_ioaddr); ++ } ++ ++ ++ if (chip->irq_base) { ++ for (i = chip->irq_base; i < (chip->irq_base + gc->ngpio); i++) { ++ irq_set_chip(i, &iproc_gpio_irq_chip); ++ irq_set_chip_data(i,chip); ++ irq_set_handler(i, handle_level_irq); ++ set_irq_flags(i, IRQF_VALID); ++ ++ } ++#if defined(IPROC_GPIO_CCA) ++ if (chip->id == IPROC_GPIO_CCA_ID ){ ++ unsigned int val; ++ /* enable the GPIO in CCA interrupt mask */ ++ val = readl(chip->intr_ioaddr + IPROC_CCA_INT_MASK); ++ val |= IPROC_CCA_INT_F_GPIOINT; ++ writel(val, chip->intr_ioaddr + IPROC_CCA_INT_MASK); ++ } ++#endif ++ if (chip->irqcfg) { ++ struct iproc_gpio_irqcfg *irqcfg = chip->irqcfg; ++ if (irqcfg->handler) { ++ ret = request_irq(chip->irq, irqcfg->handler, irqcfg->flags, ++ gc->label, chip); ++ if (ret) ++ printk(KERN_ERR "Unable to request IRQ%d: %d\n", ++ chip->irq, ret); ++ } ++ else ++ printk(KERN_ERR "%s is added without isr!\n", chip->chip.label); ++ } ++ } ++ iproc_gpio_dev[dev] = chip; ++ dev++; ++} ++ ++static int __init gpio_init(void) ++{ ++ iproc_gpiolib_init(); ++ ++ return 0; ++} ++static void __exit gpio_exit(void) ++{ ++ int i=0; ++ ++ for (i = 0 ; i < MAX_NS_GPIO; i++) { ++ if(iproc_gpio_dev[i]){ ++ if(iproc_gpio_dev[i]->ioaddr){ ++ iounmap(iproc_gpio_dev[i]->ioaddr); ++ } ++ if(iproc_gpio_dev[i]->intr_ioaddr){ ++#if defined(IPROC_GPIO_CCA) ++ if (iproc_gpio_dev[i]->id == IPROC_GPIO_CCA_ID ){ ++ unsigned int val; ++ val = readl(iproc_gpio_dev[i]->intr_ioaddr + IPROC_CCA_INT_MASK); ++ val &= ~(IPROC_CCA_INT_F_GPIOINT); ++ writel(val, iproc_gpio_dev[i]->intr_ioaddr + IPROC_CCA_INT_MASK); ++ } ++#endif ++ iounmap(iproc_gpio_dev[i]->intr_ioaddr); ++ } ++ if(iproc_gpio_dev[i]->dmu_ioaddr){ ++ iounmap(iproc_gpio_dev[i]->dmu_ioaddr); ++ } ++ if(iproc_gpio_dev[i]->irq_base) { ++ free_irq(iproc_gpio_dev[i]->irq,iproc_gpio_dev[i]); ++ } ++ ++ gpiochip_remove(&iproc_gpio_dev[i]->chip); ++ iproc_gpio_dev[i] = NULL; ++ } ++ } ++} ++ ++MODULE_DESCRIPTION("IPROC GPIO driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(gpio_init); ++module_exit(gpio_exit); +diff --git a/drivers/bcmdrivers/gpio/gpio.h b/drivers/bcmdrivers/gpio/gpio.h +new file mode 100644 +index 0000000..bfc44f7 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch new file mode 100644 index 00000000..63f451cd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio.h.patch @@ -0,0 +1,107 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_PLAT_GPIO_H ++#define __IPROC_PLAT_GPIO_H ++ ++#include ++ ++#if defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG ++#else ++#define IPROC_GPIO_CCA ++#define IPROC_GPIO_CCB ++#endif ++ ++#define IPROC_GPIO_REG_SIZE (0x50) ++ ++ ++ ++ ++ ++#define REGOFFSET_GPIO_DIN 0x000 /* GPIO Data in register */ ++#define REGOFFSET_GPIO_DOUT 0x004 /* GPIO Data out register */ ++#define REGOFFSET_GPIO_EN 0x008 /* GPIO driver enable register */ ++ ++ ++#define IPROC_GPIO_CCA_ID (0) ++#define IPROC_GPIO_CCB_ID (1) ++#define IPROC_GPIO_CCG_ID (2) ++ ++#define IPROC_GPIO_CCA_IRQ_BASE (IPROC_IRQ_GPIO_0) ++#define IPROC_GPIO_CCB_IRQ_BASE (IPROC_IRQ_GPIO_0 + 32) ++#define IPROC_GPIO_CCG_IRQ_BASE (IPROC_IRQ_GPIO_0) ++ ++ ++ ++ ++#define IPROC_CCA_INT_F_GPIOINT (1) ++ ++struct iproc_gpio_irqcfg { ++ unsigned long flags; ++ irqreturn_t (*handler)(int irq, void *dev); ++ void (*ack)(unsigned int irq); ++ void (*unmask)(unsigned int irq); ++ void (*mask)(unsigned int irq); ++ int (*set_type)(unsigned int irq, unsigned int type); ++}; ++ ++struct iproc_gpio_chip { ++ int id; ++ struct gpio_chip chip; ++ struct iproc_gpio_cfg *config; ++ void __iomem *ioaddr; ++ void __iomem *intr_ioaddr; ++ void __iomem *dmu_ioaddr; ++ spinlock_t lock; ++ int irq_base; ++ struct resource * resource; ++ int irq; ++ struct iproc_gpio_irqcfg *irqcfg; ++ int pin_offset; ++}; ++ ++ ++static inline struct iproc_gpio_chip *to_iproc_gpio(struct gpio_chip *gpc) ++{ ++ return container_of(gpc, struct iproc_gpio_chip, chip); ++} ++ ++#define IPROC_GPIO_END (32 + 4) ++ ++extern struct iproc_gpio_chip *iproc_gpios[IPROC_GPIO_END]; ++ ++static inline struct iproc_gpio_chip *iproc_gpiolib_getchip(unsigned int chip) ++{ ++ return (chip < IPROC_GPIO_END) ? iproc_gpios[chip] : NULL; ++} ++ ++/* locking wrappers to deal with multiple access to the same gpio bank */ ++#define iproc_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) ++#define iproc_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) ++ ++extern void iproc_gpiolib_add(struct iproc_gpio_chip *chip); ++extern int iproc_gpiolib_init(void); ++ ++#define MAX_NS_GPIO 2 ++ ++#endif +diff --git a/drivers/bcmdrivers/gpio/gpio_cfg.c b/drivers/bcmdrivers/gpio/gpio_cfg.c +new file mode 100644 +index 0000000..2bd1a74 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch new file mode 100644 index 00000000..d4d59972 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.c.patch @@ -0,0 +1,408 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio_cfg.c +@@ -0,0 +1,402 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "gpio.h" ++#include "gpio_cfg.h" ++ ++#if defined(IPROC_GPIO_CCA) ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++int iproc_gpio_set_config_cca(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ aux_sel_reg = IPROC_GPIO_CCA_CTRL0; ++ base = (unsigned int)chip->dmu_ioaddr; ++ if(off <= 17){ ++ pin = 1 << off; ++ } else if (off >= 21){ ++ pin = 1 << (off - 3); ++ } else { ++ if (cfg == IPROC_GPIO_AUX_FUN) ++ return -EINVAL; ++ else ++ return 0; ++ } ++ } ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ switch (cfg) { ++ case IPROC_GPIO_GENERAL: ++ aux_sel |= pin; ++ break; ++ case IPROC_GPIO_AUX_FUN: ++ aux_sel &= ~(pin); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(aux_sel, base + aux_sel_reg); ++ ++ return 0; ++} ++ ++ ++unsigned iproc_gpio_get_config_cca(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ ++ aux_sel_reg = IPROC_GPIO_CCA_CTRL0; ++ base = (unsigned int)chip->dmu_ioaddr; ++ if(off <= 17){ ++ pin = 1 << off; ++ } else if (off >= 21){ ++ pin = 1 << (off - 3); ++ } else { ++ return IPROC_GPIO_GENERAL; ++ } ++ } ++ ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ if (aux_sel & pin) { ++ return IPROC_GPIO_GENERAL; ++ } else { ++ return IPROC_GPIO_AUX_FUN; ++ } ++} ++ ++ ++int iproc_gpio_setpull_updown_cca(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull) ++{ ++ unsigned int base; ++ base = 0; ++ ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ unsigned long pull_up, pull_down; ++ ++ base = (unsigned int)chip->dmu_ioaddr; ++ ++ pull_up = readl_relaxed(base + IPROC_GPIO_CCA_PULL_UP); ++ pull_down = readl_relaxed(base + IPROC_GPIO_CCA_PULL_DOWN); ++ ++ switch (pull) { ++ case IPROC_GPIO_PULL_UP: ++ pull_up |= (1 << off); ++ pull_down &= ~(1 << off); ++ break; ++ case IPROC_GPIO_PULL_DOWN: ++ pull_up &= ~(1 << off); ++ pull_down |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_NONE: ++ pull_up &= ~(1 << off); ++ pull_down &= ~(1 << off); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(pull_up, base + IPROC_GPIO_CCA_PULL_UP); ++ writel_relaxed(pull_down, base + IPROC_GPIO_CCA_PULL_DOWN); ++ } ++ ++ return 0; ++} ++ ++ ++iproc_gpio_pull_t iproc_gpio_getpull_updown_cca(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ ++ unsigned int base; ++ base = 0; ++ ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ unsigned long pull_up, pull_down; ++ ++ base = (unsigned int)chip->dmu_ioaddr; ++ ++ pull_up = readl_relaxed(base + IPROC_GPIO_CCA_PULL_UP); ++ pull_down = readl_relaxed(base + IPROC_GPIO_CCA_PULL_DOWN); ++ pull_up &= 1 << off; ++ pull_down &= 1 << off; ++ ++ if (pull_up ^ pull_down) { ++ if (pull_up) { ++ return IPROC_GPIO_PULL_UP; ++ } else { ++ return IPROC_GPIO_PULL_DOWN; ++ } ++ } else if(!pull_up) { ++ return IPROC_GPIO_PULL_NONE; ++ } ++ } ++ ++ return IPROC_GPIO_PULL_NONE; ++} ++struct iproc_gpio_cfg cca_gpio_cfg = { ++ .get_pull = iproc_gpio_getpull_updown_cca, ++ .set_pull = iproc_gpio_setpull_updown_cca, ++ .get_config = iproc_gpio_get_config_cca, ++ .set_config = iproc_gpio_set_config_cca, ++}; ++#endif ++#endif /* IPROC_GPIO_CCA */ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++int iproc_gpio_set_config_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ aux_sel_reg = IPROC_GPIO_CCB_AUX_SEL; ++ base = (unsigned int)chip->ioaddr; ++ pin = 1 << off; ++ } ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ switch (cfg) { ++ case IPROC_GPIO_GENERAL: ++ aux_sel &= ~(pin); ++ break; ++ case IPROC_GPIO_AUX_FUN: ++ aux_sel |= (pin); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(aux_sel, base + aux_sel_reg); ++ ++ return 0; ++} ++ ++ ++unsigned iproc_gpio_get_config_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ aux_sel_reg = IPROC_GPIO_CCB_AUX_SEL; ++ base = (unsigned int)chip->ioaddr; ++ pin = 1 << off; ++ } ++ ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ if (aux_sel & pin) { ++ return IPROC_GPIO_AUX_FUN; ++ } else { ++ return IPROC_GPIO_GENERAL; ++ } ++} ++ ++ ++int iproc_gpio_setpull_updown_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull) ++{ ++ unsigned int base; ++ base = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned long pad_res, res_en; ++ ++ base = (unsigned int)chip->ioaddr; ++ ++ pad_res = readl_relaxed(base + IPROC_GPIO_CCB_PAD_RES); ++ res_en = readl_relaxed(base + IPROC_GPIO_CCB_RES_EN); ++ switch (pull) { ++ case IPROC_GPIO_PULL_UP: ++ pad_res |= (1 << off); ++ res_en |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_DOWN: ++ pad_res &= ~(1 << off); ++ res_en |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_NONE: ++ res_en &= ~(1 << off); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(pad_res, base + IPROC_GPIO_CCB_PAD_RES); ++ writel_relaxed(res_en, base + IPROC_GPIO_CCB_RES_EN); ++ } ++ return 0; ++} ++ ++ ++iproc_gpio_pull_t iproc_gpio_getpull_updown_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ ++ unsigned int base; ++ base = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned long pad_res, res_en; ++ ++ base = (unsigned int)chip->ioaddr; ++ ++ pad_res = readl_relaxed(base + IPROC_GPIO_CCB_PAD_RES); ++ res_en = readl_relaxed(base + IPROC_GPIO_CCB_RES_EN); ++ pad_res &= 1 << off; ++ res_en &= 1 << off; ++ ++ if (res_en) { ++ if (pad_res) { ++ return IPROC_GPIO_PULL_UP; ++ } else { ++ return IPROC_GPIO_PULL_DOWN; ++ } ++ } else { ++ return IPROC_GPIO_PULL_NONE; ++ } ++ } ++ return IPROC_GPIO_PULL_NONE; ++} ++ ++struct iproc_gpio_cfg ccb_gpio_cfg = { ++ .get_pull = iproc_gpio_getpull_updown_ccb, ++ .set_pull = iproc_gpio_setpull_updown_ccb, ++ .get_config = iproc_gpio_get_config_ccb, ++ .set_config = iproc_gpio_set_config_ccb, ++}; ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG */ ++ ++iproc_gpio_pull_t iproc_gpio_getpull(unsigned int pin) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset, ret = -EINVAL; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->get_pull)(chip, offset); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(iproc_gpio_getpull); ++ ++ ++int iproc_gpio_setpull(unsigned int pin, iproc_gpio_pull_t pull) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset, ret = -EINVAL; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->set_pull)(chip, offset, pull); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(iproc_gpio_setpull); ++ ++unsigned iproc_gpio_getcfg(unsigned int pin) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset; ++ unsigned ret = 0; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->get_config)(chip, offset); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(iproc_gpio_getcfg); ++ ++int iproc_gpio_cfgpin(unsigned int pin, unsigned int config) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset; ++ int ret = 0; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ (chip->config->set_config)(chip, offset, config); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++ ++} ++EXPORT_SYMBOL(iproc_gpio_cfgpin); +diff --git a/drivers/bcmdrivers/gpio/gpio_cfg.h b/drivers/bcmdrivers/gpio/gpio_cfg.h +new file mode 100644 +index 0000000..126a7fb diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch new file mode 100644 index 00000000..ba3066b5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpio_cfg.h.patch @@ -0,0 +1,113 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio_cfg.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __PLAT_GPIO_CFG_H ++#define __PLAT_GPIO_CFG_H ++ ++typedef unsigned int __bitwise__ iproc_gpio_pull_t; ++typedef unsigned int __bitwise__ iproc_gpio_drvstr_t; ++ ++struct iproc_gpio_chip; ++ ++struct iproc_gpio_cfg { ++ iproc_gpio_pull_t (*get_pull)(struct iproc_gpio_chip *chip, unsigned int offs); ++ int (*set_pull)(struct iproc_gpio_chip *chip, unsigned int offs, ++ iproc_gpio_pull_t pull); ++ unsigned (*get_config)(struct iproc_gpio_chip *chip, unsigned int offs); ++ int (*set_config)(struct iproc_gpio_chip *chip, unsigned int offs, ++ unsigned int config); ++}; ++ ++ ++/** ++ * iproc_gpio_cfgpin() - Change the GPIO function of a pin. ++ * @pin pin The pin number to configure. ++ * @to to The configuration (IPROC_GPIO_GENERAL/ IPROC_GPIO_AUX_FUN) for the pin's function. ++ * ++ */ ++ ++extern int iproc_gpio_cfgpin(unsigned int pin, unsigned int to); ++ ++ ++/** ++ * iproc_gpio_getcfg - Read the current function for a GPIO pin ++ * @pin: The pin to read the configuration value for. ++ * ++ * Read the configuration state of the given @pin, returning a value that ++ * could be passed back to iproc_gpio_cfgpin(). ++ * ++ * ++ */ ++extern unsigned iproc_gpio_getcfg(unsigned int pin); ++ ++#define IPROC_GPIO_GENERAL 0 ++#define IPROC_GPIO_AUX_FUN 1 ++ ++ ++/* Define values for the pull-{up,down} available for each gpio pin. ++ * ++ * These values control the state of the weak pull-{up,down} resistors. ++ */ ++#define IPROC_GPIO_PULL_NONE ((__force iproc_gpio_pull_t)0x00) ++#define IPROC_GPIO_PULL_DOWN ((__force iproc_gpio_pull_t)0x01) ++#define IPROC_GPIO_PULL_UP ((__force iproc_gpio_pull_t)0x02) ++ ++ ++ ++ ++/** ++ * iproc_gpio_setpull() - set the state of a gpio pin pull resistor ++ * @pin: The pin number to configure the pull resistor. ++ * @pull: The configuration for the pull resistor. ++ * ++ * This function sets the state of the pull-{up,down} resistor for the ++ * specified pin. It will return 0 if successfull, or a negative error ++ * code if the pin cannot support the requested pull setting. ++ * ++ * @pull is one of IPROC_GPIO_PULL_NONE, IPROC_GPIO_PULL_DOWN or IPROC_GPIO_PULL_UP. ++*/ ++extern int iproc_gpio_setpull(unsigned int pin, iproc_gpio_pull_t pull); ++ ++ ++/** ++ * iproc_gpio_getpull() - get the pull resistor state of a gpio pin ++ * @pin: The pin number to get the settings for ++ * ++ * Read the pull resistor value for the specified pin. ++*/ ++extern iproc_gpio_pull_t iproc_gpio_getpull(unsigned int pin); ++ ++/* internal gpio functions */ ++extern int iproc_gpio_setpull_updown(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull); ++ ++extern iproc_gpio_pull_t iproc_gpio_getpull_updown(struct iproc_gpio_chip *chip, ++ unsigned int off); ++ ++extern int iproc_gpio_set_config(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg); ++ ++unsigned iproc_gpio_get_config(struct iproc_gpio_chip *chip, ++ unsigned int off); ++ ++#endif +diff --git a/drivers/bcmdrivers/gpio/gpiolib.c b/drivers/bcmdrivers/gpio/gpiolib.c +new file mode 100644 +index 0000000..6348974 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch new file mode 100644 index 00000000..1a8e21f5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_gpio_gpiolib.c.patch @@ -0,0 +1,265 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpiolib.c +@@ -0,0 +1,259 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "gpio.h" ++#include "gpio_cfg.h" ++ ++ ++#if defined(IPROC_GPIO_CCA) ++ ++extern struct iproc_gpio_irqcfg cca_gpio_irqcfg; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ ++extern struct iproc_gpio_cfg cca_gpio_cfg; ++ ++#endif /*CONFIG_MACH_NS || CONFIG_MACH_NSP */ ++ ++static struct resource iproc_gpio_cca_config_resource[] = { ++ [0] = { ++ .start = IPROC_CCA_BASE, ++ .end = IPROC_CCA_BASE + IPROC_GPIO_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "intr", ++ }, ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ [1] = { ++ .start = IPROC_DMU_BASE, ++ .end = IPROC_DMU_BASE + 0x200 - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "dmu", ++ }, ++#else ++ [1] = {.name = "",}, ++#endif ++}; ++ ++#endif /* IPROC_GPIO_CCA */ ++ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++ ++extern struct iproc_gpio_irqcfg ccb_gpio_irqcfg; ++extern struct iproc_gpio_cfg ccb_gpio_cfg; ++ ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG */ ++ ++ ++#if defined(IPROC_GPIO_CCG) ++static struct resource iproc_gpio_resources[] = { ++ [0] = { ++ .start = IPROC_GPIO_CCG_BASE, ++ .end = IPROC_GPIO_CCG_BASE + IPROC_GPIO_REG_SIZE -1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++#else ++static struct resource iproc_gpio_resources[] = { ++ [0] = { ++ .start = IPROC_GPIO_CCA_BASE, ++ .end = IPROC_GPIO_CCA_BASE + IPROC_GPIO_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ .child = iproc_gpio_cca_config_resource, ++ }, ++ [1] = { ++ .start = IPROC_GPIO_CCB_BASE, ++ .end = IPROC_GPIO_CCB_BASE + IPROC_GPIO_REG_SIZE -1, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++#endif ++ ++#if defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .config = &cca_gpio_cfg, ++ .chip = { ++ .base = 0, ++ .label = "GPIOA", ++ .ngpio = 24, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++/* CONFIG_MACH_NS */ ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++/* ++ * Chip level GPIO 0-3 from CMICD, ++ * GPIO 4-11 from ChipcommonA gpio pin 0 - 7 ++ * Hence the base is 4 and the number is 8. ++ */ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 4, ++ .label = "GPIOA", ++ .ngpio = 8, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#elif defined(CONFIG_MACH_HR2) ++/* ++ * Chip level GPIO 0-3 from CMICD, ++ * GPIO 4-15 are from ChipcommonA gpio pin 0 - 11 ++ * where GPIO 8-15 are shared with MII or LED depends on strap pin ++ * Hence the base is 4 and the number is 12. ++ */ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 4, ++ .label = "GPIOA", ++ .ngpio = 12, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#elif defined(CONFIG_MACH_GH) ++/* ++* Chip level GPIO 0-3 from CMICD, ++* GPIO 4-15 are from ChipcommonG gpio pin 4 - 15 ++*/ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCG_ID, ++ .config = &ccb_gpio_cfg, ++ .chip = { ++ .base = 4, ++ .label = "GPIOG", ++ .ngpio = 12, ++ }, ++ .irq_base = IPROC_GPIO_CCG_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCG_INT, ++ .irqcfg = &ccb_gpio_irqcfg, ++ .pin_offset = 4, ++ }, ++}; ++#else ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 0, ++ .label = "GPIOA", ++ .ngpio = 32, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++ [1] = { ++ .id = IPROC_GPIO_CCB_ID, ++ .chip = { ++ .base = -EINVAL, ++ .label = "GPIOB", ++ .ngpio = 4, ++ }, ++ .irq_base = IPROC_GPIO_CCB_IRQ_BASE, ++ .resource = &iproc_gpio_resources[1], ++ .irq = IPROC_GPIO_CCB_INT, ++ .irqcfg = &ccb_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#endif ++ ++int iproc_gpiolib_init(void) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpios_config; ++ int gpn; ++ int temp_base; ++ ++#if defined(CONFIG_MACH_NS) ++ /* bcm53012 support 24 gpios; bcm53010/53011 support 16 gpios */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) != 0x0) { ++ iproc_gpios_config[0].chip.ngpio = 16; ++ } ++#endif ++#if defined(CONFIG_MACH_NSP) ++ /* bcm53025 support 32 gpios; bcm53022/53023 support 24 gpios */ ++ reg32_write((volatile uint32_t *)(IPROC_PCIE_AXIB0_REG_VA + PAXB_0_CONFIG_IND_ADDR_BASE), 0); ++ ++/* ++ the mechanism to get the chip number does not work, always reads 22K. ++ OTP must be programmed and then need to look at OTP ++ for now assume 25K chip ++ ++ if ((__REG32(IPROC_PCIE_AXIB0_REG_VA + PAXB_0_CONFIG_IND_DATA_BASE) ++ & 0xffff0000) == 0x80250000) { ++*/ ++ if (1) { ++ iproc_gpios_config[0].chip.ngpio = 32; ++ } ++#endif ++ ++ ++ temp_base = 0; ++ for (gpn = 0; gpn < ARRAY_SIZE(iproc_gpios_config); gpn++, chip++) { ++ if (gpn >= MAX_NS_GPIO){ ++ printk("Unavailabe to add gpiolib\n"); ++ return -EINVAL; ++ } ++ ++ if (chip->chip.base == -EINVAL) { ++ chip->chip.base = temp_base; ++ } ++ ++ iproc_gpiolib_add(chip); ++ temp_base = chip->chip.base + chip->chip.ngpio; ++ } ++ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/include/Readme.txt b/drivers/bcmdrivers/include/Readme.txt +new file mode 100644 +index 0000000..41eb87c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch new file mode 100644 index 00000000..9b622fc5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_include_Readme.txt.patch @@ -0,0 +1,7 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/include/Readme.txt +@@ -0,0 +1 @@ ++Only shared api's or exported api's common files +diff --git a/drivers/bcmdrivers/mdio/.gitignore b/drivers/bcmdrivers/mdio/.gitignore +new file mode 100644 +index 0000000..c1e8a25 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch new file mode 100644 index 00000000..584088e1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_.gitignore.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_mdio.o.cmd ++/.iproc_mii.o.cmd ++/built-in.o ++/iproc_mdio.o ++/iproc_mii.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/mdio/Kconfig b/drivers/bcmdrivers/mdio/Kconfig +new file mode 100644 +index 0000000..3d54c81 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch new file mode 100644 index 00000000..28f46181 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Kconfig.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_MDIO ++ tristate "MDIO support" ++ depends on ARCH_IPROC ++ default n ++ help ++ MDIO support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/mdio/Makefile b/drivers/bcmdrivers/mdio/Makefile +new file mode 100644 +index 0000000..03746c7 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch new file mode 100644 index 00000000..0306d5be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_MDIO) += iproc_mii.o ++iproc_mii-objs := iproc_mdio.o +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio.c b/drivers/bcmdrivers/mdio/iproc_mdio.c +new file mode 100755 +index 0000000..5ecb92e diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch new file mode 100644 index 00000000..70a566e5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.c.patch @@ -0,0 +1,591 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio.c +@@ -0,0 +1,585 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include "iproc_mdio.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "iproc_mdio_dev.h" ++ ++static void * baseAddr; ++ ++#define R_REG(reg) ioread32(baseAddr + (reg&0x0fff)) ++#define W_REG(reg, val) iowrite32(val, baseAddr + (reg&0x0fff)) ++ ++#define MII_ERR_VAL 0x0001 ++#define MII_MSG_VAL 0x0002 ++#define MII_DBG_VAL 0x0004 ++//static u32 mii_msg_level = MII_ERR_VAL; ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) ++#define MII_ERR(args) do {if (mii_msg_level & MII_ERR_VAL) printk args;} while (0) ++#else ++#define MII_ERR(args) ++#endif ++ ++#ifdef BCMDBG ++#define MII_MSG(args) do {if (mii_msg_level & MII_MSG_VAL) printk args;} while (0) ++#define MII_DBG(args) do {if (mii_msg_level & MII_DBG_VAL) printk args;} while (0) ++#else ++#define MII_MSG(args) ++#define MII_DBG(args) ++#endif ++ ++#define MII_EN_CHK \ ++ {\ ++ if (!baseAddr) { \ ++ return MII_ERR_INIT; \ ++ } \ ++ if (!(R_REG(MII_MGMT) & 0x7f)) { \ ++ return MII_ERR_INTERNAL; \ ++ } \ ++ } ++ ++#define MII_TRIES 100000 ++#define MII_POLL_USEC 20 ++ ++struct mdio_device_data { ++ mdio_info_t *mdio; ++ int init; ++}; ++ ++static struct mdio_device_data mdio_devices={0}; ++ ++#define DRIVER_VERSION "0.01" ++#define DRIVER_NAME "iproc mdio" ++ ++static int mdio_major; ++static struct cdev mdio_cdev; ++ ++#define MDIO_IOC_OP_EXTERNAL_READ 0 ++#define MDIO_IOC_OP_EXTERNAL_WRITE 1 ++#define MDIO_IOC_OP_LOCAL_READ 2 ++#define MDIO_IOC_OP_LOCAL_WRITE 3 ++ ++/* Function : ccb_mii_read ++ * - Read operation. ++ * Return : ++ * Note : ++ */ ++int ++ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data) ++{ ++ int i; ++ uint32_t ctrl = 0; ++ unsigned long flags; ++ mdio_info_t *mdio = NULL; ++ ++ MII_EN_CHK; ++ ++ mdio = mdio_devices.mdio; ++ ++ spin_lock_irqsave(&mdio->lock, flags); ++ ++ ctrl = R_REG(MII_MGMT); ++ if (dev_type == MII_DEV_LOCAL) { ++ ctrl &= ~MII_MGMT_EXP_MASK; ++ } else { ++ ctrl |= MII_MGMT_EXP_MASK; ++ } ++ W_REG(MII_MGMT, ctrl); ++ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = ((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | ++ ((2 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | ++ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | ++ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | ++ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK); ++ W_REG(MII_CMD_DATA, ctrl); ++ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); ++ ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = R_REG(MII_CMD_DATA); ++ ++ MII_DBG(("MDIO READ: addr=%x off=%x value=%x\n", phy_addr, reg_off, ctrl)); ++ ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ ++ *data = (ctrl & 0xffff); ++ return 0; ++} ++ ++/* Function : ccb_mii_write ++ * - Write operation. ++ * Return : ++ * Note : ++ */ ++int ++ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data) ++{ ++ int i; ++ uint32_t ctrl = 0; ++ unsigned long flags; ++ mdio_info_t *mdio = NULL; ++ ++ MII_DBG(("MDIO WRITE: addr=%x off=%x\n", phy_addr, reg_off)); ++ ++ MII_EN_CHK; ++ ++ mdio = mdio_devices.mdio; ++ ++ spin_lock_irqsave(&mdio->lock, flags); ++ ++ ctrl = R_REG(MII_MGMT); ++ if (dev_type == MII_DEV_LOCAL) { ++ ctrl &= ~MII_MGMT_EXP_MASK; ++ } else { ++ ctrl |= MII_MGMT_EXP_MASK; ++ } ++ W_REG(MII_MGMT, ctrl); ++ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = ((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | ++ ((1 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | ++ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | ++ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | ++ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK) | ++ ((data << MII_CMD_DATA_DATA_SHIFT) & MII_CMD_DATA_DATA_MASK); ++ W_REG(MII_CMD_DATA, ctrl); ++ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); ++ ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ ++ return MII_ERR_NONE; ++} ++ ++/* Function : ccb_mii_freq_set ++ * - Set MII management interface frequency. ++ * Return : ++ * Note : ++ * ++ */ ++int ++ccb_mii_freq_set(int speed_khz) ++{ ++ int rv = MII_ERR_NONE; ++ uint32_t divider = 0; ++ uint32_t mgmt = 0; ++ ++ MII_DBG(("MDIO FREQ SET: %d KHz\n", speed_khz)); ++ ++ /* host clock 66MHz device value the MDCDIV field */ ++ /* resultant MDIO clock should not exceed 2.5MHz */ ++ ++ if (speed_khz > 2560) { ++ MII_ERR(("\n%s: Maximum MDIO frequency is 2.5MHz\n", __FUNCTION__)); ++ return MII_ERR_PARAM; ++ } ++ ++ divider = 67584 / speed_khz; ++ divider = (divider & MII_MGMT_MDCDIV_MASK); ++ if (divider > 0x7f) { ++ /* make sure the minimum configurable frequency */ ++ divider = 0x7f; ++ } ++ mgmt = R_REG(MII_MGMT); ++ mgmt &= ~MII_MGMT_MDCDIV_MASK; ++ mgmt |= divider; ++ ++ W_REG(MII_MGMT, mgmt); ++ MII_DBG(("MII FREQ(%d KHz): write(0x%x)=0x%x\n",speed_khz, MII_MGMT, mgmt)); ++ ++ return rv; ++} ++ ++static void __maybe_unused ++_dump_devs(void) ++{ ++// int r; ++// int addr, off; ++ int addr; ++ int phyid1, phyid2; ++ int cnt = 0; ++ int found = 0; ++ ++ for (addr = 0; addr <= 0x1f; addr++) { ++ ccb_mii_read(MII_DEV_LOCAL, addr, 2, (uint16_t *)&phyid1); ++ ccb_mii_read(MII_DEV_LOCAL, addr, 3, (uint16_t *)&phyid2); ++ found = 0; ++ if (phyid1 == 0xffff) { ++ continue; ++ } ++ ++ if ((phyid1) && (phyid2)) { ++ cnt ++; ++ found = 1; ++ } ++ if (cnt == 1) { ++ printk("Found LOCAL device(s) on MDC/MDIO interface:\n"); ++ } ++ if (found) { ++ printk("PHY address=%2d, IDs = 0x%4x 0x%4x\n", addr, phyid1, phyid2); ++ } ++ } ++ ++ cnt = 0; ++ found = 0; ++ for (addr = 0; addr <= 0x1f; addr++) { ++ ccb_mii_read(MII_DEV_EXT, addr, 2, (uint16_t *)&phyid1); ++ ccb_mii_read(MII_DEV_EXT, addr, 3, (uint16_t *)&phyid2); ++ found = 0; ++ if (phyid1 == 0xffff) { ++ continue; ++ } ++ ++ if ((phyid1) && (phyid2)) { ++ cnt ++; ++ found = 1; ++ } ++ if (cnt == 1) { ++ printk("Found EXTERNAL device(s) on MDC/MDIO interface:\n"); ++ } ++ if (found) { ++ printk("PHY address=%2d, IDs = 0x%4x 0x%4x\n", addr, phyid1, phyid2); ++ } ++ } ++} ++ ++static int ++mdio_open(struct inode *inode, struct file *filp) ++{ ++ filp->private_data = mdio_devices.mdio; ++ return 0; ++} ++ ++static int ++mdio_release(struct inode *inode, struct file *filp) ++{ ++ ++ return 0; ++} ++ ++static int mdio_message(mdio_info_t *mdio, ++ struct mdio_ioc_transfer *u_xfers, unsigned n_xfers, int op) ++{ ++ ++ uint8_t pa, ra; ++ uint16_t regval; ++ ++ pa = u_xfers->pa; ++ ra = u_xfers->ra; ++ ++ MII_DBG(("mdio_message: op = %d\n", op)); ++ ++ if(op == MDIO_IOC_OP_LOCAL_READ) { ++ ccb_mii_read(MII_DEV_LOCAL, pa, ra, ®val); ++ u_xfers->rx_buf = regval; ++ } ++ ++ if(op == MDIO_IOC_OP_LOCAL_WRITE) { ++ ccb_mii_write(MII_DEV_LOCAL, pa, ra, u_xfers->tx_buf); ++ } ++ ++ if(op == MDIO_IOC_OP_EXTERNAL_READ) { ++ ccb_mii_read(MII_DEV_EXT, pa, ra, ®val); ++ u_xfers->rx_buf = regval; ++ } ++ ++ if(op == MDIO_IOC_OP_EXTERNAL_WRITE) { ++ ccb_mii_write(MII_DEV_EXT, pa, ra, u_xfers->tx_buf); ++ } ++ return 0; ++} ++ ++static long ++mdio_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ int err = 0; ++ int retval = 0; ++ int ioc_op = 0; ++ uint32_t tmp; ++ unsigned n_ioc; ++ struct mdio_ioc_transfer *ioc, *uf; ++ mdio_info_t *mdio; ++ ++ MII_DBG(("mdio_ioctl: cmd = %d\n", cmd)); ++ ++ /* Check type and command number */ ++ if (_IOC_TYPE(cmd) != MDIO_IOC_MAGIC){ ++ return -ENOTTY; ++ } ++ ++ /* Check access direction once here; don't repeat below. ++ * IOC_DIR is from the user perspective, while access_ok is ++ * from the kernel perspective; so they look reversed. ++ */ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ err = !access_ok(VERIFY_WRITE, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) ++ err = !access_ok(VERIFY_READ, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err) ++ return -EFAULT; ++ ++ mdio = (mdio_info_t *)filp->private_data; ++ ++ switch (cmd) { ++ ++ case MDIO_IOC_EXTERNAL_R_REG: ++ ioc_op = MDIO_IOC_OP_EXTERNAL_READ; ++ break; ++ case MDIO_IOC_EXTERNAL_W_REG: ++ ioc_op = MDIO_IOC_OP_EXTERNAL_WRITE; ++ break; ++ case MDIO_IOC_LOCAL_R_REG: ++ ioc_op = MDIO_IOC_OP_LOCAL_READ; ++ break; ++ case MDIO_IOC_LOCAL_W_REG: ++ ioc_op = MDIO_IOC_OP_LOCAL_WRITE; ++ break; ++ } ++ ++ tmp = _IOC_SIZE(cmd); ++ if ((tmp % sizeof(struct mdio_ioc_transfer)) != 0) { ++ retval = -EINVAL; ++ return retval; ++ } ++ n_ioc = tmp / sizeof(struct mdio_ioc_transfer); ++ if (n_ioc == 0) ++ return 0; ++ ++ /* copy into scratch area */ ++ ioc = kmalloc(tmp, GFP_KERNEL); ++ if (!ioc) { ++ retval = -ENOMEM; ++ return retval; ++ } ++ if (__copy_from_user(ioc, (void __user *)arg, tmp)) { ++ kfree(ioc); ++ retval = -EFAULT; ++ return retval; ++ } ++ /* translate to mdio_message, execute */ ++ retval = mdio_message(mdio, ioc, n_ioc, ioc_op); ++ ++ if ((ioc_op == MDIO_IOC_OP_EXTERNAL_READ) || (ioc_op == MDIO_IOC_OP_LOCAL_READ)) { ++ ++ uf = (struct mdio_ioc_transfer *)arg; ++ if (__copy_to_user((u8 __user *)&uf->rx_buf, (uint8_t *)&ioc->rx_buf, 2)) { ++ kfree(ioc); ++ retval = -EFAULT; ++ return retval; ++ } ++ } ++ kfree(ioc); ++ ++ return 0; ++} ++ ++static const struct file_operations mdio_fops = { ++ .open = mdio_open, ++ .release = mdio_release, ++ .unlocked_ioctl = mdio_ioctl, ++ .owner = THIS_MODULE, ++}; ++ ++static int _mdio_handler_init(mdio_info_t **mdio) ++{ ++ *mdio = kmalloc(sizeof(mdio_info_t), GFP_KERNEL); ++ if (*mdio == NULL) { ++ MII_ERR(("mdio_init: out of memory\n")); ++ return -ENOMEM; ++ } ++ memset(*mdio, 0, sizeof(mdio_info_t)); ++ ++ /* Initialize lock */ ++ spin_lock_init(&(*mdio)->lock); ++ ++ ++ mdio_devices.mdio = *mdio; ++ mdio_devices.init = 1; ++ ++ return 0; ++} ++ ++/* Function : ccb_mii_init ++ * - Init Northstar CCB MII management interface. ++ * Return : ++ * Note : ++ * ++ */ ++int ++ccb_mii_init(void) ++{ ++ int ret = -ENODEV; ++ dev_t mdio_dev; ++ mdio_info_t *mdio=NULL; ++ ++ _mdio_handler_init(&mdio); ++ ++ /* Get register base address */ ++ baseAddr = ioremap(IPROC_CCB_MDIO_REG_BASE, 0x1000); ++ MII_DBG(("MDIO INIT: baseAddr %x\n",baseAddr)); ++ ++ /* Set preamble */ ++ W_REG(MII_MGMT, MII_MGMT_PRE_MASK); ++ /* Set the MII default clock 1MHz */ ++ ccb_mii_freq_set(1024); ++ ++// _dump_devs(); ++ ++ if(mdio_devices.init != 1) { ++ return -ENOMEM; ++ } ++ mdio = mdio_devices.mdio; ++ ++ if (mdio_major) { ++ mdio_dev = MKDEV(mdio_major, 0); ++ ret = register_chrdev_region(mdio_dev, ++ 1, "mdio"); ++ } else { ++ ret = alloc_chrdev_region(&mdio_dev, 0, ++ 1, "mdio"); ++ mdio_major = MAJOR(mdio_dev); ++ } ++ ++ if (ret) { ++ goto error; ++ } ++ cdev_init(&mdio_cdev, &mdio_fops); ++ ret = cdev_add(&mdio_cdev, mdio_dev, 1); ++ if (ret) { ++ printk(KERN_ERR "Fail to add mdio char dev!\n"); ++ goto error_region; ++ } ++ ++ return 0; ++ ++error_region: ++ unregister_chrdev_region(mdio_dev, 1); ++error: ++ kfree(mdio); ++ return ret; ++} ++ ++void ++ccb_mii_exit(void) ++{ ++ mdio_info_t *mdio=NULL; ++ ++ /* Get register base address */ ++ if (baseAddr) { ++ iounmap(baseAddr); ++ baseAddr = NULL; ++ } ++ ++ mdio = mdio_devices.mdio; ++ kfree(mdio); ++ ++ mdio_devices.mdio = NULL; ++ mdio_devices.init = 0; ++ unregister_chrdev_region(MKDEV(mdio_major, 0), 1); ++ ++} ++ ++module_init(ccb_mii_init); ++module_exit(ccb_mii_exit); ++ ++EXPORT_SYMBOL(ccb_mii_init); ++EXPORT_SYMBOL(ccb_mii_freq_set); ++EXPORT_SYMBOL(ccb_mii_read); ++EXPORT_SYMBOL(ccb_mii_write); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("BCM5301X MDIO Device Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio.h b/drivers/bcmdrivers/mdio/iproc_mdio.h +new file mode 100755 +index 0000000..2356ce6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch new file mode 100644 index 00000000..562b1c30 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio.h.patch @@ -0,0 +1,88 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _bcm5301x_ccb_mii_h_ ++#define _bcm5301x_ccb_mii_h_ ++ ++#include ++ ++typedef struct _mdio_info_s { ++ void *h; /* dev handle */ ++ spinlock_t lock; ++} mdio_info_t; ++ ++/* reutrn value for MII driver */ ++#define MII_ERR_NONE 0 ++#define MII_ERR_TIMEOUT -1 ++#define MII_ERR_INTERNAL -2 ++#define MII_ERR_PARAM -3 ++#define MII_ERR_UNAVAIL -4 ++#define MII_ERR_UNKNOW -5 ++#define MII_ERR_INIT -6 ++ ++/* device type */ ++#define MII_DEV_LOCAL 0 ++#define MII_DEV_EXT 1 ++ ++/* MII register definition */ ++#define MII_MGMT 0x18003000 ++#define MII_MGMT_BASE 0x000 ++#define MII_MGMT_DATAMASK 0x000007ff ++#define MII_CMD_DATA 0x18003004 ++#define MII_CMD_DATA_BASE 0x004 ++#define MII_CMD_DATA_DATAMASK 0xffffffff ++ ++/* fields in MII_MGMT */ ++#define MII_MGMT_BYP_MASK 0x00000400 ++#define MII_MGMT_BYP_SHIFT 10 ++#define MII_MGMT_EXP_MASK 0x00000200 ++#define MII_MGMT_EXP_SHIFT 9 ++#define MII_MGMT_BSY_MASK 0x00000100 ++#define MII_MGMT_BSY_SHIFT 8 ++#define MII_MGMT_PRE_MASK 0x00000080 ++#define MII_MGMT_PRE_SHIFT 7 ++#define MII_MGMT_MDCDIV_MASK 0x0000007f ++#define MII_MGMT_MDCDIV_SHIFT 0 ++/* fields in MII_CMD_DATA */ ++#define MII_CMD_DATA_SB_MASK 0xc0000000 ++#define MII_CMD_DATA_SB_SHIFT 30 ++#define MII_CMD_DATA_OP_MASK 0x30000000 ++#define MII_CMD_DATA_OP_SHIFT 28 ++#define MII_CMD_DATA_PA_MASK 0x0f800000 ++#define MII_CMD_DATA_PA_SHIFT 23 ++#define MII_CMD_DATA_RA_MASK 0x007c0000 ++#define MII_CMD_DATA_RA_SHIFT 18 ++#define MII_CMD_DATA_TA_MASK 0x00030000 ++#define MII_CMD_DATA_TA_SHIFT 16 ++#define MII_CMD_DATA_DATA_MASK 0x0000ffff ++#define MII_CMD_DATA_DATA_SHIFT 0 ++ ++ ++/* external functions for SPI driver */ ++extern int ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data); ++extern int ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data); ++ ++extern int ccb_mii_freq_set(int speed_khz); ++extern int ccb_mii_init(void); ++ ++#endif /* _bcm5301x_ccb_mii_h_ */ +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio_dev.h b/drivers/bcmdrivers/mdio/iproc_mdio_dev.h +new file mode 100755 +index 0000000..fcf080a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch new file mode 100644 index 00000000..a0397644 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch @@ -0,0 +1,50 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio_dev.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _IPROC_MDIO_DEV_H ++#define _IPROC_MDIO_DEV_H ++ ++/* IOCTL commands */ ++ ++#define MDIO_IOC_MAGIC 'm' ++ ++struct mdio_ioc_transfer { ++ uint8_t pa; /* phy address */ ++ uint8_t ra; /* register address */ ++ uint16_t tx_buf; ++ uint16_t rx_buf; ++}; ++ ++#define MDIO_MSGSIZE(N) \ ++ ((((N)*(sizeof (struct mdio_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ ++ ? ((N)*(sizeof (struct mdio_ioc_transfer))) : 0) ++ ++#define MDIO_IOC_MESSAGE(N) _IOW(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(N)]) ++ ++#define MDIO_IOC_EXTERNAL_R_REG _IOWR(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_EXTERNAL_W_REG _IOW(MDIO_IOC_MAGIC, 1, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_LOCAL_R_REG _IOWR(MDIO_IOC_MAGIC, 2, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_LOCAL_W_REG _IOW(MDIO_IOC_MAGIC, 3, char[MDIO_MSGSIZE(1)]) ++ ++ ++#endif +diff --git a/drivers/bcmdrivers/nand/.gitignore b/drivers/bcmdrivers/nand/.gitignore +new file mode 100644 +index 0000000..26ea8be diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch new file mode 100644 index 00000000..04230fa1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_.gitignore.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/nand/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order ++/.iproc_mtd_nand.o.cmd ++/.nand_iproc.o.cmd ++/iproc_mtd_nand.o ++/nand_iproc.o +diff --git a/drivers/bcmdrivers/nand/Kconfig b/drivers/bcmdrivers/nand/Kconfig +new file mode 100644 +index 0000000..1cd1050 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch new file mode 100644 index 00000000..00293770 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Kconfig.patch @@ -0,0 +1,30 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/nand/Kconfig +@@ -0,0 +1,24 @@ ++menuconfig IPROC_MTD_NAND ++ tristate "NAND support" ++ depends on ARCH_IPROC ++ select MTD ++ select MTD_NAND ++ default n ++ help ++ This selects a driver for the iProc NAND Controller. ++ ++ If unsure, say N. ++ ++if IPROC_MTD_NAND ++ ++config IPROC_MTD_NAND_USE_JFFS2 ++ bool "Use JFFS2 on NAND" ++ default n ++ help ++ Enable this if JFFS2 will be used on NAND. This is to solve compatibility ++ issue for the NAND controller to work with JFFS2 (with some performance ++ degrade). ++ ++ If unsure, say N. ++ ++endif # IPROC_MTD_NAND +diff --git a/drivers/bcmdrivers/nand/Makefile b/drivers/bcmdrivers/nand/Makefile +new file mode 100644 +index 0000000..5d2b01d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch new file mode 100644 index 00000000..f3def015 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_Makefile.patch @@ -0,0 +1,8 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/nand/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_IPROC_MTD_NAND) += iproc_mtd_nand.o ++iproc_mtd_nand-objs := nand_iproc.o +diff --git a/drivers/bcmdrivers/nand/nand_iproc.c b/drivers/bcmdrivers/nand/nand_iproc.c +new file mode 100644 +index 0000000..f4b5d90 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch new file mode 100644 index 00000000..d59b9a7b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_nand_nand_iproc.c.patch @@ -0,0 +1,1739 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/nand/nand_iproc.c +@@ -0,0 +1,1733 @@ ++ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../../mtd/mtdcore.h" ++ ++/* ++ * Current version of NAND controller includes spare area for ECC calculation. ++ * This is not what some file system (eg. JFFS2) expects because they could ++ * write OOB first and data later. Thus we need to do some special handling. ++ */ ++#ifdef CONFIG_IPROC_MTD_NAND_USE_JFFS2 ++#define NAND_MTD_WRITE_OOB_SEPARATELY ++#endif /* CONFIG_IPROC_MTD_NAND_USE_JFFS2 */ ++#define NAND_REPORT_ECC_UNCORR_ERRORS ++ ++/* ++ * This flag controls if WP stays on between erase/write ++ * commands to mitigate flash corruption due to power glitches. Values: ++ * 0: NAND_WP is not used or not available ++ * 1: NAND_WP is set by default, cleared for erase/write operations ++ * 2: NAND_WP is always cleared ++ */ ++static int wp_on = 1; ++module_param(wp_on, int, 0444); ++ ++/*********************************************************************** ++ * Definitions ++ ***********************************************************************/ ++ ++#ifdef IPROC_NAND_DEBUG ++#define DBG(args...) printk(args) ++#else ++#define DBG(args...) do { } while(0) ++#endif ++ ++/* ++ * Controller/driver specific ++ */ ++#define DRV_NAME "nand_iproc" ++#define MAX_CONTROLLER_OOB 64 ++ ++/* ++ * NAND flash commands ++ */ ++#define CMD_PAGE_READ 0x01 ++#define CMD_SPARE_AREA_READ 0x02 ++#define CMD_STATUS_READ 0x03 ++#define CMD_PROGRAM_PAGE 0x04 ++#define CMD_PROGRAM_SPARE_AREA 0x05 ++#define CMD_COPY_BACK 0x06 ++#define CMD_DEVICE_ID_READ 0x07 ++#define CMD_BLOCK_ERASE 0x08 ++#define CMD_FLASH_RESET 0x09 ++#define CMD_BLOCKS_LOCK 0x0a ++#define CMD_BLOCKS_LOCK_DOWN 0x0b ++#define CMD_BLOCKS_UNLOCK 0x0c ++#define CMD_READ_BLOCKS_LOCK_STATUS 0x0d ++#define CMD_PARAMETER_READ 0x0e ++#define CMD_PARAMETER_CHANGE_COL 0x0f ++#define CMD_LOW_LEVEL_OP 0x10 ++ ++/* ++ * NAND controller register offset ++ */ ++#define NCREG_REVISION 0x000 /* Revision */ ++#define NCREG_CMD_START 0x004 /* Flash Command Start */ ++#define NCREG_CMD_EXT_ADDRESS 0x008 /* Flash Command Extended Address */ ++#define NCREG_CMD_ADDRESS 0x00c /* Flash Command Address */ ++#define NCREG_CMD_END_ADDRESS 0x010 /* Flash Command End Address */ ++#define NCREG_INTFC_STATUS 0x014 /* Flash Interface Status */ ++#define NCREG_CS_NAND_SELECT 0x018 /* Flash EBI CS Select */ ++#define NCREG_CS_NAND_XOR 0x01c /* Flash EBI CS Address XOR with 1FC0 Control */ ++#define NCREG_LL_OP 0x020 /* Flash Low Level Operation */ ++#define NCREG_MPLANE_BASE_EXT_ADDRESS 0x024 /* Flash Multiplane base address */ ++#define NCREG_MPLANE_BASE_ADDRESS 0x028 /* Flash Multiplane base address */ ++#define NCREG_ACC_CONTROL_CS0 0x050 /* Flash Access Control */ ++#define NCREG_CONFIG_CS0 0x054 /* Flash Config */ ++#define NCREG_TIMING_1_CS0 0x058 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS0 0x05c /* Flash Timing Parameters 2 */ ++#define NCREG_ACC_CONTROL_CS1 0x060 /* Flash Access Control */ ++#define NCREG_CONFIG_CS1 0x064 /* Flash Config */ ++#define NCREG_TIMING_1_CS1 0x068 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS1 0x06c /* Flash Timing Parameters 2 */ ++#define NCREG_ACC_CONTROL_CS2 0x070 /* Flash Access Control */ ++#define NCREG_CONFIG_CS2 0x074 /* Flash Config */ ++#define NCREG_TIMING_1_CS2 0x078 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS2 0x07c /* Flash Timing Parameters 2 */ ++#define NCREG_CORR_STAT_THRESHOLD 0x0c0 /* Correctable Error Reporting Threshold */ ++#define NCREG_BLK_WR_PROTECT 0x0c8 /* Block Write Protect Enable and Size for EBI_CS0b */ ++#define NCREG_MULTIPLANE_OPCODES_1 0x0cc /* Flash Multiplane Customerized Opcodes */ ++#define NCREG_MULTIPLANE_OPCODES_2 0x0d0 /* Flash Multiplane Customerized Opcodes */ ++#define NCREG_MULTIPLANE_CTRL 0x0d4 /* Flash Multiplane Control */ ++#define NCREG_UNCORR_ERROR_COUNT 0x0fc /* Read Uncorrectable Event Count */ ++#define NCREG_CORR_ERROR_COUNT 0x100 /* Read Error Count */ ++#define NCREG_READ_ERROR_COUNT 0x104 /* Read Error Count */ ++#define NCREG_BLOCK_LOCK_STATUS 0x108 /* Flash Block Lock Status */ ++#define NCREG_ECC_CORR_EXT_ADDR 0x10c /* ECC Correctable Error Extended Address */ ++#define NCREG_ECC_CORR_ADDR 0x110 /* ECC Correctable Error Address */ ++#define NCREG_ECC_UNC_EXT_ADDR 0x114 /* ECC Uncorrectable Error Extended Address */ ++#define NCREG_ECC_UNC_ADDR 0x118 /* ECC Uncorrectable Error Address */ ++#define NCREG_FLASH_READ_EXT_ADDR 0x11c /* Flash Read Data Extended Address */ ++#define NCREG_FLASH_READ_ADDR 0x120 /* Flash Read Data Address */ ++#define NCREG_PROGRAM_PAGE_EXT_ADDR 0x124 /* Page Program Extended Address */ ++#define NCREG_PROGRAM_PAGE_ADDR 0x128 /* Page Program Address */ ++#define NCREG_COPY_BACK_EXT_ADDR 0x12c /* Copy Back Extended Address */ ++#define NCREG_COPY_BACK_ADDR 0x130 /* Copy Back Address */ ++#define NCREG_BLOCK_ERASE_EXT_ADDR 0x134 /* Block Erase Extended Address */ ++#define NCREG_BLOCK_ERASE_ADDR 0x138 /* Block Erase Address */ ++#define NCREG_INV_READ_EXT_ADDR 0x13c /* Flash Invalid Data Extended Address */ ++#define NCREG_INV_READ_ADDR 0x140 /* Flash Invalid Data Address */ ++#define NCREG_INIT_STATUS 0x144 /* Initialization status */ ++#define NCREG_ONFI_STATUS 0x148 /* ONFI Status */ ++#define NCREG_ONFI_DEBUG_DATA 0x14c /* ONFI Debug Data */ ++#define NCREG_SEMAPHORE 0x150 /* Semaphore */ ++#define NCREG_FLASH_DEVICE_ID 0x194 /* Flash Device ID */ ++#define NCREG_FLASH_DEVICE_ID_EXT 0x198 /* Flash Extended Device ID */ ++#define NCREG_LL_RDDATA 0x19c /* Flash Low Level Read Data */ ++#define NCREG_SPARE_AREA_READ_OFS_0 0x200 /* Flash Spare Area Read Bytes */ ++#define NCREG_SPARE_AREA_WRITE_OFS_0 0x280 /* Flash Spare Area Write Bytes */ ++#define NCREG_FLASH_CACHE_BASE 0x400 /* Flash Cache Buffer Access */ ++ ++/* ++ * Required NAND controller register fields ++ */ ++#define NCFLD_CMD_START_OPCODE_SHIFT 24 ++#define NCFLD_INTFC_STATUS_FLASH_STATUS_MASK 0x000000FF ++#define NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG 0x40000000 ++#define NCFLD_CS_NAND_SELECT_WP 0x20000000 ++#define NCFLD_CS_NAND_SELECT_DIRECT_ACCESS_CS_MASK 0x000000FF ++#define NCFLD_CS_NAND_XOR_CS_MASK 0x000000FF ++#define NCFLD_CONFIG_CS0_BLOCK_SIZE_MASK 0x70000000 ++#define NCFLD_CONFIG_CS0_BLOCK_SIZE_SHIFT 28 ++#define NCFLD_CONFIG_CS0_DEVICE_SIZE_MASK 0x0f000000 ++#define NCFLD_CONFIG_CS0_DEVICE_SIZE_SHIFT 24 ++#define NCFLD_CONFIG_CS0_DEVICE_WIDTH_MASK 0x00800000 ++#define NCFLD_CONFIG_CS0_DEVICE_WIDTH_SHIFT 23 ++#define NCFLD_CONFIG_CS0_PAGE_SIZE_MASK 0x00300000 ++#define NCFLD_CONFIG_CS0_PAGE_SIZE_SHIFT 20 ++#define NCFLD_CONFIG_CS0_FUL_ADR_BYTES_MASK 0x00070000 ++#define NCFLD_CONFIG_CS0_FUL_ADR_BYTES_SHIFT 16 ++#define NCFLD_CONFIG_CS0_COL_ADR_BYTES_MASK 0x00007000 ++#define NCFLD_CONFIG_CS0_COL_ADR_BYTES_SHIFT 12 ++#define NCFLD_CONFIG_CS0_BLK_ADR_BYTES_MASK 0x00000700 ++#define NCFLD_CONFIG_CS0_BLK_ADR_BYTES_SHIFT 8 ++#define NCFLD_ACC_CONTROL_CS0_RD_ECC_EN_MASK 0x80000000 ++#define NCFLD_ACC_CONTROL_CS0_RD_ECC_EN_SHIFT 31 ++#define NCFLD_ACC_CONTROL_CS0_WR_ECC_EN_MASK 0x40000000 ++#define NCFLD_ACC_CONTROL_CS0_WR_ECC_EN_SHIFT 30 ++#define NCFLD_ACC_CONTROL_CS0_FAST_PGM_RDIN_MASK 0x10000000 ++#define NCFLD_ACC_CONTROL_CS0_FAST_PGM_RDIN_SHIFT 28 ++#define NCFLD_ACC_CONTROL_CS0_RD_ERASED_ECC_EN_MASK 0x08000000 ++#define NCFLD_ACC_CONTROL_CS0_RD_ERASED_ECC_EN_SHIFT 27 ++#define NCFLD_ACC_CONTROL_CS0_PARTIAL_PAGE_EN_MASK 0x04000000 ++#define NCFLD_ACC_CONTROL_CS0_PARTIAL_PAGE_EN_SHIFT 26 ++#define NCFLD_ACC_CONTROL_CS0_PAGE_HIT_EN_MASK 0x01000000 ++#define NCFLD_ACC_CONTROL_CS0_PAGE_HIT_EN_SHIFT 24 ++#define NCFLD_ACC_CONTROL_CS0_ECC_LEVEL_MASK 0x001f0000 ++#define NCFLD_ACC_CONTROL_CS0_ECC_LEVEL_SHIFT 16 ++#define NCFLD_ACC_CONTROL_CS0_SECTOR_SIZE_1K_MASK 0x00000080 ++#define NCFLD_ACC_CONTROL_CS0_SECTOR_SIZE_1K_SHIFT 7 ++#define NCFLD_ACC_CONTROL_CS0_SPARE_AREA_SIZE_MASK 0x0000007f ++#define NCFLD_ACC_CONTROL_CS0_SPARE_AREA_SIZE_SHIFT 0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS0_MASK 0x0000003f ++#define NCFLD_CORR_STAT_THRESHOLD_CS0_SHIFT 0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS1_MASK 0x00000fc0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS1_SHIFT 6 ++ ++/* ++ * IDM register base (for interrupts) ++ */ ++#define IDMREG_NAND_IO_CONTROL_DIRECT 0x00000000 ++ ++/* ++ * Required IDM NAND IO Control register fields ++ */ ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_AXI_BE_MODE (1UL << 28) ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE (1UL << 24) ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT 2 ++ ++/* ++ * Interrupts ++ */ ++#define NCINTR_NP_READ 0 ++#define NCINTR_BLKERA 1 ++#define NCINTR_CPYBK 2 ++#define NCINTR_PGMPG 3 ++#define NCINTR_CTLRDY 4 ++#define NCINTR_RBPIN 5 ++#define NCINTR_UNC 6 ++#define NCINTR_CORR 7 ++ ++/* 512B flash cache in the NAND controller HW */ ++#define FC_SHIFT 9U ++#define FC_BYTES 512U ++#define FC_WORDS (FC_BYTES >> 2) ++#define FC(x) (NCREG_FLASH_CACHE_BASE + ((x) << 2)) ++ ++/* ++ * Register access macros - generic ++ */ ++#define REG_RD(ptr) readl(ptr) ++#define REG_WR(ptr, val) writel(val, ptr) ++ ++/* ++ * Register access macros - NAND flash controller ++ */ ++#define NAND_REG_RD(x) REG_RD(ctrl.nand_regs + (x)) ++#define NAND_REG_WR(x, y) \ ++ do { REG_WR(ctrl.nand_regs + (x), (y)); } while(0) ++#define NAND_REG_UNSET(x, y) \ ++ do { NAND_REG_WR((x), NAND_REG_RD(x) & ~(y)); } while(0) ++#define NAND_REG_SET(x, y) \ ++ do { NAND_REG_WR((x), NAND_REG_RD(x) | (y)); } while(0) ++#define NAND_REG_WR_RB(x, y) \ ++ do { NAND_REG_WR((x), (y)); NAND_REG_RD(x); } while(0) ++#define NAND_REG_SET_RB(x, y) \ ++ do { NAND_REG_SET((x), (y)); NAND_REG_RD(x); } while(0) ++#define NAND_REG_UNSET_RB(x, y) \ ++ do { NAND_REG_UNSET((x), (y)); NAND_REG_RD(x); } while(0) ++ ++/* ++ * IRQ operations ++ */ ++ ++#define NAND_ENABLE_IRQ(bit) do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) | \ ++ (1UL << ((bit) + IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT)) \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_DISABLE_IRQ(bit) do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) & \ ++ ~(1UL << ((bit) + IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT)) \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_ACK_IRQ(bit) do { \ ++ REG_WR(((u32 *)ctrl.nand_intr_regs) + (bit), 1); \ ++ REG_RD(((u32 *)ctrl.nand_intr_regs) + (bit)); \ ++} while(0) ++ ++#define NAND_TEST_IRQ(bit) (REG_RD(((u32 *)ctrl.nand_intr_regs) + (bit)) & 1) ++ ++/* ++ * Data access macros for endianness ++ */ ++#ifdef __LITTLE_ENDIAN ++#define NAND_BEGIN_DATA_ACCESS() do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) | \ ++ IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_END_DATA_ACCESS() do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) & \ ++ ~IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++#else /* !__LITTLE_ENDIAN */ ++#define NAND_BEGIN_DATA_ACCESS() do { } while (0) ++#define NAND_END_DATA_ACCESS() do { } while (0) ++#endif /* !__LITTLE_ENDIAN */ ++ ++/* ++ * Misc NAND controller configuration/status macros ++ */ ++ ++#define NC_REG_CONFIG(cs) (NCREG_CONFIG_CS0 + ((cs) << 4)) ++ ++#define WR_CONFIG(cs, field, val) do { \ ++ u32 reg = NC_REG_CONFIG(cs), contents = NAND_REG_RD(reg); \ ++ contents &= ~(NCFLD_CONFIG_CS0_##field##_MASK); \ ++ contents |= (val) << NCFLD_CONFIG_CS0_##field##_SHIFT; \ ++ NAND_REG_WR(reg, contents); \ ++} while(0) ++ ++#define RD_CONFIG(cs, field) \ ++ ((NAND_REG_RD(NC_REG_CONFIG(cs)) & NCFLD_CONFIG_CS0_##field##_MASK) \ ++ >> NCFLD_CONFIG_CS0_##field##_SHIFT) ++ ++#define NC_REG_ACC_CONTROL(cs) (NCREG_ACC_CONTROL_CS0 + ((cs) << 4)) ++ ++#define WR_ACC_CONTROL(cs, field, val) do { \ ++ u32 reg = NC_REG_ACC_CONTROL(cs), contents = NAND_REG_RD(reg); \ ++ contents &= ~(NCFLD_ACC_CONTROL_CS0_##field##_MASK); \ ++ contents |= (val) << NCFLD_ACC_CONTROL_CS0_##field##_SHIFT; \ ++ NAND_REG_WR(reg, contents); \ ++} while(0) ++ ++#define RD_ACC_CONTROL(cs, field) \ ++ ((NAND_REG_RD(NC_REG_ACC_CONTROL(cs)) & \ ++ NCFLD_ACC_CONTROL_CS0_##field##_MASK) \ ++ >> NCFLD_ACC_CONTROL_CS0_##field##_SHIFT) ++ ++#define CORR_ERROR_COUNT (NAND_REG_RD(NCREG_CORR_ERROR_COUNT)) ++#define UNCORR_ERROR_COUNT (NAND_REG_RD(NCREG_UNCORR_ERROR_COUNT)) ++ ++#define WR_CORR_THRESH(cs, val) do { \ ++ u32 contents = NAND_REG_RD(NCREG_CORR_STAT_THRESHOLD); \ ++ u32 shift = NCFLD_CORR_STAT_THRESHOLD_CS1_SHIFT * (cs); \ ++ contents &= ~(NCFLD_CORR_STAT_THRESHOLD_CS0_MASK << shift); \ ++ contents |= ((val) & NCFLD_CORR_STAT_THRESHOLD_CS0_MASK) << shift; \ ++ NAND_REG_WR(NCREG_CORR_STAT_THRESHOLD, contents); \ ++} while(0) ++ ++/* ++ * Internal structures ++ */ ++struct iproc_nand_controller { ++ struct nand_hw_control controller; ++ int irq; ++ int cmd_pending; ++ struct completion done; ++ int boot_inited; ++ ++ volatile void *nand_regs; ++ volatile void *nand_intr_regs; ++ volatile void *idm_nand_regs; ++}; ++ ++struct iproc_nand_cfg { ++ u64 device_size; ++ unsigned int block_size; ++ unsigned int page_size; ++ unsigned int spare_area_size; ++ unsigned int device_width; ++ unsigned int col_adr_bytes; ++ unsigned int blk_adr_bytes; ++ unsigned int ful_adr_bytes; ++ unsigned int sector_size_1k; ++}; ++ ++struct iproc_nand_host { ++ u32 buf[FC_WORDS]; ++ struct nand_chip chip; ++ struct mtd_info mtd; ++ struct platform_device *pdev; ++ int cs; ++ unsigned int last_cmd; ++ unsigned int last_byte; ++ u64 last_addr; ++ struct iproc_nand_cfg hwcfg; ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ u16 eccpos; ++ u16 eccbytes; ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++}; ++ ++static struct nand_ecclayout iproc_nand_oob_layout; ++ ++struct iproc_nand_exception { ++ const char *name; ++ int id[7]; ++ int idlen; /* usable */ ++ unsigned int chipsize; /* MB */ ++ unsigned int writesize; /* B */ ++ unsigned int erasesize; /* B */ ++ unsigned int oobsize; /* B per page */ ++ int chipoptions; ++ int badblockpos; ++}; ++ ++/* ++ * Global variables ++ */ ++ ++static struct iproc_nand_controller ctrl; ++ ++static struct iproc_nand_exception iproc_exceptions_list[] = { ++ {"Micron MT29F8G08ABACA", ++ {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00}, ++ 5, 0x00400, 4096, 0x040000, 224}, ++ {"Micron MT29F16G08ABABA", ++ {0x2C, 0x48, 0x00, 0x26, 0x89, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x080000, 224}, ++ {"Micron MT29F16G08CBABA", ++ {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x100000, 224}, ++ {"Micron MT29F16G08CBACA", ++ {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x100000, 224}, ++ {"Micron MT29F16G08MAA", ++ {0x2C, 0xD5, 0x94, 0x3E, 0x74, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x080000, 218}, ++ {"Micron MT29F32G08CBACA", ++ {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00}, ++ 5, 0x01000, 4096, 0x100000, 224}, ++ {"Micron MT29F64G08CBAAA", ++ {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00}, ++ 5, 0x02000, 8192, 0x200000, 448}, ++ {"Micron MT29F256G08CJAAA", ++ {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00}, ++ 5, 0x08000, 8192, 0x200000, 448}, ++ {NULL,} ++}; ++ ++/* Used for running nand_scan_ident without the built-in heuristics */ ++static struct nand_flash_dev iproc_empty_flash_table[] = { ++ {NULL,} ++}; ++ ++/* ECC bytes required per 512B */ ++static const uint8_t nand_iproc_ecc_levels[2] = { 18, 21 }; ++static const uint8_t nand_iproc_ecc_bytes[] = { ++ 0, 2, 4, 6, 7, 9, 11, 13, 14, 16, 18, 20, 21, 23, 25, ++ 27, /* or 3 if SPARE_AREA_SIZE == 16 && SECTOR_SIZE_1K == 0*/ ++ 28, 30, 32, 34, 35 ++}; ++ ++/* Strap settings */ ++struct nand_strap_type_t { ++ uint8_t sector_1k; ++ uint8_t ecclevel; ++ uint16_t spare_size; ++}; ++static const struct nand_strap_type_t nand_strap_types[] = { ++ { 0, 0, 16 }, ++ { 0, 15, 16 }, ++ { 0, 4, 16 }, ++ { 0, 8, 16 }, ++ { 0, 8, 27 }, ++ { 0, 12, 27 }, ++ { 1, 12, 27 }, ++ { 1, 15, 27 }, ++ { 1, 20, 45 }, ++}; ++static const uint32_t nand_strap_page_sizes[] = { 2048, 2048, 4096, 8192 }; ++ ++/*********************************************************************** ++ * Internal support functions ++ ***********************************************************************/ ++ ++static void ++iproc_nand_wp(struct mtd_info *mtd, int wp) ++{ ++ if (wp_on == 1) { ++ static int old_wp = -1; ++ if (old_wp != wp) { ++ DBG("%s: WP %s\n", __func__, wp ? "on" : "off"); ++ old_wp = wp; ++ } ++ if (wp) { ++ NAND_REG_SET_RB(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } else { ++ NAND_REG_UNSET_RB(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } ++ } ++} ++ ++/* Helper functions for reading and writing OOB registers */ ++static inline unsigned char ++oob_reg_read(int offs) ++{ ++ if (offs >= MAX_CONTROLLER_OOB) ++ return 0x77; ++ ++ return NAND_REG_RD(NCREG_SPARE_AREA_READ_OFS_0 + (offs & ~0x03)) ++ >> (24 - ((offs & 0x03) << 3)); ++} ++ ++static inline void ++oob_reg_write(int offs, unsigned long data) ++{ ++ if (offs >= MAX_CONTROLLER_OOB) ++ return; ++ ++ NAND_REG_WR(NCREG_SPARE_AREA_WRITE_OFS_0 + (offs & ~0x03), ++ data); ++} ++ ++/* ++ * read_oob_from_regs - read data from OOB registers ++ * @i: sub-page sector index ++ * @oob: buffer to read to ++ * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) ++ * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal ++ */ ++static int ++read_oob_from_regs(int i, u8 *oob, int sas, int sector_1k) ++{ ++ int tbytes = sas << sector_1k; ++ int j; ++ ++ /* Adjust OOB values for 1K sector size */ ++ if (sector_1k && (i & 0x01)) ++ tbytes = max(0, tbytes - MAX_CONTROLLER_OOB); ++ tbytes = min(tbytes, MAX_CONTROLLER_OOB); ++ ++ for (j = 0; j < tbytes; j++) ++ oob[j] = oob_reg_read(j); ++ return tbytes; ++} ++ ++/* ++ * write_oob_to_regs - write data to OOB registers ++ * @i: sub-page sector index ++ * @oob: buffer to write from ++ * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) ++ * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal ++ */ ++static int ++write_oob_to_regs(int i, const u8 *oob, int sas, int sector_1k) ++{ ++ int tbytes = sas << sector_1k; ++ int j; ++ ++ /* Adjust OOB values for 1K sector size */ ++ if (sector_1k && (i & 0x01)) ++ tbytes = max(0, tbytes - MAX_CONTROLLER_OOB); ++ tbytes = min(tbytes, MAX_CONTROLLER_OOB); ++ ++ for (j = 0; j < tbytes; j += 4) ++ oob_reg_write(j, ++ (oob[j + 0] << 24) | ++ (oob[j + 1] << 16) | ++ (oob[j + 2] << 8) | ++ (oob[j + 3] << 0)); ++ return tbytes; ++} ++ ++static irqreturn_t ++iproc_nand_irq(int irq, void *data) ++{ ++ if (NAND_TEST_IRQ(NCINTR_CTLRDY)) { ++ NAND_ACK_IRQ(NCINTR_CTLRDY); ++ if (ctrl.cmd_pending) { ++ /* ++ * If the direct access region (eg. 0x1c000000 on NS) is accessed, ++ * IRQ handler will also be called with NCINTR_CTLRDY asserted. ++ * Thus we need to filter these events by ctrl.cmd_pending, or ++ * ctrl.done will be mistakenly set and cause incorrect result for ++ * the following command. ++ * We actually should avoid direct access to the mapped region when ++ * NAND driver is running. ++ */ ++ complete(&ctrl.done); ++ } ++ return IRQ_HANDLED; ++ } ++ return IRQ_NONE; ++} ++ ++static void ++iproc_nand_send_cmd(int cmd) ++{ ++ DBG("%s: native cmd %d addr_lo 0x%lx\n", __func__, cmd,(unsigned long)NAND_REG_RD(NCREG_CMD_ADDRESS)); ++ BUG_ON(ctrl.cmd_pending != 0); ++ ctrl.cmd_pending = cmd; ++ mb(); ++ NAND_REG_WR(NCREG_CMD_START, cmd << NCFLD_CMD_START_OPCODE_SHIFT); ++} ++ ++/*********************************************************************** ++ * NAND MTD API: read/program/erase ++ ***********************************************************************/ ++ ++static void ++iproc_nand_cmd_ctrl(struct mtd_info *mtd, int dat, ++ unsigned int ctrl) ++{ ++ /* intentionally left blank */ ++} ++ ++static int ++iproc_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ ++ DBG("%s: native cmd %d\n", __func__, ctrl.cmd_pending); ++ if (ctrl.cmd_pending && ++ wait_for_completion_timeout(&ctrl.done, HZ / 10) <= 0) { ++ dev_err(&host->pdev->dev, ++ "timeout waiting for command %u (%ld)\n", ++ host->last_cmd, (unsigned long)NAND_REG_RD(NCREG_CMD_START) >> 24); ++ dev_err(&host->pdev->dev, ++ "irq status %08lx, intfc status %08lx\n", ++ (unsigned long)NAND_TEST_IRQ(NCINTR_CTLRDY), ++ (unsigned long)NAND_REG_RD(NCREG_INTFC_STATUS)); ++ } ++ ctrl.cmd_pending = 0; ++ iproc_nand_wp(mtd, 1); ++ return NAND_REG_RD(NCREG_INTFC_STATUS) & ++ NCFLD_INTFC_STATUS_FLASH_STATUS_MASK; ++} ++ ++static void ++iproc_nand_cmdfunc(struct mtd_info *mtd, unsigned command, ++ int column, int page_addr) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ u64 addr = (u64)page_addr << chip->page_shift; ++ int native_cmd = 0; ++ ++ if (command == NAND_CMD_READID ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ || command == NAND_CMD_PARAM ++#endif ++ ) ++ addr = (u64)column; ++ ++ DBG("%s: cmd 0x%x addr 0x%llx\n", __func__, command,(unsigned long long)addr); ++ host->last_cmd = command; ++ host->last_byte = 0; ++ host->last_addr = addr; ++ ++ switch (command) { ++ case NAND_CMD_RESET: ++ native_cmd = CMD_FLASH_RESET; ++ break; ++ case NAND_CMD_STATUS: ++ native_cmd = CMD_STATUS_READ; ++ break; ++ case NAND_CMD_READID: ++ native_cmd = CMD_DEVICE_ID_READ; ++ break; ++ case NAND_CMD_READOOB: ++ native_cmd = CMD_SPARE_AREA_READ; ++ break; ++ case NAND_CMD_ERASE1: ++ native_cmd = CMD_BLOCK_ERASE; ++ iproc_nand_wp(mtd, 0); ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ case NAND_CMD_PARAM: ++ native_cmd = CMD_PARAMETER_READ; ++ break; ++#endif ++ } ++ ++ if (!native_cmd) ++ return; ++ ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ ++ iproc_nand_send_cmd(native_cmd); ++ iproc_nand_waitfunc(mtd, chip); ++} ++ ++static uint8_t ++iproc_nand_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ uint8_t ret = 0; ++ ++ switch (host->last_cmd) { ++ case NAND_CMD_READID: ++ if (host->last_byte < 4) ++ ret = NAND_REG_RD(NCREG_FLASH_DEVICE_ID) >> ++ (24 - (host->last_byte << 3)); ++ else if (host->last_byte < 8) ++ ret = NAND_REG_RD(NCREG_FLASH_DEVICE_ID_EXT) >> ++ (56 - (host->last_byte << 3)); ++ break; ++ ++ case NAND_CMD_READOOB: ++ ret = oob_reg_read(host->last_byte); ++ break; ++ ++ case NAND_CMD_STATUS: ++ ret = NAND_REG_RD(NCREG_INTFC_STATUS) & ++ NCFLD_INTFC_STATUS_FLASH_STATUS_MASK; ++ if (wp_on) { ++ /* Hide WP status from MTD */ ++ ret |= NAND_STATUS_WP; ++ } ++ break; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ case NAND_CMD_PARAM: ++ if (host->last_byte < FC_BYTES) ++ ret = NAND_REG_RD(FC(host->last_byte >> 2)) >> ++ (24 - ((host->last_byte & 0x03) << 3)); ++ break; ++#endif ++ } ++ ++ DBG("%s: byte = 0x%02x\n", __func__, ret); ++ host->last_byte++; ++ ++ return ret; ++} ++ ++static void ++iproc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++, buf++) ++ *buf = iproc_nand_read_byte(mtd); ++} ++ ++/* Copied from nand_base.c to support custom iproc_check_exceptions() */ ++static void ++iproc_nand_erase_cmd(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *chip = mtd->priv; ++ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); ++} ++ ++/* ++ * Assumes proper CS is already set ++ */ ++static void ++iproc_nand_read_by_pio(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, unsigned int trans, ++ u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int i, j; ++ ++ for (i = 0; i < trans; i++, addr += FC_BYTES) { ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ ++ iproc_nand_send_cmd(CMD_PAGE_READ); ++ iproc_nand_waitfunc(mtd, chip); ++ ++ if (likely(buf)) { ++ NAND_BEGIN_DATA_ACCESS(); ++ for (j = 0; j < FC_WORDS; j++, buf++) ++ *buf = NAND_REG_RD(FC(j)); ++ NAND_END_DATA_ACCESS(); ++ } ++ ++ if (oob) ++ oob += read_oob_from_regs(i, oob, ++ mtd->oobsize / trans, host->hwcfg.sector_size_1k); ++ } ++} ++ ++static int ++iproc_nand_read(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, unsigned int trans, ++ u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ u64 err_addr; ++ DBG("%s %llx -> %p\n", __func__, (unsigned long long)addr, buf); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* If reading OOB only, don't enable ECC correction */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ } ++ ++ /* We must read spare area to check false uncorrectable errors. */ ++ if (oob == NULL) { ++ oob = (u8 *)host->buf; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ NAND_REG_WR_RB(NCREG_ECC_UNC_ADDR, 0); ++ NAND_REG_WR_RB(NCREG_ECC_CORR_ADDR, 0); ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ ++ iproc_nand_read_by_pio(mtd, chip, addr, trans, buf, oob); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Rollback ECC correction */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ ++ /* No ECC correction was performed */ ++ return 0; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ /* Check correctable errors */ ++ err_addr = NAND_REG_RD(NCREG_ECC_CORR_ADDR) | ++ ((u64)(NAND_REG_RD(NCREG_ECC_CORR_EXT_ADDR) & 0xffff) << 32); ++ if (err_addr) { ++ printk(KERN_DEBUG "%s: corrected error at 0x%llx\n", ++ DRV_NAME, (unsigned long long)err_addr); ++ mtd->ecc_stats.corrected += CORR_ERROR_COUNT; ++ /* NAND layer expects zero on ECC errors */ ++ return 0; ++ } ++ ++ /* Check uncorrectable errors */ ++ err_addr = NAND_REG_RD(NCREG_ECC_UNC_ADDR) | ++ ((u64)(NAND_REG_RD(NCREG_ECC_UNC_EXT_ADDR) & 0xffff) << 32); ++ if (err_addr != 0) { ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ int i; ++ ++ /* Check if ECC bytes are FFs. Only the first sector is required. */ ++ for(i=0; ieccbytes; i++) { ++ if (oob[host->eccpos + i] != 0xFF) { ++ break; ++ } ++ } ++ if (i == host->eccbytes) { ++ /* False alarm (the page was written with OOB only and ECC off) */ ++ return 0; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++#ifdef NAND_REPORT_ECC_UNCORR_ERRORS ++ printk(KERN_WARNING "%s: uncorrectable error at 0x%llx\n", ++ DRV_NAME, (unsigned long long)err_addr); ++ mtd->ecc_stats.failed += UNCORR_ERROR_COUNT; ++#endif /* NAND_REPORT_ECC_UNCORR_ERRORS */ ++ ++ /* NAND layer expects zero on ECC errors */ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int ++iproc_nand_read_page(struct mtd_info *mtd, ++ struct nand_chip *chip, uint8_t *buf, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ return iproc_nand_read(mtd, chip, host->last_addr, ++ mtd->writesize >> FC_SHIFT, (u32 *)buf, ++ (u8 *)chip->oob_poi); ++} ++ ++static int ++iproc_nand_read_page_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, uint8_t *buf, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int ret; ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ ret = iproc_nand_read(mtd, chip, host->last_addr, ++ mtd->writesize >> FC_SHIFT, ++ (u32 *)buf, (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ return ret; ++} ++ ++static int ++iproc_nand_read_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ return iproc_nand_read(mtd, chip, (u64)page << chip->page_shift, ++ mtd->writesize >> FC_SHIFT, ++ NULL, (u8 *)chip->oob_poi); ++} ++ ++#ifdef NAND_BBT_USE_FLASH ++/* Patched MTD implementation */ ++static int ++iproc_nand_read_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ iproc_nand_read(mtd, chip, (u64)page << chip->page_shift, ++ mtd->writesize >> FC_SHIFT, ++ NULL, (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ return 0; ++} ++#endif ++ ++static int ++iproc_nand_read_subpage(struct mtd_info *mtd, ++ struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, ++ uint8_t *bufpoi) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ return iproc_nand_read(mtd, chip, host->last_addr + data_offs, ++ readlen >> FC_SHIFT, (u32 *)bufpoi, NULL); ++} ++ ++static int ++iproc_nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ unsigned int i, j; ++ int err; ++ u64 addr = host->last_addr; ++ u32 *src = (u32 *)buf, *dst; ++ ++ for (i = 0; i < (mtd->writesize >> FC_SHIFT); i++) { ++ err = iproc_nand_read(mtd, chip, addr, 1, host->buf, NULL); ++ ++ if (err) { ++ dev_info(&host->pdev->dev, ++ "verify failed at 0x%llx (error %d)\n", ++ (unsigned long long)addr, err); ++ return -EFAULT; ++ } ++ dst = host->buf; ++ ++ for (j = 0; j < FC_WORDS; j++, src++, dst++) ++ if (*src != le32_to_cpu(*dst)) { ++ dev_info(&host->pdev->dev, ++ "mismatch at 0x%llx (read %08lx, " ++ "expected %08lx)\n", ++ (unsigned long long)addr + (j << 2), ++ (unsigned long)*dst, ++ (unsigned long)*src); ++ return -EFAULT; ++ } ++ addr += FC_BYTES; ++ } ++ return 0; ++} ++ ++static int ++iproc_nand_write(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, const u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ unsigned int i = 0, j, trans = mtd->writesize >> FC_SHIFT; ++ int status; ++ ++ DBG("%s %llx <- %p\n", __func__, (unsigned long long)addr, buf); ++ ++ if (unlikely((u32)buf & 0x03)) { ++ dev_warn(&host->pdev->dev, "unaligned buffer: %p\n", buf); ++ buf = (u32 *)((u32)buf & ~0x03); ++ } ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Merge (AND) the new and old OOB data */ ++ if (oob) { ++ ++ u8 *oob0 = (u8 *)host->buf; ++ int i; ++ ++ /* Read the spare area from flash */ ++ iproc_nand_read(mtd, chip, addr, 8, NULL, oob0); ++ ++ /* AND them with new OOB data */ ++ for(i=0; ioobsize; i++) { ++ oob[i] &= oob0[i]; ++ } ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ ++ for (j = 0; j < MAX_CONTROLLER_OOB; j += 4) ++ oob_reg_write(j, 0xffffffff); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Disable ECC generation if writing OOB only */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ for (; i < trans; i++, addr += FC_BYTES) { ++ ++ /* full address MUST be set before populating FC */ ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ ++ if (buf) { ++ NAND_BEGIN_DATA_ACCESS(); ++ for (j = 0; j < FC_WORDS; j++, buf++) ++ NAND_REG_WR(FC(j), *buf); ++ NAND_END_DATA_ACCESS(); ++ } else if (oob) { ++ for (j = 0; j < FC_WORDS; j++) ++ NAND_REG_WR(FC(j), 0xffffffff); ++ } ++ ++ if (oob) { ++ oob += write_oob_to_regs(i, oob, mtd->oobsize / trans, ++ host->hwcfg.sector_size_1k); ++ } ++ ++ iproc_nand_wp(mtd, 0); ++ ++ /* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */ ++ iproc_nand_send_cmd(CMD_PROGRAM_PAGE); ++ status = iproc_nand_waitfunc(mtd, chip); ++ ++ if (status & NAND_STATUS_FAIL) { ++ dev_info(&host->pdev->dev, "program failed at %llx\n", ++ (unsigned long long)addr); ++ return -EIO; ++ } ++ } ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Rollback ECC generation */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ return 0; ++} ++ ++static void ++iproc_nand_write_page(struct mtd_info *mtd, ++ struct nand_chip *chip, const uint8_t *buf) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ iproc_nand_write(mtd, chip, host->last_addr, (u32 *)buf, (u8 *)chip->oob_poi); ++} ++ ++static void ++iproc_nand_write_page_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, const uint8_t *buf) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ iproc_nand_write(mtd, chip, host->last_addr, (u32 *)buf, ++ (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++} ++ ++static int ++iproc_nand_write_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page) ++{ ++ return iproc_nand_write(mtd, chip, (u64)page << chip->page_shift, NULL, ++ (u8 *)chip->oob_poi); ++} ++ ++#ifdef NAND_BBT_USE_FLASH ++/* Patched MTD implementation */ ++static int ++iproc_nand_write_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int r; ++ ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ r = iproc_nand_write(mtd, chip, (u64)page << chip->page_shift, NULL, ++ (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ return r; ++} ++#endif ++ ++ ++/*********************************************************************** ++ * Per-CS setup (1 NAND device) ++ ***********************************************************************/ ++ ++static const unsigned int block_sizes[] = { 8, 16, 128, 256, 512, 1024, 2048 }; ++static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192 }; ++ ++static void ++iproc_nand_set_cfg(struct iproc_nand_host *host, ++ struct iproc_nand_cfg *cfg) ++{ ++ int i, found; ++ ++ for (i = 0, found = 0; i < ARRAY_SIZE(block_sizes); i++) ++ if ((block_sizes[i] << 10) == cfg->block_size) { ++ WR_CONFIG(host->cs, BLOCK_SIZE, i); ++ found = 1; ++ } ++ if (!found) ++ dev_warn(&host->pdev->dev, "invalid block size %u\n", ++ cfg->block_size); ++ ++ for (i = 0, found = 0; i < ARRAY_SIZE(page_sizes); i++) ++ if (page_sizes[i] == cfg->page_size) { ++ WR_CONFIG(host->cs, PAGE_SIZE, i); ++ found = 1; ++ } ++ if (!found) ++ dev_warn(&host->pdev->dev, "invalid page size %u\n", ++ cfg->page_size); ++ ++ if (fls64(cfg->device_size) < 23) ++ dev_warn(&host->pdev->dev, "invalid device size 0x%llx\n", ++ (unsigned long long)cfg->device_size); ++ ++ WR_CONFIG(host->cs, DEVICE_SIZE, fls64(cfg->device_size) - 23); ++ WR_CONFIG(host->cs, DEVICE_WIDTH, cfg->device_width == 16 ? 1 : 0); ++ WR_CONFIG(host->cs, COL_ADR_BYTES, cfg->col_adr_bytes); ++ WR_CONFIG(host->cs, BLK_ADR_BYTES, cfg->blk_adr_bytes); ++ WR_CONFIG(host->cs, FUL_ADR_BYTES, cfg->ful_adr_bytes); ++ ++ WR_ACC_CONTROL(host->cs, SPARE_AREA_SIZE, cfg->spare_area_size); ++ WR_ACC_CONTROL(host->cs, SECTOR_SIZE_1K, cfg->sector_size_1k); ++} ++ ++static void ++iproc_nand_get_cfg(struct iproc_nand_host *host, ++ struct iproc_nand_cfg *cfg) ++{ ++ cfg->block_size = RD_CONFIG(host->cs, BLOCK_SIZE); ++ cfg->device_size = (4ULL << 20) << RD_CONFIG(host->cs, DEVICE_SIZE); ++ cfg->page_size = RD_CONFIG(host->cs, PAGE_SIZE); ++ cfg->device_width = RD_CONFIG(host->cs, DEVICE_WIDTH) ? 16 : 8; ++ cfg->col_adr_bytes = RD_CONFIG(host->cs, COL_ADR_BYTES); ++ cfg->blk_adr_bytes = RD_CONFIG(host->cs, BLK_ADR_BYTES); ++ cfg->ful_adr_bytes = RD_CONFIG(host->cs, FUL_ADR_BYTES); ++ cfg->spare_area_size = RD_ACC_CONTROL(host->cs, SPARE_AREA_SIZE); ++ cfg->sector_size_1k = RD_ACC_CONTROL(host->cs, SECTOR_SIZE_1K); ++ ++ if (cfg->block_size < ARRAY_SIZE(block_sizes)) ++ cfg->block_size = block_sizes[cfg->block_size] << 10; ++ else ++ cfg->block_size = 128 << 10; ++ ++ if (cfg->page_size < ARRAY_SIZE(page_sizes)) ++ cfg->page_size = page_sizes[cfg->page_size]; ++ else ++ cfg->page_size = 2048; ++} ++ ++static void ++iproc_nand_print_cfg(char *buf, struct iproc_nand_cfg *cfg) ++{ ++ sprintf(buf, ++ "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit", ++ (unsigned long long)cfg->device_size >> 20, ++ cfg->block_size >> 10, ++ cfg->page_size >= 1024 ? cfg->page_size >> 10 : cfg->page_size, ++ cfg->page_size >= 1024 ? "KiB" : "B", ++ cfg->spare_area_size, cfg->device_width); ++} ++ ++static int __devinit ++iproc_nand_setup_dev( ++ struct iproc_nand_host *host, ++ struct brcmnand_platform_data *pd) ++{ ++ struct mtd_info *mtd = &host->mtd; ++ struct nand_chip *chip = &host->chip; ++ struct iproc_nand_cfg orig_cfg, new_cfg; ++ struct nand_oobfree *free = iproc_nand_oob_layout.oobfree; ++ char msg[128]; ++ unsigned int ecclevel; ++ ++ iproc_nand_get_cfg(host, &orig_cfg); ++ host->hwcfg = orig_cfg; ++ ++ memset(&new_cfg, 0, sizeof(new_cfg)); ++ new_cfg.device_size = mtd->size; ++ new_cfg.block_size = mtd->erasesize; ++ new_cfg.page_size = mtd->writesize; ++ new_cfg.spare_area_size = mtd->oobsize / (mtd->writesize >> FC_SHIFT); ++ new_cfg.device_width = (chip->options & NAND_BUSWIDTH_16) ? 16 : 8; ++ new_cfg.col_adr_bytes = 2; ++ ++ if (mtd->writesize > 512) ++ if (mtd->size >= (256 << 20)) ++ new_cfg.blk_adr_bytes = 3; ++ else ++ new_cfg.blk_adr_bytes = 2; ++ else ++ if (mtd->size >= (64 << 20)) ++ new_cfg.blk_adr_bytes = 3; ++ else ++ new_cfg.blk_adr_bytes = 2; ++ new_cfg.ful_adr_bytes = new_cfg.blk_adr_bytes + new_cfg.col_adr_bytes; ++ ++ /* Original ECC level */ ++ ecclevel = RD_ACC_CONTROL(host->cs, ECC_LEVEL); ++ ++ /* Check settings inherited from bootloader */ ++ if(ctrl.boot_inited) { ++ ++ /* Check basic device attributes first */ ++ int sz1k = orig_cfg.sector_size_1k? 1 : 0; ++ if (orig_cfg.device_size != new_cfg.device_size || ++ orig_cfg.block_size != new_cfg.block_size || ++ orig_cfg.page_size != new_cfg.page_size || ++ orig_cfg.device_width != new_cfg.device_width || ++ orig_cfg.col_adr_bytes != new_cfg.col_adr_bytes || ++ orig_cfg.blk_adr_bytes != new_cfg.blk_adr_bytes || ++ orig_cfg.ful_adr_bytes != new_cfg.ful_adr_bytes || ++ ecclevel == 0 || ecclevel >= nand_iproc_ecc_levels[sz1k] || ++ orig_cfg.spare_area_size > new_cfg.spare_area_size || ++ nand_iproc_ecc_bytes[ecclevel] > orig_cfg.spare_area_size) { ++ ++ ctrl.boot_inited = 0; ++ printk(KERN_INFO "%s: invalid bootloader settings\n", DRV_NAME); ++ ++ } else { ++ /* Bootloader has initialized the flash correctly. */ ++ new_cfg = orig_cfg; ++ iproc_nand_print_cfg(msg, &orig_cfg); ++ printk(KERN_INFO "%s: following bootloader settings\n", DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ } ++ } ++ ++ /* Decide ECC settings ourselves if it's not initialized before */ ++ if (!ctrl.boot_inited) { ++ ++ /* Check if strap settings are valid */ ++ if (pd->strap_type > 0 && ++ nand_strap_page_sizes[pd->strap_page_size] == new_cfg.page_size && ++ nand_strap_types[pd->strap_type].spare_size <= mtd->writesize ) { ++ ++ /* It's valid, follow the strap settings */ ++ new_cfg.spare_area_size = nand_strap_types[pd->strap_type].spare_size; ++ new_cfg.sector_size_1k = nand_strap_types[pd->strap_type].sector_1k; ++ ecclevel = nand_strap_types[pd->strap_type].ecclevel; ++ if (pd->strap_page_size == 0) { ++ new_cfg.blk_adr_bytes = 2; ++ new_cfg.ful_adr_bytes = 4; ++ } else { ++ new_cfg.blk_adr_bytes = 3; ++ new_cfg.ful_adr_bytes = 5; ++ } ++ ++ iproc_nand_print_cfg(msg, &new_cfg); ++ printk(KERN_INFO "%s: following strap settings\n", DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ ++ } else { ++ ++ /* ++ * Strap settings are not valid, decide the settings on our own ++ */ ++ ++ /* Trying to fit with available strap settings */ ++ new_cfg.spare_area_size = new_cfg.spare_area_size >= 27 ? 27 : 16; ++ new_cfg.sector_size_1k = 0; ++ if (new_cfg.spare_area_size == 27) { ++ ecclevel = 12; ++ new_cfg.sector_size_1k = (new_cfg.page_size >= 2048) ? 1 : 0; ++ } else if (chip->badblockpos == NAND_SMALL_BADBLOCK_POS) { ++ ecclevel = 4; ++ } else { ++ ecclevel = 8; ++ } ++ ++ iproc_nand_print_cfg(msg, &new_cfg); ++ printk(KERN_ERR "*ERROR* Invalid board strap settings for NAND!"); ++ printk(KERN_INFO "%s: overriding invalid strap settings\n", ++ DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ } ++ ++ iproc_nand_set_cfg(host, &new_cfg); ++ host->hwcfg = new_cfg; ++ ++ WR_ACC_CONTROL(host->cs, ECC_LEVEL, ecclevel); ++ /* threshold = ceil(BCH-level * 0.75) */ ++ WR_CORR_THRESH(host->cs, ((ecclevel << new_cfg.sector_size_1k) ++ * 3 + 2) / 4); ++ ++ /* Account for 24-bit per 1024-byte ECC settings */ ++ if (new_cfg.sector_size_1k) ++ printk(KERN_INFO "%s: ECC set to BCH-%u (1KiB sector)\n", ++ DRV_NAME, ecclevel << 1); ++ else ++ printk(KERN_INFO "%s: ECC set to BCH-%u (512B sector)\n", ++ DRV_NAME, ecclevel); ++ } ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ WR_ACC_CONTROL(host->cs, FAST_PGM_RDIN, 0); ++ WR_ACC_CONTROL(host->cs, RD_ERASED_ECC_EN, 0); ++ WR_ACC_CONTROL(host->cs, PARTIAL_PAGE_EN, 0); ++ WR_ACC_CONTROL(host->cs, PAGE_HIT_EN, 1); ++ ++ mb(); ++ ++ /* Adjust MTD oobsize according to the configuration */ ++ mtd->oobsize = new_cfg.spare_area_size * (mtd->writesize >> FC_SHIFT); ++ ++ /* Adjust ECC layout for storing usb OOB data */ ++ free->length = 0; ++ if (ecclevel < nand_iproc_ecc_levels[new_cfg.sector_size_1k]) { ++ ++ uint8_t steps = mtd->writesize >> FC_SHIFT; ++ uint8_t eccbytes = nand_iproc_ecc_bytes[ecclevel]; ++ ++ /* Special case: using Hamming code when ecclevel == 15 */ ++ if (ecclevel == 15) { ++ if (new_cfg.spare_area_size == 16 && !new_cfg.sector_size_1k) { ++ eccbytes = 3; ++ } ++ } ++ ++ /* These are not really used. We still prepare them for safety. */ ++ iproc_nand_oob_layout.eccbytes = eccbytes * steps; ++ chip->ecc.bytes = eccbytes; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) ++ chip->ecc.strength = ecclevel; ++#endif ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ host->eccpos = ++ (new_cfg.spare_area_size - eccbytes) << new_cfg.sector_size_1k; ++ host->eccbytes = eccbytes << new_cfg.sector_size_1k; ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ /* Create oobfree for storing user OOB data */ ++ if (new_cfg.spare_area_size > eccbytes) { ++ ++ unsigned int spare_size; ++ uint8_t i, cnt; ++ ++ spare_size = new_cfg.spare_area_size << new_cfg.sector_size_1k; ++ eccbytes <<= new_cfg.sector_size_1k; ++ steps >>= new_cfg.sector_size_1k; ++ if (steps > MTD_MAX_OOBFREE_ENTRIES) { ++ steps = MTD_MAX_OOBFREE_ENTRIES; ++ } ++ for(i=0, cnt=0; ioffset = i * spare_size; ++ free->length = 6; ++ ++ } else { ++ ++ /* BCH: ECC bytes at the bottom */ ++ free->offset = i * spare_size; ++ free->length = spare_size - eccbytes; ++ } ++ ++ /* Reserve the first two bytes of the page */ ++ if (i == 0) { ++ if (free->length <= 2) { ++ /* Don't claim this entry if less than 2 bytes */ ++ continue; ++ } ++ free->offset += 2; ++ free->length -= 2; ++ } ++ ++ if (eccbytes == 3) { ++ /* Hamming code: the 2nd free part */ ++ free++; ++ cnt++; ++ if (cnt < MTD_MAX_OOBFREE_ENTRIES) { ++ free->offset = i * spare_size + 9; ++ free->length = 7; ++ } else { ++ /* The structure limits us. */ ++ break; ++ } ++ } ++ ++ free++; ++ cnt++; ++ } ++ if (cnt < MTD_MAX_OOBFREE_ENTRIES) { ++ /* Terminater */ ++ free->length = 0; ++ } ++ ++ /* Print out oob space information */ ++ free = iproc_nand_oob_layout.oobfree; ++ if (free->length) { ++ spare_size = 0; ++ while(free->length) { ++ spare_size += free->length; ++ free++; ++ } ++ printk(KERN_INFO "%s: user oob per page: %u bytes (%u steps)\n", ++ DRV_NAME, spare_size, (int)steps); ++ } ++ } ++ } ++ ++ if (iproc_nand_oob_layout.oobfree[0].length == 0) { ++ printk(KERN_INFO "%s: no oob space available\n", DRV_NAME); ++ } ++ ++ return 0; ++} ++ ++static int ++iproc_check_exceptions(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_exception *list = iproc_exceptions_list; ++ int i; ++ u8 id_data[8]; ++ ++ /* ++ * run default nand_base initialization w/o built-in ID table; ++ * should return error, so we tell it to be "silent" ++ */ ++ chip->options |= NAND_SCAN_SILENT_NODEV; ++ nand_scan_ident(mtd, 1, iproc_empty_flash_table); ++ chip->options &= ~NAND_SCAN_SILENT_NODEV; ++ ++ /* Send the command for reading device ID */ ++ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ++ for (i = 0; i < 8; i++) ++ id_data[i] = chip->read_byte(mtd); ++ ++ for (; list->name != NULL; list++) { ++ for (i = 0; i < list->idlen; i++) ++ if (id_data[i] != list->id[i]) ++ break; ++ if (i == list->idlen) ++ break; ++ } ++ ++ if (!list->name) ++ return -ENODEV; ++ ++ chip->chipsize = (uint64_t)list->chipsize << 20; ++ mtd->size = chip->chipsize; ++ ++ mtd->erasesize = list->erasesize; ++ mtd->writesize = list->writesize; ++ mtd->oobsize = list->oobsize; ++ ++ chip->options |= list->chipoptions; ++ chip->badblockpos = list->badblockpos; ++ ++ /* The 3rd id byte holds MLC / multichip data */ ++ chip->cellinfo = id_data[2]; ++ ++ chip->numchips = 1; ++ ++ /* Calculate the address shift from the page size */ ++ chip->page_shift = ffs(mtd->writesize) - 1; ++ /* Convert chipsize to number of pages per chip -1. */ ++ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; ++ ++ chip->bbt_erase_shift = chip->phys_erase_shift = ++ ffs(mtd->erasesize) - 1; ++ chip->chip_shift = fls64(chip->chipsize) - 1; ++ ++ chip->erase_cmd = iproc_nand_erase_cmd; ++ ++ printk(KERN_INFO "%s: heuristics exception detected, %s\n", ++ DRV_NAME, list->name); ++ return 0; ++} ++ ++static int __devinit ++iproc_nand_probe(struct platform_device *pdev) ++{ ++ struct brcmnand_platform_data *pd = pdev->dev.platform_data; ++ struct iproc_nand_host *host; ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ int ret = 0; ++ ++#if defined(CONFIG_MTD_PARTITIONS) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) ++ int nr_parts; ++ struct mtd_partition *parts; ++ const char *part_probe_types[] = { "cmdlinepart", NULL }; ++#endif ++ ++ DBG("%s: id %d cs %d\n", __func__, pdev->id, pd->chip_select); ++ ++ host = kzalloc(sizeof(*host), GFP_KERNEL); ++ if (!host) { ++ dev_err(&pdev->dev, "can't allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ host->cs = pd->chip_select; ++ ++ mtd = &host->mtd; ++ chip = &host->chip; ++ host->pdev = pdev; ++ dev_set_drvdata(&pdev->dev, host); ++ ++ chip->priv = host; ++ mtd->priv = chip; ++ mtd->name = dev_name(&pdev->dev); ++ mtd->owner = THIS_MODULE; ++ mtd->dev.parent = &pdev->dev; ++ ++ chip->IO_ADDR_R = (void *)0xdeadbeef; ++ chip->IO_ADDR_W = (void *)0xdeadbeef; ++ ++ chip->cmd_ctrl = iproc_nand_cmd_ctrl; ++ chip->cmdfunc = iproc_nand_cmdfunc; ++ chip->waitfunc = iproc_nand_waitfunc; ++ chip->read_byte = iproc_nand_read_byte; ++ chip->read_buf = iproc_nand_read_buf; ++ chip->verify_buf = iproc_nand_verify_buf; ++ ++ chip->ecc.mode = NAND_ECC_HW; ++ chip->ecc.size = 512; ++ chip->ecc.layout = &iproc_nand_oob_layout; ++ chip->ecc.read_page = (void *) iproc_nand_read_page; ++ chip->ecc.read_subpage = iproc_nand_read_subpage; ++ chip->ecc.write_page = (void *) iproc_nand_write_page; ++ chip->ecc.read_page_raw = (void *) iproc_nand_read_page_raw; ++ chip->ecc.write_page_raw = (void *) iproc_nand_write_page_raw; ++ ++#ifdef NAND_BBT_USE_FLASH ++ /* Patched MTD implementation */ ++ chip->ecc.write_oob_raw = iproc_nand_write_oob_raw; ++ chip->ecc.read_oob_raw = (void *) iproc_nand_read_oob_raw; ++#endif ++ ++ chip->ecc.read_oob = (void *) iproc_nand_read_oob; ++ chip->ecc.write_oob = iproc_nand_write_oob; ++ ++ chip->controller = &ctrl.controller; ++ ++ if (iproc_check_exceptions(mtd) && nand_scan_ident(mtd, 1, NULL)) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_SKIP_BBTSCAN; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) ++ chip->options |= NAND_NO_AUTOINCR; ++#endif ++ ++#ifdef NAND_BBT_USE_FLASH ++ /* patched MTD implementation */ ++ chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; ++#else /* Standard MTD implementation */ ++ chip->options |= NAND_USE_FLASH_BBT; ++#ifdef NAND_USE_FLASH_BBT_NO_OOB ++ chip->options |= NAND_USE_FLASH_BBT_NO_OOB; ++#endif /* NAND_USE_FLASH_BBT_NO_OOB */ ++#endif /* NAND_BBT_USE_FLASH */ ++ ++ if (iproc_nand_setup_dev(host, pd) || nand_scan_tail(mtd) || ++ chip->scan_bbt(mtd)) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) ++ mtd_device_parse_register(mtd, NULL, NULL, pd->parts, pd->nr_parts); ++#else ++#ifdef CONFIG_MTD_PARTITIONS ++ nr_parts = parse_mtd_partitions(mtd, part_probe_types, &parts, 0); ++ if (nr_parts <= 0) { ++ nr_parts = pd->nr_parts; ++ parts = pd->parts; ++ } ++ ++ if (nr_parts) ++ add_mtd_partitions(mtd, parts, nr_parts); ++ else ++#endif ++ add_mtd_device(mtd); ++#endif ++ ++ return 0; ++ ++err1: ++ kfree(host); ++ return ret; ++} ++ ++static int __devexit ++iproc_nand_remove(struct platform_device *pdev) ++{ ++ struct iproc_nand_host *host = dev_get_drvdata(&pdev->dev); ++ struct mtd_info *mtd = &host->mtd; ++ ++ nand_release(mtd); ++ dev_set_drvdata(&pdev->dev, NULL); ++ kfree(host); ++ ++ return 0; ++} ++ ++/*********************************************************************** ++ * Platform driver setup (per controller) ++ ***********************************************************************/ ++static struct platform_driver iproc_nand_driver = { ++ .probe = iproc_nand_probe, ++ .remove = __devexit_p(iproc_nand_remove), ++ .driver = { ++ .name = "nand_iproc", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init iproc_nand_init(void) ++{ ++ int err = -ENODEV; ++ ++ init_completion(&ctrl.done); ++ spin_lock_init(&ctrl.controller.lock); ++ init_waitqueue_head(&ctrl.controller.wq); ++ ctrl.cmd_pending = 0; ++ ctrl.boot_inited = 1; ++ ++ /* Initialize registers and IRQ */ ++ ctrl.nand_regs = ctrl.nand_intr_regs = ctrl.idm_nand_regs = NULL; ++ ctrl.nand_regs = (volatile void *)ioremap(NAND_NAND_FLASH_REV, 0x1000); ++ if (!ctrl.nand_regs) { ++ printk(KERN_ERR "%s: can't ioremap\n", DRV_NAME); ++ err = -EIO; ++ goto err; ++ } ++ ctrl.nand_intr_regs = ctrl.nand_regs + ++ (NAND_DIRECT_READ_RD_MISS - NAND_NAND_FLASH_REV); ++ ctrl.idm_nand_regs = (volatile void *)ioremap(IPROC_IDM_NAND_REG_BASE, 4); ++ if (!ctrl.idm_nand_regs) { ++ printk(KERN_ERR "%s: can't ioremap\n", DRV_NAME); ++ err = -EIO; ++ goto err; ++ } ++ ctrl.irq = IPROC_NAND_IRQ_START; ++ DBG("%s: nand_regs - %p\n", __func__, ctrl.nand_regs); ++ DBG("%s: nand_intr_regs - %p\n", __func__, ctrl.nand_intr_regs); ++ DBG("%s: idm_nand_regs - %p\n", __func__, ctrl.idm_nand_regs); ++ DBG("%s: irq - %d\n", __func__, ctrl.irq); ++ ++ /* If bootloader has initialized it, auto-config should be cleared */ ++ if (NAND_REG_RD(NCREG_CS_NAND_SELECT) & ++ NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG) { ++ ctrl.boot_inited = 0; ++ } ++ ++ /* Perform basic controller initialization */ ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG); ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_DIRECT_ACCESS_CS_MASK); ++ NAND_REG_UNSET(NCREG_CS_NAND_XOR, NCFLD_CS_NAND_XOR_CS_MASK); ++ if (wp_on == 2) { ++ /* Permanently remove write-protection */ ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } ++ ++ /* Attach IRQ handler */ ++ NAND_ACK_IRQ(NCINTR_CTLRDY); ++ NAND_ENABLE_IRQ(NCINTR_CTLRDY); ++ err = request_irq((unsigned int)ctrl.irq, iproc_nand_irq, 0, ++ DRV_NAME, &ctrl); ++ if (err < 0) { ++ printk(KERN_ERR "%s: unable to allocate IRQ (error %d)\n", DRV_NAME, err); ++ goto err; ++ } ++ ++ err = platform_driver_register(&iproc_nand_driver); ++ if (err < 0) { ++ printk(KERN_ERR "%s: can't register platform driver " ++ "(error %d)\n", DRV_NAME, err); ++ free_irq(ctrl.irq, &ctrl); ++ goto err; ++ } ++ ++ printk(KERN_INFO DRV_NAME ": NAND controller driver is loaded\n"); ++ return 0; ++ ++err: ++ NAND_DISABLE_IRQ(NCINTR_CTLRDY); ++ if (ctrl.idm_nand_regs) { ++ iounmap(ctrl.idm_nand_regs); ++ ctrl.idm_nand_regs = NULL; ++ } ++ ctrl.nand_intr_regs = NULL; ++ if (ctrl.nand_regs) { ++ iounmap(ctrl.nand_regs); ++ ctrl.nand_regs = NULL; ++ } ++ return err; ++} ++ ++static void __exit iproc_nand_exit(void) ++{ ++ platform_driver_unregister(&iproc_nand_driver); ++ free_irq(ctrl.irq, &ctrl); ++ NAND_DISABLE_IRQ(NCINTR_CTLRDY); ++ if (ctrl.idm_nand_regs) { ++ iounmap(ctrl.idm_nand_regs); ++ ctrl.idm_nand_regs = NULL; ++ } ++ ctrl.nand_intr_regs = NULL; ++ if (ctrl.nand_regs) { ++ iounmap(ctrl.nand_regs); ++ ctrl.nand_regs = NULL; ++ } ++} ++ ++module_init(iproc_nand_init); ++module_exit(iproc_nand_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("NAND driver for iProc chips"); +diff --git a/drivers/bcmdrivers/pmu/.gitignore b/drivers/bcmdrivers/pmu/.gitignore +new file mode 100644 +index 0000000..af7303c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch new file mode 100644 index 00000000..38ee39b6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_.gitignore.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_pmu.o.cmd ++/.iproc-pmu.o.cmd ++/built-in.o ++/iproc_pmu.o ++/iproc-pmu.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/pmu/Kconfig b/drivers/bcmdrivers/pmu/Kconfig +new file mode 100644 +index 0000000..8b09c0c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch new file mode 100644 index 00000000..7febc0e0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Kconfig.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/Kconfig +@@ -0,0 +1,9 @@ ++ ++config IPROC_PMU ++ tristate "Iproc PMU support" ++ depends on ARCH_IPROC ++ default y ++ help ++ Iproc PMU support ++ This config provides kernel-side support for iProc PMU description. ++ Its generic driver is perf_event.c +diff --git a/drivers/bcmdrivers/pmu/Makefile b/drivers/bcmdrivers/pmu/Makefile +new file mode 100644 +index 0000000..b491218 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch new file mode 100644 index 00000000..dae1af6d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_Makefile.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/Makefile +@@ -0,0 +1,8 @@ ++# iproc TDM support ++ ++EXTRA_CFLAGS += -I$(BCMDRIVERS_DIR)/gmac/src/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++iproc_pmu-objs := iproc-pmu.o ++ ++obj-$(CONFIG_IPROC_PMU) += iproc_pmu.o +diff --git a/drivers/bcmdrivers/pmu/iproc-pmu.c b/drivers/bcmdrivers/pmu/iproc-pmu.c +new file mode 100644 +index 0000000..83e1aec diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch new file mode 100644 index 00000000..a14e656d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pmu_iproc-pmu.c.patch @@ -0,0 +1,67 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/iproc-pmu.c +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * PMU device description to Iproc ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct resource iproc_pmu_resource = { ++ .start = BCM_INT_ID_IHOST_PMU, ++ .end = BCM_INT_ID_IHOST_PMU+1, ++ .flags = IORESOURCE_IRQ, ++}; ++ ++ ++static struct platform_device iproc_pmu_device = { ++ .name = "arm-pmu", ++ .id = ARM_PMU_DEVICE_CPU, ++ .dev = { ++ .init_name = "arm-pmu", ++ }, ++ .num_resources = 1, ++ .resource = &iproc_pmu_resource, ++}; ++ ++ ++static int __init iproc_pmu_init(void) ++{ ++ int ret; ++ printk(KERN_INFO "Registering iproc_pmu_device\n"); ++ ret = platform_device_register(&iproc_pmu_device); ++ return ret; ++} ++module_init(iproc_pmu_init); ++ ++ ++/* Module information */ ++MODULE_DESCRIPTION("IPROC PMU Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/pwm/.gitignore b/drivers/bcmdrivers/pwm/.gitignore +new file mode 100644 +index 0000000..6e1da9b diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch new file mode 100644 index 00000000..48910901 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_.gitignore.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_pwm.o.cmd ++/.iproc_pwmc.o.cmd ++/built-in.o ++/iproc_pwm.o ++/iproc_pwmc.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/pwm/Kconfig b/drivers/bcmdrivers/pwm/Kconfig +new file mode 100644 +index 0000000..c3bf727 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch new file mode 100644 index 00000000..8864744e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Kconfig.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_PWM ++ tristate "PWM support" ++ depends on ARCH_IPROC ++ default n ++ help ++ Add PWM support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/pwm/Makefile b/drivers/bcmdrivers/pwm/Makefile +new file mode 100644 +index 0000000..18ac980 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch new file mode 100644 index 00000000..cf9178bd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_PWM) += iproc_pwm.o ++iproc_pwm-objs := iproc_pwmc.o +diff --git a/drivers/bcmdrivers/pwm/iproc_pwmc.c b/drivers/bcmdrivers/pwm/iproc_pwmc.c +new file mode 100644 +index 0000000..4ea9255 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch new file mode 100644 index 00000000..edeab9b8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc.c.patch @@ -0,0 +1,417 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/iproc_pwmc.c +@@ -0,0 +1,411 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 5) ++#include "iproc_pwmc_3x.c" ++#else ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++#define IPROC_PWM_CHANNEL_CNT 4 ++#define PWM_PRESCALER_MAX 63 /* 6 bits field */ ++ ++ ++#define PWM_CTL_ENABLE_SHIFT (0) ++#define PWM_CTL_POLARITY_SHIFT (8) ++ ++#define PWM_PRESCALE_PWM3_PRESCALE_SHIFT (0) ++#define PWM_PRESCALE_PWM3_PRESCALE_MASK (0x0000003F) ++#define PWM_PRESCALE_PWM2_PRESCALE_SHIFT (6) ++#define PWM_PRESCALE_PWM2_PRESCALE_MASK (0x00000FC0) ++#define PWM_PRESCALE_PWM1_PRESCALE_SHIFT (12) ++#define PWM_PRESCALE_PWM1_PRESCALE_MASK (0x0003F000) ++#define PWM_PRESCALE_PWM0_PRESCALE_SHIFT (18) ++#define PWM_PRESCALE_PWM0_PRESCALE_MASK (0x00FC0000) ++ ++#define PWM_DUTY_HI_CNT0_SHIFT (0) ++#define PWM_DUTY_HI_CNT0_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT1_SHIFT (0) ++#define PWM_DUTY_HI_CNT1_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT2_SHIFT (0) ++#define PWM_DUTY_HI_CNT2_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT3_SHIFT (0) ++#define PWM_DUTY_HI_CNT3_MASK (0xFFFF) ++ ++#define PWM_PERIOD_CNT0_SHIFT (0) ++#define PWM_PERIOD_CNT0_MASK (0xFFFF) ++#define PWM_PERIOD_CNT1_SHIFT (0) ++#define PWM_PERIOD_CNT1_MASK (0xFFFF) ++#define PWM_PERIOD_CNT2_SHIFT (0) ++#define PWM_PERIOD_CNT2_MASK (0xFFFF) ++#define PWM_PERIOD_CNT3_SHIFT (0) ++#define PWM_PERIOD_CNT3_MASK (0xFFFF) ++ ++ ++struct pwm_reg_def { ++ u32 mask ; ++ u32 shift ; ++ u32 offset ; ++} ; ++ ++#define PWM_REG_DEF(c, m, s, a) \ ++ [c] = { \ ++ .mask = m, \ ++ .shift = s, \ ++ .offset = a \ ++ } ++ ++static const ++struct pwm_reg_def pwm_chan_pre_scaler_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PRESCALE_PWM0_PRESCALE_MASK, ++ PWM_PRESCALE_PWM0_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(1, PWM_PRESCALE_PWM1_PRESCALE_MASK, ++ PWM_PRESCALE_PWM1_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(2, PWM_PRESCALE_PWM2_PRESCALE_MASK, ++ PWM_PRESCALE_PWM2_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(3, PWM_PRESCALE_PWM3_PRESCALE_MASK, ++ PWM_PRESCALE_PWM3_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_period_cnt_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PERIOD_CNT0_MASK, ++ PWM_PERIOD_CNT0_SHIFT, CCB_PWM_PERIOD_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_PERIOD_CNT1_MASK, ++ PWM_PERIOD_CNT1_SHIFT, CCB_PWM_PERIOD_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_PERIOD_CNT2_MASK, ++ PWM_PERIOD_CNT2_SHIFT, CCB_PWM_PERIOD_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_PERIOD_CNT3_MASK, ++ PWM_PERIOD_CNT3_SHIFT, CCB_PWM_PERIOD_COUNT3_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_duty_cycle_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_DUTY_HI_CNT0_MASK, ++ PWM_DUTY_HI_CNT0_SHIFT, CCB_PWM_DUTY_HI_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_DUTY_HI_CNT1_MASK, ++ PWM_DUTY_HI_CNT1_SHIFT, CCB_PWM_DUTY_HI_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_DUTY_HI_CNT2_MASK, ++ PWM_DUTY_HI_CNT2_SHIFT, CCB_PWM_DUTY_HI_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_DUTY_HI_CNT3_MASK, ++ PWM_DUTY_HI_CNT3_SHIFT, CCB_PWM_DUTY_HI_COUNT3_BASE), ++} ; ++ ++ ++struct iproc_pwmc { ++ struct pwm_device *p[IPROC_PWM_CHANNEL_CNT]; ++ struct pwm_device_ops ops; ++ void __iomem *iobase; ++ struct clk *clk; ++}; ++ ++ ++static int iproc_get_chan(const struct iproc_pwmc *ap, const struct pwm_device *p) ++{ ++ int chan; ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) ++ if (p == ap->p[chan]) ++ return chan; ++ BUG(); ++ return 0; ++} ++ ++static void iproc_pwmc_clear_set_bit(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int shift, unsigned char en_dis) ++{ ++ unsigned long val = readl(ap->iobase + offset ) ; ++ ++ // Clear bit. ++ clear_bit(shift,&val) ; ++ if ( en_dis == 1 ) ++ set_bit(shift,&val); ++ ++ writel(val, (ap->iobase + offset )); ++} ++ ++ ++static void iproc_pwmc_set_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int wval) ++{ ++ unsigned int val = readl(ap->iobase + offset ) ; ++ ++ val = (val & ~mask) | ( wval << shift ) ; ++ writel(val, (ap->iobase + offset )); ++} ++ ++static void iproc_pwmc_get_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int *val) ++{ ++ *val = readl(ap->iobase + offset ) ; ++ *val = ( *val & mask ) >> shift ; ++} ++ ++ ++static void iproc_pwmc_start(const struct iproc_pwmc *ap, int chan) ++{ ++ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 1) ; ++} ++ ++static void iproc_pwmc_stop(const struct iproc_pwmc *ap, int chan) ++{ ++ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 0) ; ++ ++ ++} ++static void iproc_pwmc_config_polarity(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ struct pwm_device *p = ap->p[chan]; ++ ++ if ( c->polarity ){ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 1) ; ++ }else{ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 0) ; ++ } ++ p->polarity = c->polarity ? 1 : 0; ++ ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ ++} ++ ++ ++static void iproc_pwmc_config_duty_ticks(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ struct pwm_device *p = ap->p[chan]; ++ unsigned int pre_scaler = 0 ; ++ unsigned int duty_cnt = 0 ; ++ ++ iproc_pwmc_get_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, pwm_chan_pre_scaler_info[chan].shift, ++ &pre_scaler) ; ++ ++ /* Read prescaler value from register. */ ++ duty_cnt = c->duty_ticks / (pre_scaler + 1) ; ++ ++ /* program duty cycle. */ ++ iproc_pwmc_set_field(ap, pwm_chan_duty_cycle_info[chan].offset, ++ pwm_chan_duty_cycle_info[chan].mask, ++ pwm_chan_duty_cycle_info[chan].shift, duty_cnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ p->duty_ticks = c->duty_ticks; ++ ++} ++ ++static int iproc_pwmc_config_period_ticks(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ unsigned int pcnt ; ++ unsigned char pre_scaler = 0 ; ++ struct pwm_device *p = ap->p[chan]; ++ ++ pre_scaler = c->period_ticks / 0xFFFF ; ++ if ( pre_scaler > PWM_PRESCALER_MAX ) ++ pre_scaler = PWM_PRESCALER_MAX ; ++ ++ pcnt = c->period_ticks / (pre_scaler + 1) ; ++ ++ /* programe prescaler */ ++ iproc_pwmc_set_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, ++ pwm_chan_pre_scaler_info[chan].shift, pre_scaler) ; ++ ++ /* program period count. */ ++ iproc_pwmc_set_field(ap, pwm_chan_period_cnt_info[chan].offset, ++ pwm_chan_period_cnt_info[chan].mask, ++ pwm_chan_period_cnt_info[chan].shift, pcnt) ; ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ ++ p->period_ticks = c->period_ticks; ++ ++ return 0; ++} ++ ++static int iproc_pwmc_request(struct pwm_device *p) ++{ ++ struct iproc_pwmc *ap = pwm_get_drvdata(p); ++ int chan = iproc_get_chan(ap, p); ++ ++ /* 1M */ ++ p->tick_hz = 1000000UL; ++ iproc_pwmc_stop(ap,chan); ++ ++ return 0; ++} ++ ++static int iproc_pwmc_config(struct pwm_device *p, struct pwm_config *c) ++{ ++ struct iproc_pwmc *ap = pwm_get_drvdata(p); ++ int chan = iproc_get_chan(ap, p); ++ int ret; ++ ++ if (test_bit(PWM_CONFIG_PERIOD_TICKS, &c->config_mask)) { ++ ret = iproc_pwmc_config_period_ticks(ap, chan, c); ++ if (ret) ++ return ret; ++ if (!test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) { ++ struct pwm_config d = { ++ .config_mask = PWM_CONFIG_DUTY_TICKS, ++ .duty_ticks = p->duty_ticks, ++ }; ++ iproc_pwmc_config_duty_ticks(ap, chan, &d); ++ } ++ } ++ ++ if (test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) ++ iproc_pwmc_config_duty_ticks(ap, chan, c); ++ ++ if (test_bit(PWM_CONFIG_POLARITY, &c->config_mask)) ++ iproc_pwmc_config_polarity(ap, chan, c); ++ ++ if (test_bit(PWM_CONFIG_START, &c->config_mask)) ++ iproc_pwmc_start(ap, chan); ++ ++ if (test_bit(PWM_CONFIG_STOP, &c->config_mask)) ++ iproc_pwmc_stop(ap, chan); ++ ++ return 0; ++} ++ ++ ++static const struct pwm_device_ops iproc_pwm_ops = { ++ .request = iproc_pwmc_request, ++ .config = iproc_pwmc_config, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static int __devinit iproc_pwmc_probe(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ int chan; ++ int ret = 0; ++ ++ ap = kzalloc(sizeof(*ap), GFP_KERNEL); ++ if (!ap) { ++ ret = -ENOMEM; ++ goto err_iproc_pwmc_alloc; ++ } ++ ++ platform_set_drvdata(pdev, ap); ++ ++ ap->iobase = ioremap_nocache(r->start, resource_size(r)); ++ if (!ap->iobase) { ++ ret = -ENODEV; ++ goto err_ioremap; ++ } ++ printk(KERN_INFO "iproc_pwmc_probe iobase %p phys:%x\n", ++ ap->iobase,r->start); ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ ap->p[chan] = pwm_register(&iproc_pwm_ops, &pdev->dev, "%s:%d", ++ dev_name(&pdev->dev), chan); ++ if (IS_ERR_OR_NULL(ap->p[chan])) ++ goto err_pwm_register; ++ pwm_set_drvdata(ap->p[chan], ap); ++ } ++ ++ return 0; ++ ++err_pwm_register: ++ while (--chan > 0) ++ pwm_unregister(ap->p[chan]); ++ ++ iounmap(ap->iobase); ++err_ioremap: ++ platform_set_drvdata(pdev, NULL); ++ kfree(ap); ++err_iproc_pwmc_alloc: ++ printk(KERN_ERR "%s: error, returning %d\n", __func__, ret); ++return ret; ++} ++ ++static int __devexit iproc_pwmc_remove(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap = platform_get_drvdata(pdev); ++ int chan; ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) ++ pwm_unregister(ap->p[chan]); ++ ++ iounmap(ap->iobase); ++ ++ kfree(ap); ++ return 0; ++} ++ ++static struct platform_driver iproc_pwmc_driver = { ++ .driver = { ++ .name = "iproc_pwmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = iproc_pwmc_probe, ++ .remove = __devexit_p(iproc_pwmc_remove), ++}; ++ ++static int __init iproc_pwmc_init(void) ++{ ++ return platform_driver_register(&iproc_pwmc_driver); ++} ++ ++static void __exit iproc_pwmc_exit(void) ++{ ++ platform_driver_unregister(&iproc_pwmc_driver); ++} ++module_init(iproc_pwmc_init); ++module_exit(iproc_pwmc_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Driver for iProc PWMC"); ++MODULE_LICENSE("GPL"); ++ ++#endif +diff --git a/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c b/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c +new file mode 100644 +index 0000000..c410014 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch new file mode 100644 index 00000000..9ae130eb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch @@ -0,0 +1,581 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c +@@ -0,0 +1,575 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_DEBUG_FS ++#include ++#endif ++ ++#include ++ ++ ++#define IPROC_PWM_CHANNEL_CNT 4 ++#define PWM_PRESCALER_MAX 63 /* 6 bits field */ ++ ++ ++#define PWM_CTL_ENABLE_SHIFT (0) ++#define PWM_CTL_POLARITY_SHIFT (8) ++ ++#define PWM_PRESCALE_PWM3_PRESCALE_SHIFT (0) ++#define PWM_PRESCALE_PWM3_PRESCALE_MASK (0x0000003F) ++#define PWM_PRESCALE_PWM2_PRESCALE_SHIFT (6) ++#define PWM_PRESCALE_PWM2_PRESCALE_MASK (0x00000FC0) ++#define PWM_PRESCALE_PWM1_PRESCALE_SHIFT (12) ++#define PWM_PRESCALE_PWM1_PRESCALE_MASK (0x0003F000) ++#define PWM_PRESCALE_PWM0_PRESCALE_SHIFT (18) ++#define PWM_PRESCALE_PWM0_PRESCALE_MASK (0x00FC0000) ++ ++#define PWM_DUTY_HI_CNT0_SHIFT (0) ++#define PWM_DUTY_HI_CNT0_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT1_SHIFT (0) ++#define PWM_DUTY_HI_CNT1_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT2_SHIFT (0) ++#define PWM_DUTY_HI_CNT2_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT3_SHIFT (0) ++#define PWM_DUTY_HI_CNT3_MASK (0xFFFF) ++ ++#define PWM_PERIOD_CNT0_SHIFT (0) ++#define PWM_PERIOD_CNT0_MASK (0xFFFF) ++#define PWM_PERIOD_CNT1_SHIFT (0) ++#define PWM_PERIOD_CNT1_MASK (0xFFFF) ++#define PWM_PERIOD_CNT2_SHIFT (0) ++#define PWM_PERIOD_CNT2_MASK (0xFFFF) ++#define PWM_PERIOD_CNT3_SHIFT (0) ++#define PWM_PERIOD_CNT3_MASK (0xFFFF) ++ ++ ++struct pwm_reg_def { ++ u32 mask ; ++ u32 shift ; ++ u32 offset ; ++} ; ++ ++#define PWM_REG_DEF(c, m, s, a) \ ++ [c] = { \ ++ .mask = m, \ ++ .shift = s, \ ++ .offset = a \ ++ } ++ ++static const ++struct pwm_reg_def pwm_chan_pre_scaler_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PRESCALE_PWM0_PRESCALE_MASK, ++ PWM_PRESCALE_PWM0_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(1, PWM_PRESCALE_PWM1_PRESCALE_MASK, ++ PWM_PRESCALE_PWM1_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(2, PWM_PRESCALE_PWM2_PRESCALE_MASK, ++ PWM_PRESCALE_PWM2_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(3, PWM_PRESCALE_PWM3_PRESCALE_MASK, ++ PWM_PRESCALE_PWM3_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_period_cnt_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PERIOD_CNT0_MASK, ++ PWM_PERIOD_CNT0_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_PERIOD_CNT1_MASK, ++ PWM_PERIOD_CNT1_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_PERIOD_CNT2_MASK, ++ PWM_PERIOD_CNT2_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_PERIOD_CNT3_MASK, ++ PWM_PERIOD_CNT3_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT3_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_duty_cycle_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_DUTY_HI_CNT0_MASK, ++ PWM_DUTY_HI_CNT0_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_DUTY_HI_CNT1_MASK, ++ PWM_DUTY_HI_CNT1_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_DUTY_HI_CNT2_MASK, ++ PWM_DUTY_HI_CNT2_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_DUTY_HI_CNT3_MASK, ++ PWM_DUTY_HI_CNT3_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE), ++} ; ++ ++#ifdef CONFIG_DEBUG_FS ++struct iproc_pwm_config_debug_fs{ ++ struct dentry *period; ++ struct dentry *duty; ++ struct dentry *polarity; ++ struct dentry *run; ++}; ++#endif ++ ++struct iproc_pwm_config { ++ struct device *dev; ++ struct pwm_device *pwm; ++ int pwm_id; ++ int duty_ns; ++ int period_ns; ++ u32 duty_ticks; ++ u32 period_ticks; ++ u8 polarity; ++ int running; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs_entry; ++ struct iproc_pwm_config_debug_fs config_entry; ++#endif ++ ++}; ++ ++ ++struct iproc_pwmc { ++ void __iomem *iobase; ++ unsigned long tick_hz; ++ struct pwm_chip chip; ++ struct iproc_pwm_config *config[IPROC_PWM_CHANNEL_CNT]; ++}; ++ ++ ++#ifdef CONFIG_DEBUG_FS ++static int __init iproc_pwmc_debugfs_init(void); ++void iproc_pwmc_debugfs_add_chan(struct iproc_pwmc *ap, int chan); ++ ++static struct dentry *debugfs_base; ++ ++static int _debug_pwm_config_set(void *data, u64 val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ if (val) { ++ iproc_pwmc_config_polarity(config->pwm->chip, config->pwm, config->polarity); ++ pwm_config(config->pwm, config->duty_ns, config->period_ns); ++ pwm_enable(config->pwm); ++ config->running = 1; ++ } else { ++ pwm_disable(config->pwm); ++ config->running = 0; ++ } ++ return 0; ++} ++static int _debug_pwm_config_get(void *data, u64 *val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ *val = config->running; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(iproc_pwm_config_fop, _debug_pwm_config_get, ++ _debug_pwm_config_set, "%llu\n"); ++ ++static int _debug_pwm_export_set(void *data, u64 val) ++{ ++ ++ struct iproc_pwm_config *config = data; ++ struct pwm_device *pwm; ++ char pwm_id[16]; ++ ++ sprintf(pwm_id, "pwm-%d", config->pwm_id); ++ ++ if (val) { ++ pwm = pwm_get(config->dev,pwm_id); ++ config->pwm = pwm; ++ config->config_entry.polarity = debugfs_create_u8("polarity", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->polarity); ++ config->config_entry.period = debugfs_create_u32("period_ns", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->period_ns); ++ config->config_entry.duty = debugfs_create_u32("duty_ns", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->duty_ns); ++ config->config_entry.run = debugfs_create_file("run", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ data, &iproc_pwm_config_fop); ++ ++ } else { ++ debugfs_remove(config->config_entry.polarity); ++ debugfs_remove(config->config_entry.period); ++ debugfs_remove(config->config_entry.duty); ++ debugfs_remove(config->config_entry.run); ++ pwm_disable(config->pwm); ++ pwm_put(config->pwm); ++ config->pwm = NULL; ++ } ++ ++ return 0; ++} ++static int _debug_pwm_export_get(void *data, u64 *val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ if(config->pwm){ ++ *val = 1; ++ } else { ++ *val = 0; ++ } ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(iproc_pwm_export_fop, _debug_pwm_export_get, ++ _debug_pwm_export_set, "%llu\n"); ++ ++void iproc_pwmc_debugfs_add_chan(struct iproc_pwmc *ap, int chan) ++{ ++ char fname[16]; ++ ++ if (!debugfs_base) ++ return; ++ ++ ++ sprintf(fname, "iproc-pwm%d", chan); ++ ap->config[chan]->debugfs_entry = debugfs_create_dir(fname, debugfs_base); ++ ++ ++ debugfs_create_file("export", S_IRUGO | S_IWUSR, ap->config[chan]->debugfs_entry, ++ ap->config[chan], &iproc_pwm_export_fop); ++ ++} ++static int __init iproc_pwmc_debugfs_init(void) ++{ ++ ++ debugfs_base = debugfs_create_dir("iproc", NULL); ++ if (!debugfs_base) ++ return -ENOMEM; ++ ++ return 0; ++} ++#endif ++ ++ ++static int iproc_get_chan(const struct iproc_pwmc *ap, const struct pwm_device *p) ++{ ++ int chan; ++ ++ chan = p->hwpwm; ++ return chan; ++} ++ ++static void iproc_pwmc_clear_set_bit(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int shift, unsigned char en_dis) ++{ ++ unsigned long val = readl(ap->iobase + offset ) ; ++ ++ // Clear bit. ++ clear_bit(shift,&val) ; ++ if ( en_dis == 1 ) ++ set_bit(shift,&val); ++ ++ writel(val, (ap->iobase + offset )); ++} ++ ++ ++static void iproc_pwmc_set_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int wval) ++{ ++ unsigned int val = readl(ap->iobase + offset ) ; ++ ++ val = (val & ~mask) | ( wval << shift ) ; ++ writel(val, (ap->iobase + offset )); ++} ++ ++static void iproc_pwmc_get_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int *val) ++{ ++ *val = readl(ap->iobase + offset ) ; ++ *val = ( *val & mask ) >> shift ; ++} ++ ++ ++#define to_iproc_chip(chip) container_of(chip, struct iproc_pwmc, chip) ++static int iproc_pwmc_start(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, pwm); ++ ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 1) ; ++ ++ return 0; ++} ++ ++static void iproc_pwmc_stop(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, pwm); ++ ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 0) ; ++ ++} ++static int iproc_pwmc_request(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ iproc_pwmc_stop(chip, pwm); ++ return 0; ++} ++ ++static void iproc_pwmc_config_duty_ticks(struct iproc_pwmc *ap, int chan, ++ unsigned long duty_ticks) ++{ ++ /*struct pwm_device *p = ap->p[chan];*/ ++ unsigned int pre_scaler = 0 ; ++ unsigned int duty_cnt = 0 ; ++ ++ iproc_pwmc_get_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, pwm_chan_pre_scaler_info[chan].shift, ++ &pre_scaler) ; ++ ++ /* Read prescaler value from register. */ ++ duty_cnt = duty_ticks / (pre_scaler + 1) ; ++ ++ /* program duty cycle. */ ++ iproc_pwmc_set_field(ap, pwm_chan_duty_cycle_info[chan].offset, ++ pwm_chan_duty_cycle_info[chan].mask, ++ pwm_chan_duty_cycle_info[chan].shift, duty_cnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ++} ++ ++static int iproc_pwmc_config_period_ticks(struct iproc_pwmc *ap, int chan, ++ unsigned long period_ticks) ++{ ++ unsigned int pcnt ; ++ unsigned char pre_scaler = 0 ; ++ /*struct pwm_device *p = ap->p[chan]; */ ++ ++ pre_scaler = period_ticks / 0xFFFF ; ++ if ( pre_scaler > PWM_PRESCALER_MAX ) ++ pre_scaler = PWM_PRESCALER_MAX ; ++ ++ pcnt = period_ticks / (pre_scaler + 1) ; ++ ++ /* programe prescaler */ ++ iproc_pwmc_set_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, ++ pwm_chan_pre_scaler_info[chan].shift, pre_scaler) ; ++ ++ /* program period count. */ ++ iproc_pwmc_set_field(ap, pwm_chan_period_cnt_info[chan].offset, ++ pwm_chan_period_cnt_info[chan].mask, ++ pwm_chan_period_cnt_info[chan].shift, pcnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ++ return 0; ++} ++static unsigned long pwm_ns_to_ticks(struct iproc_pwmc *ap, unsigned long nsecs) ++{ ++ unsigned long long ticks; ++ ++ ticks = nsecs; ++ ticks *= ap->tick_hz; ++ do_div(ticks,1000000000UL); ++ ++ return ticks; ++} ++ ++int iproc_pwmc_config_polarity(struct pwm_chip *chip, ++ struct pwm_device *p, int polarity) ++{ ++ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, p); ++ ++ if (polarity) { ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 1) ; ++ } else { ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 0) ; ++ } ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ap->config[chan]->polarity = polarity; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(iproc_pwmc_config_polarity); ++ ++ ++static int iproc_pwmc_config(struct pwm_chip *chip, ++ struct pwm_device *p, int duty_ns, int period_ns) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, p); ++ int ret; ++ unsigned long period_ticks, duty_ticks; ++ ++ period_ticks = pwm_ns_to_ticks(ap, period_ns); ++ ret = iproc_pwmc_config_period_ticks(ap, chan, period_ticks); ++ if (ret) ++ return ret; ++ ap->config[chan]->period_ticks = period_ticks; ++ ap->config[chan]->period_ns = period_ns; ++ ++ duty_ticks = pwm_ns_to_ticks(ap, duty_ns); ++ iproc_pwmc_config_duty_ticks(ap, chan, duty_ticks); ++ ap->config[chan]->duty_ticks = duty_ticks; ++ ap->config[chan]->duty_ns = duty_ns; ++ ++ return 0; ++} ++ ++ ++static const struct pwm_ops iproc_pwm_ops = { ++ .enable = iproc_pwmc_start, ++ .disable = iproc_pwmc_stop, ++ .request = iproc_pwmc_request, ++ .free = iproc_pwmc_stop, ++ .config = iproc_pwmc_config, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static int __devinit iproc_pwmc_probe(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ struct resource *r; ++ int ret = 0; ++ int chan; ++ ++ ap = devm_kzalloc(&pdev->dev, sizeof(*ap), GFP_KERNEL); ++ if (!ap) { ++ dev_err(&pdev->dev, "failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++#ifdef CONFIG_MACH_NSP ++ ap->tick_hz = 25000000UL; ++#else ++ ap->tick_hz = 1000000UL; ++#endif ++ ap->chip.ops = &iproc_pwm_ops; ++ ap->chip.dev = &pdev->dev; ++ ap->chip.base = -1; ++ ap->chip.npwm = IPROC_PWM_CHANNEL_CNT; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ dev_err(&pdev->dev, "no memory resource defined\n"); ++ return -ENODEV; ++ } ++ ++ ap->iobase = devm_request_and_ioremap(&pdev->dev, r); ++ if (!ap->iobase) { ++ return -EADDRNOTAVAIL; ++ } ++ printk(KERN_INFO "iproc_pwmc_probe iobase %p phys:%x\n", ++ ap->iobase,r->start); ++ ret = pwmchip_add(&ap->chip); ++ if (ret < 0) ++ return ret; ++ ++ platform_set_drvdata(pdev, ap); ++ ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ ap->config[chan] = kzalloc(sizeof(struct iproc_pwm_config), GFP_KERNEL); ++ ap->config[chan]->pwm_id = chan; ++ ap->config[chan]->dev = &pdev->dev; ++ } ++ ++ ++#ifdef CONFIG_DEBUG_FS ++ iproc_pwmc_debugfs_init(); ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ iproc_pwmc_debugfs_add_chan(ap,chan); ++ } ++#endif ++ ++ return 0; ++ ++} ++ ++static int __devexit iproc_pwmc_remove(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ int chan; ++ ++ ap = platform_get_drvdata(pdev); ++ ++#ifdef CONFIG_DEBUG_FS ++ if (debugfs_base) ++ debugfs_remove_recursive(debugfs_base); ++ ++#endif ++ ++ if (ap == NULL) ++ return -ENODEV; ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++){ ++ kfree(ap->config[chan]); ++ } ++ pwmchip_remove(&ap->chip); ++ ++ devm_iounmap(&pdev->dev,ap->iobase); ++ kfree(ap); ++ ++ return 0; ++} ++ ++static struct platform_driver iproc_pwmc_driver = { ++ .driver = { ++ .name = "iproc_pwmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = iproc_pwmc_probe, ++ .remove = __devexit_p(iproc_pwmc_remove), ++}; ++ ++static int __init iproc_pwmc_init(void) ++{ ++ return platform_driver_register(&iproc_pwmc_driver); ++} ++ ++static void __exit iproc_pwmc_exit(void) ++{ ++ platform_driver_unregister(&iproc_pwmc_driver); ++} ++module_init(iproc_pwmc_init); ++module_exit(iproc_pwmc_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Driver for iProc PWMC"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/qspi/.gitignore b/drivers/bcmdrivers/qspi/.gitignore +new file mode 100644 +index 0000000..d03ee50 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch new file mode 100644 index 00000000..d119602b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_.gitignore.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order ++/.iproc_qspi.o.cmd ++/.qspi_iproc.o.cmd ++/iproc_qspi.o ++/qspi_iproc.o +diff --git a/drivers/bcmdrivers/qspi/Kconfig b/drivers/bcmdrivers/qspi/Kconfig +new file mode 100644 +index 0000000..fac545c diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch new file mode 100644 index 00000000..f5204dc9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Kconfig.patch @@ -0,0 +1,78 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/Kconfig +@@ -0,0 +1,72 @@ ++menuconfig IPROC_QSPI ++ tristate "QSPI support" ++ depends on ARCH_IPROC ++ select SPI ++ select SPI_MASTER ++ select MTD ++ select MTD_M25P80 ++ select M25PXX_USE_FAST_READ ++ default n ++ help ++ This selects a driver for the iProc QSPI Controller (for serial flash). ++ ++ If unsure, say N. ++ ++if IPROC_QSPI ++ ++choice ++ prompt "Multi I/O SPI support" ++ default IPROC_QSPI_SINGLE_MODE ++ help ++ Number of (multi I/O) data lanes supported by the SPI flash. ++ ++config IPROC_QSPI_SINGLE_MODE ++ bool "Single lane" ++ help ++ Single lane. ++ ++config IPROC_QSPI_DUAL_MODE ++ bool "Dual mode" ++ help ++ Dual mode. ++ ++config IPROC_QSPI_QUAD_MODE ++ bool "Quad mode" ++ help ++ Quad mode. ++ ++endchoice ++ ++config IPROC_QSPI_MULTI_LANE_ADDR ++ bool "Use multi lanes also for address" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ default y ++ help ++ Use multi lanes also for address. ++ ++config IPROC_QSPI_READ_CMD ++ hex "Flash opcode for multi I/O read" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ range 0x00 0xff ++ default 0xbb if IPROC_QSPI_DUAL_MODE ++ default 0xeb ++ help ++ Flash opcode to send to flash for multip I/O read. ++ ++config IPROC_QSPI_READ_DUMMY_CYCLES ++ int "Dummy cycles for multi I/O read operation" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ range 0 255 ++ default 8 if IPROC_QSPI_DUAL_MODE ++ default 10 ++ help ++ Dummy cycles for flash read operation ++ ++config IPROC_QSPI_MAX_HZ ++ int "Maximal SPI clock in HZ" ++ range 1 1000000000 ++ default 62500000 ++ help ++ The maximal SPI clock (in Hz) supported by the flash. ++ ++endif # IPROC_QSPI +diff --git a/drivers/bcmdrivers/qspi/Makefile b/drivers/bcmdrivers/qspi/Makefile +new file mode 100644 +index 0000000..be164d1 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch new file mode 100644 index 00000000..90266a9c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o ++iproc_qspi-objs := qspi_iproc.o +diff --git a/drivers/bcmdrivers/qspi/qspi_iproc.c b/drivers/bcmdrivers/qspi/qspi_iproc.c +new file mode 100755 +index 0000000..2643787 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch new file mode 100644 index 00000000..dfa76075 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_qspi_qspi_iproc.c.patch @@ -0,0 +1,1813 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/qspi_iproc.c +@@ -0,0 +1,1807 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DBG(...) /* */ ++ ++/* ++ * Interrupts ++ */ ++ ++#define QSPI_INTR_COUNT (7) ++ ++#define QSPI_INTR_MSPI_HALTED_MASK (0x00000040) ++#define QSPI_INTR_MSPI_DONE_MASK (0x00000020) ++#define QSPI_INTR_BSPI_LR_OVERREAD_MASK (0x00000010) ++#define QSPI_INTR_BSPI_LR_SESSION_DONE_MASK (0x00000008) ++#define QSPI_INTR_BSPI_LR_IMPATIENT_MASK (0x00000004) ++#define QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK (0x00000002) ++#define QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK (0x00000001) ++ ++#define BSPI_LR_INTERRUPTS_DATA \ ++ (QSPI_INTR_BSPI_LR_SESSION_DONE_MASK | \ ++ QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK) ++ ++#define BSPI_LR_INTERRUPTS_ERROR \ ++ (QSPI_INTR_BSPI_LR_OVERREAD_MASK | \ ++ QSPI_INTR_BSPI_LR_IMPATIENT_MASK | \ ++ QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK) ++ ++#define BSPI_LR_INTERRUPTS_ALL \ ++ (BSPI_LR_INTERRUPTS_ERROR | \ ++ BSPI_LR_INTERRUPTS_DATA) ++ ++#define SPBR_MIN 8U ++#define SPBR_MAX 255U ++#define DEFAULT_SPEED_HZ 25000000UL ++#define MSPI_REFCLK_SOURCE "c_clk125" /* To be doubled */ ++#define MSPI_REFCLK_SOURCE_DEVID "iproc_slow" ++ ++/* ++ * Flash opcode and parameters ++ */ ++#define OPCODE_RDID 0x9f ++#define OPCODE_WREN 0x06 ++#define OPCODE_WRDI 0x04 ++#define OPCODE_WRR 0x01 ++#define OPCODE_RCR 0x35 ++#define OPCODE_READ 0x03 ++#define OPCODE_RDSR 0x05 ++#define OPCODE_WRSR 0x01 ++#define OPCODE_RDFSR 0x70 ++#define OPCODE_FAST_READ 0x0B ++#define OPCODE_FAST_READ_4B 0x0C ++#define OPCODE_EN4B 0xB7 ++#define OPCODE_EX4B 0xE9 ++#define OPCODE_BRWR 0x17 ++ ++#define BSPI_WIDTH_1BIT 1 ++#define BSPI_WIDTH_2BIT 2 ++#define BSPI_WIDTH_4BIT 4 ++ ++#define BSPI_ADDRLEN_3BYTES 3 ++#define BSPI_ADDRLEN_4BYTES 4 ++ ++#define BSPI_FLASH_TYPE_SPANSION 0 ++#define BSPI_FLASH_TYPE_MACRONIX 1 ++#define BSPI_FLASH_TYPE_NUMONYX 2 ++#define BSPI_FLASH_TYPE_SST 3 ++#define BSPI_FLASH_TYPE_UNKNOWN -1 ++ ++/* ++ * Register masks/fields/values ++ */ ++#define QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK (0x00000002) ++#define QSPI_BSPI_RAF_CONTROL_START_MASK (0x00000001) ++#define QSPI_BSPI_RAF_CONTROL_CLEAR_MASK (0x00000002) ++#define QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK (0x00010000) ++#define QSPI_BSPI_BPP_MODE_BPP_MASK (0x00000100) ++#define QSPI_BSPI_FLEX_MODE_ENABLE_MASK (0x00000001) ++ ++ ++/* ++ * Module parameters ++ */ ++ ++/* Mulit I/O for read: 0 - single, 1 - dual, 2 - quad */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int io_mode = 0; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++#ifdef CONFIG_IPROC_QSPI_DUAL_MODE ++static int io_mode = 1; ++#else /* !CONFIG_IPROC_QSPI_DUAL_MODE */ ++static int io_mode = 2; ++#endif /* !CONFIG_IPROC_QSPI_DUAL_MODE */ ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(io_mode, int, 0444); ++ ++/* Multi I/O for address (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_MULTI_LANE_ADDR ++static int addr_multi = 1; ++#else /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ ++static int addr_multi = 0; ++#endif /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ ++module_param(addr_multi, int, 0444); ++ ++/* Read opcode (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int read_opcode = OPCODE_FAST_READ; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++static int read_opcode = CONFIG_IPROC_QSPI_READ_CMD; ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(read_opcode, int, 0444); ++ ++/* Dummy cycles for read (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int dummy_cycles = 8; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++static int dummy_cycles = CONFIG_IPROC_QSPI_READ_DUMMY_CYCLES; ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(dummy_cycles, int, 0444); ++ ++/* Max SPI clock HZ */ ++static int max_hz = 0; ++module_param(max_hz, int, 0444); ++ ++/* Spansion high performance mode */ ++static int bspi_hp; ++module_param(bspi_hp, int, 0444); ++ ++struct bcmspi_parms { ++ u32 speed_hz; ++ u8 chip_select; ++ u8 mode; ++ u8 bits_per_word; ++}; ++ ++struct position { ++ struct spi_message *msg; ++ struct spi_transfer *trans; ++ int byte; ++ int mspi_16bit; ++}; ++ ++#define NUM_TXRAM 32 ++#define NUM_RXRAM 32 ++#define NUM_CDRAM 16 ++ ++struct bcm_mspi_hw { ++ u32 spcr0_lsb; /* 0x000 */ ++ u32 spcr0_msb; /* 0x004 */ ++ u32 spcr1_lsb; /* 0x008 */ ++ u32 spcr1_msb; /* 0x00c */ ++ u32 newqp; /* 0x010 */ ++ u32 endqp; /* 0x014 */ ++ u32 spcr2; /* 0x018 */ ++ u32 reserved0; /* 0x01c */ ++ u32 mspi_status; /* 0x020 */ ++ u32 cptqp; /* 0x024 */ ++ u32 reserved1[6]; /* 0x028 */ ++ u32 txram[NUM_TXRAM]; /* 0x040 */ ++ u32 rxram[NUM_RXRAM]; /* 0x0c0 */ ++ u32 cdram[NUM_CDRAM]; /* 0x140 */ ++ u32 write_lock; /* 0x180 */ ++ u32 disable_flush_gen; /* 0x184 */ ++}; ++ ++struct bcm_bspi_hw { ++ u32 revision_id; /* 0x000 */ ++ u32 scratch; /* 0x004 */ ++ u32 mast_n_boot_ctrl; /* 0x008 */ ++ u32 busy_status; /* 0x00c */ ++ u32 intr_status; /* 0x010 */ ++ u32 b0_status; /* 0x014 */ ++ u32 b0_ctrl; /* 0x018 */ ++ u32 b1_status; /* 0x01c */ ++ u32 b1_ctrl; /* 0x020 */ ++ u32 strap_override_ctrl; /* 0x024 */ ++ u32 flex_mode_enable; /* 0x028 */ ++ u32 bits_per_cycle; /* 0x02C */ ++ u32 bits_per_phase; /* 0x030 */ ++ u32 cmd_and_mode_byte; /* 0x034 */ ++ u32 flash_upper_addr_byte; /* 0x038 */ ++ u32 xor_value; /* 0x03C */ ++ u32 xor_enable; /* 0x040 */ ++ u32 pio_mode_enable; /* 0x044 */ ++ u32 pio_iodir; /* 0x048 */ ++ u32 pio_data; /* 0x04C */ ++}; ++ ++struct bcm_bspi_raf { ++ u32 start_address; /* 0x00 */ ++ u32 num_words; /* 0x04 */ ++ u32 ctrl; /* 0x08 */ ++ u32 fullness; /* 0x0C */ ++ u32 watermark; /* 0x10 */ ++ u32 status; /* 0x14 */ ++ u32 read_data; /* 0x18 */ ++ u32 word_cnt; /* 0x1C */ ++ u32 curr_addr; /* 0x20 */ ++}; ++ ++struct bcm_idm_qspi_ctrl { ++ u32 io_ctrl_direct; ++}; ++ ++struct bcm_cru_control { ++ u32 cru_control; ++}; ++ ++struct bcm_flex_mode { ++ int width; ++ int addrlen; ++ int hp; ++}; ++ ++#define STATE_IDLE 0 ++#define STATE_RUNNING 1 ++#define STATE_SHUTDOWN 2 ++ ++struct bcmspi_priv { ++ struct platform_device *pdev; ++ struct spi_master *master; ++ spinlock_t lock; ++ struct bcmspi_parms last_parms; ++ struct position pos; ++ struct list_head msg_queue; ++ int state; ++ int outstanding_bytes; ++ int next_udelay; ++ int cs_change; ++ unsigned int mspi_refclk; ++ unsigned int max_speed_hz; ++ volatile struct bcm_mspi_hw *mspi_hw; ++ int irq; ++ struct tasklet_struct tasklet; ++ int curr_cs; ++ ++ /* BSPI */ ++ volatile struct bcm_bspi_hw *bspi_hw; ++ volatile struct bcm_cru_control *cru_hw; ++ int bspi_enabled; ++ /* all chip selects controlled by BSPI */ ++ int bspi_chip_select; ++ ++ /* LR */ ++ volatile struct bcm_bspi_raf *bspi_hw_raf; ++ struct spi_transfer *cur_xfer; ++ u32 cur_xfer_idx; ++ u32 cur_xfer_len; ++ u32 xfer_status; ++ struct spi_message *cur_msg; ++ u32 actual_length; ++ u32 raf_next_addr; ++ u32 raf_next_len; ++ ++ /* Interrupts */ ++ volatile u32 *qspi_intr; ++ volatile struct bcm_idm_qspi_ctrl *idm_qspi; ++ ++ /* current flex mode settings */ ++ struct bcm_flex_mode flex_mode; ++}; ++ ++static void bcmspi_enable_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ priv->idm_qspi->io_ctrl_direct |= cpu_to_le32(mask << 2); ++} ++ ++static void bcmspi_disable_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ priv->idm_qspi->io_ctrl_direct &= cpu_to_le32(~(mask << 2)); ++} ++ ++static void bcmspi_clear_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ int i; ++ ++ for(i=0; iqspi_intr[i] = cpu_to_le32(1); ++ } ++ } ++} ++ ++static u32 bcmspi_read_interrupt(struct bcmspi_priv *priv) ++{ ++ int i; ++ u32 status = 0; ++ ++ for(i=0; iqspi_intr[i] & cpu_to_le32(1)) { ++ status |= 1UL << i; ++ } ++ } ++ ++ return status; ++} ++ ++static void bcmspi_flush_prefetch_buffers(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw->b0_ctrl = 0; ++ priv->bspi_hw->b1_ctrl = 0; ++ priv->bspi_hw->b0_ctrl = cpu_to_le32(1); ++ priv->bspi_hw->b1_ctrl = cpu_to_le32(1); ++} ++ ++static int bcmspi_lr_is_fifo_empty(struct bcmspi_priv *priv) ++{ ++ return priv->bspi_hw_raf->status & cpu_to_le32(QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK); ++} ++ ++static inline u32 bcmspi_lr_read_fifo(struct bcmspi_priv *priv) ++{ ++ /* for performance reasons return the raw data, rather than ++ * byte-swapped data. This works because the caller writes ++ * values 32-bits at a time to the destination buffer, giving ++ * an automatic byte-swap on big-endian machines. */ ++ ++ return priv->bspi_hw_raf->read_data; ++} ++ ++static inline void bcmspi_lr_start(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_START_MASK); ++} ++ ++static inline void bcmspi_lr_clear(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_CLEAR_MASK); ++ bcmspi_flush_prefetch_buffers(priv); ++} ++ ++static inline int bcmspi_is_4_byte_mode(struct bcmspi_priv *priv) ++{ ++ return priv->flex_mode.addrlen == BSPI_ADDRLEN_4BYTES; ++} ++ ++static int bcmbspi_flash_type(struct bcmspi_priv *priv); ++ ++static int bcmspi_set_flex_mode(struct bcmspi_priv *priv, ++ int width, int addrlen, int hp) ++{ ++ int bpc = 0, bpp = dummy_cycles, command = read_opcode; ++ int flex_mode = 1, error = 0; ++ ++ switch (width) { ++ case BSPI_WIDTH_1BIT: ++ if (addrlen == BSPI_ADDRLEN_3BYTES) { ++ /* default mode, does not need flex_cmd */ ++ flex_mode = 0; ++ } else { ++ bpp = 8; /* dummy cycles */ ++ if (bcmbspi_flash_type(priv) == BSPI_FLASH_TYPE_SPANSION) ++ command = OPCODE_FAST_READ_4B; ++ else ++ command = OPCODE_FAST_READ; ++ } ++ break; ++ case BSPI_WIDTH_2BIT: ++ bpc = 0x00000001; /* only data is 2-bit */ ++ if (addr_multi) { ++ bpc |= 0x00010000; ++ } ++ if (hp) { ++ bpc |= 0x00010100; /* address and mode are 2-bit too */ ++ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; ++ } ++ break; ++ case BSPI_WIDTH_4BIT: ++ bpc = 0x00000002; /* only data is 4-bit */ ++ if (addr_multi) { ++ bpc |= 0x00020000; ++ } ++ if (hp) { ++ bpc |= 0x00020200; /* address and mode are 4-bit too */ ++ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; ++ } ++ break; ++ default: ++ error = 1; ++ break; ++ } ++ ++ if (addrlen == BSPI_ADDRLEN_4BYTES) { ++ bpp |= QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK; ++ } ++ ++ if (!error) { ++ priv->bspi_hw->flex_mode_enable = 0; ++ priv->bspi_hw->bits_per_cycle = cpu_to_le32(bpc); ++ priv->bspi_hw->bits_per_phase = cpu_to_le32(bpp); ++ priv->bspi_hw->cmd_and_mode_byte = cpu_to_le32(command); ++ priv->bspi_hw->flex_mode_enable = flex_mode ? ++ cpu_to_le32(QSPI_BSPI_FLEX_MODE_ENABLE_MASK) ++ : 0; ++ DBG("%s: width=%d addrlen=%d hp=%d\n", ++ __func__, width, addrlen, hp); ++ DBG("%s: fme=%08x bpc=%08x bpp=%08x cmd=%08x\n", __func__, ++ le32_to_cpu(priv->bspi_hw->flex_mode_enable), ++ le32_to_cpu(priv->bspi_hw->bits_per_cycle), ++ le32_to_cpu(priv->bspi_hw->bits_per_phase), ++ le32_to_cpu(priv->bspi_hw->cmd_and_mode_byte)); ++ } ++ ++ return error; ++} ++ ++static void bcmspi_set_mode(struct bcmspi_priv *priv, ++ int width, int addrlen, int hp) ++{ ++ int error = 0; ++ int show_info = 0; ++ ++ if (width != -1 || hp != -1) { ++ /* Don't print things if only for address mode change because it ++ * could be very frequent. */ ++ show_info = 1; ++ } ++ if (width == -1) ++ width = priv->flex_mode.width; ++ if (addrlen == -1) ++ addrlen = priv->flex_mode.addrlen; ++ if (hp == -1) ++ hp = priv->flex_mode.hp; ++ ++ error = bcmspi_set_flex_mode(priv, width, addrlen, hp); ++ ++ if (!error) { ++ priv->flex_mode.width = width; ++ priv->flex_mode.addrlen = addrlen; ++ priv->flex_mode.hp = hp; ++ if (show_info) { ++ dev_info(&priv->pdev->dev, ++ "%d-lane output, %d-byte address%s\n", ++ priv->flex_mode.width, ++ priv->flex_mode.addrlen, ++ priv->flex_mode.hp ? ", high-performance mode" : ""); ++ } ++ } else ++ dev_warn(&priv->pdev->dev, ++ "INVALID COMBINATION: width=%d addrlen=%d hp=%d\n", ++ width, addrlen, hp); ++} ++ ++static void bcmspi_set_chip_select(struct bcmspi_priv *priv, int cs) ++{ ++ if (priv->curr_cs != cs) { ++ DBG("Switching CS%1d => CS%1d\n", ++ priv->curr_cs, cs); ++ ++ /* We don't have multiple chip selects for now */ ++ } ++ priv->curr_cs = cs; ++ ++} ++ ++static inline int is_bspi_chip_select(struct bcmspi_priv *priv, u8 cs) ++{ ++ return priv->bspi_chip_select & (1 << cs); ++} ++ ++static void bcmspi_disable_bspi(struct bcmspi_priv *priv) ++{ ++ int i; ++ ++ if (!priv->bspi_hw || !priv->bspi_enabled) ++ return; ++ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 1) { ++ priv->bspi_enabled = 0; ++ return; ++ } ++ ++ DBG("disabling bspi\n"); ++ for (i = 0; i < 1000; i++) { ++ if ((priv->bspi_hw->busy_status & cpu_to_le32(1)) == 0) { ++ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); ++ priv->bspi_enabled = 0; ++ udelay(1); ++ return; ++ } ++ udelay(1); ++ } ++ dev_warn(&priv->pdev->dev, "timeout setting MSPI mode\n"); ++} ++ ++static void bcmspi_enable_bspi(struct bcmspi_priv *priv) ++{ ++ if (!priv->bspi_hw || priv->bspi_enabled) ++ return; ++ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 0) { ++ priv->bspi_enabled = 1; ++ return; ++ } ++ ++ DBG("enabling bspi\n"); ++ priv->bspi_hw->mast_n_boot_ctrl = 0; ++ priv->bspi_enabled = 1; ++} ++ ++static void bcmspi_hw_set_parms(struct bcmspi_priv *priv, ++ const struct bcmspi_parms *xp) ++{ ++ if (xp->speed_hz) { ++ unsigned int spbr = priv->mspi_refclk / (2 * xp->speed_hz); ++ ++ priv->mspi_hw->spcr0_lsb = cpu_to_le32(max(min(spbr, SPBR_MAX), SPBR_MIN)); ++ } else { ++ priv->mspi_hw->spcr0_lsb = cpu_to_le32(SPBR_MIN); ++ } ++ ++ if (priv->pos.msg == NULL || xp->bits_per_word > 8) { ++ /* Global hw init or 16bit spi_transfer */ ++ int bits = xp->bits_per_word; ++ bits = bits? (bits == 16? 0 : bits) : 8; ++ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ ++ (bits << 2) | ++ (xp->mode & 3)); ++ } else { ++ /* Configure for a new 8-bit spi_transfer */ ++ if (priv->pos.byte == 0) { ++ /* Use 16-bit MSPI transfer for performance if applicable */ ++ if (priv->pos.mspi_16bit ^ (!(priv->pos.trans->len & 1))) { ++ /* Update it only if needed */ ++ priv->pos.mspi_16bit = !priv->pos.mspi_16bit; ++ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ ++ ((priv->pos.mspi_16bit? 0 : 8) << 2) | ++ (xp->mode & 3)); ++ } ++ } ++ } ++ priv->last_parms = *xp; ++} ++ ++#define PARMS_NO_OVERRIDE 0 ++#define PARMS_OVERRIDE 1 ++ ++static int bcmspi_update_parms(struct bcmspi_priv *priv, ++ struct spi_device *spidev, struct spi_transfer *trans, int override) ++{ ++ struct bcmspi_parms xp; ++ ++ xp.speed_hz = min(trans->speed_hz ? trans->speed_hz : ++ (spidev->max_speed_hz ? spidev->max_speed_hz : DEFAULT_SPEED_HZ), ++ DEFAULT_SPEED_HZ); ++ xp.chip_select = spidev->chip_select; ++ xp.mode = spidev->mode; ++ xp.bits_per_word = trans->bits_per_word ? trans->bits_per_word : ++ (spidev->bits_per_word ? spidev->bits_per_word : 8); ++ ++ if ((override == PARMS_OVERRIDE) || ++ ((xp.speed_hz == priv->last_parms.speed_hz) && ++ (xp.chip_select == priv->last_parms.chip_select) && ++ (xp.mode == priv->last_parms.mode) && ++ (xp.bits_per_word == priv->last_parms.bits_per_word))) { ++ bcmspi_hw_set_parms(priv, &xp); ++ return 0; ++ } ++ /* no override, and parms do not match */ ++ return 1; ++} ++ ++ ++static int bcmspi_setup(struct spi_device *spi) ++{ ++ struct bcmspi_parms *xp; ++ struct bcmspi_priv *priv = spi_master_get_devdata(spi->master); ++ unsigned int speed_hz; ++ ++ DBG("%s\n", __func__); ++ ++ if (spi->bits_per_word > 16) ++ return -EINVAL; ++ ++ /* Module parameter override */ ++ if (max_hz != 0) { ++ speed_hz = max_hz; ++ } else { ++ speed_hz = spi->max_speed_hz; ++ } ++ ++ xp = spi_get_ctldata(spi); ++ if (!xp) { ++ xp = kzalloc(sizeof(struct bcmspi_parms), GFP_KERNEL); ++ if (!xp) ++ return -ENOMEM; ++ spi_set_ctldata(spi, xp); ++ } ++ if (speed_hz < priv->max_speed_hz) ++ xp->speed_hz = speed_hz; ++ else ++ xp->speed_hz = 0; ++ ++ priv->cru_hw->cru_control &= cpu_to_le32(~0x00000006); ++ (void)priv->cru_hw->cru_control; /* Need to read back */ ++ if (speed_hz >= 62500000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000006); ++ } else if (speed_hz >= 50000000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000002); ++ } else if (speed_hz >= 31250000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000004); ++ } ++ (void)priv->cru_hw->cru_control; /* Need to read back */ ++ ++ xp->chip_select = spi->chip_select; ++ xp->mode = spi->mode; ++ xp->bits_per_word = spi->bits_per_word ? spi->bits_per_word : 8; ++ ++ return 0; ++} ++ ++/* stop at end of transfer, no other reason */ ++#define FNB_BREAK_NONE 0 ++/* stop at end of spi_message */ ++#define FNB_BREAK_EOM 1 ++/* stop at end of spi_transfer if delay */ ++#define FNB_BREAK_DELAY 2 ++/* stop at end of spi_transfer if cs_change */ ++#define FNB_BREAK_CS_CHANGE 4 ++/* stop if we run out of bytes */ ++#define FNB_BREAK_NO_BYTES 8 ++/* stop at end of spi_transfer */ ++#define FNB_BREAK_EOT 16 ++ ++/* events that make us stop filling TX slots */ ++#define FNB_BREAK_TX (FNB_BREAK_EOM | FNB_BREAK_DELAY | \ ++ FNB_BREAK_CS_CHANGE) ++ ++/* events that make us deassert CS */ ++#define FNB_BREAK_DESELECT (FNB_BREAK_EOM | FNB_BREAK_CS_CHANGE) ++ ++ ++static int find_next_byte(struct bcmspi_priv *priv, struct position *p, ++ struct list_head *completed, int flags) ++{ ++ int ret = FNB_BREAK_NONE; ++ ++ p->byte++; ++ ++ while (p->byte >= p->trans->len) { ++ /* we're at the end of the spi_transfer */ ++ ++ /* in TX mode, need to pause for a delay or CS change */ ++ if (p->trans->delay_usecs && (flags & FNB_BREAK_DELAY)) ++ ret |= FNB_BREAK_DELAY; ++ if (p->trans->cs_change && (flags & FNB_BREAK_CS_CHANGE)) ++ ret |= FNB_BREAK_CS_CHANGE; ++ if (ret) ++ return ret; ++ ++ /* advance to next spi_message? */ ++ if (list_is_last(&p->trans->transfer_list, ++ &p->msg->transfers)) { ++ struct spi_message *next_msg = NULL; ++ ++ /* TX breaks at the end of each message as well */ ++ if (!completed || (flags & FNB_BREAK_EOM)) { ++ DBG("find_next_byte: advance msg exit\n"); ++ return FNB_BREAK_EOM; ++ } ++ if (!list_is_last(&p->msg->queue, &priv->msg_queue)) { ++ next_msg = list_entry(p->msg->queue.next, ++ struct spi_message, queue); ++ } ++ /* delete from run queue, add to completion queue */ ++ list_del(&p->msg->queue); ++ list_add_tail(&p->msg->queue, completed); ++ ++ p->msg = next_msg; ++ p->byte = 0; ++ if (p->msg == NULL) { ++ p->trans = NULL; ++ ret = FNB_BREAK_NO_BYTES; ++ break; ++ } ++ ++ /* ++ * move on to the first spi_transfer of the new ++ * spi_message ++ */ ++ p->trans = list_entry(p->msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ } else { ++ /* or just advance to the next spi_transfer */ ++ p->trans = list_entry(p->trans->transfer_list.next, ++ struct spi_transfer, transfer_list); ++ p->byte = 0; ++ ++ /* Separate spi_transfers into MSPI transfers */ ++ ret = FNB_BREAK_EOT; ++ } ++ } ++ DBG("find_next_byte: msg %p trans %p len %d byte %d ret %x\n", ++ p->msg, p->trans, p->trans ? p->trans->len : 0, p->byte, ret); ++ return ret; ++} ++ ++static void read_from_hw(struct bcmspi_priv *priv, struct list_head *completed) ++{ ++ struct position p; ++ int slot = 0, n = priv->outstanding_bytes; ++ ++ DBG("%s\n", __func__); ++ ++ p = priv->pos; ++ ++ while (n > 0) { ++ BUG_ON(p.msg == NULL); ++ ++ if (p.trans->bits_per_word <= 8) { ++ u8 *buf = p.trans->rx_buf; ++ ++ if (buf) { ++ ++ if (p.mspi_16bit) { ++ /* Using 16-bit SPI transfers for performance */ ++ buf[p.byte] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); ++ buf[p.byte + 1] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte + 1] : 0xff); ++ } else { ++ buf[p.byte] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); ++ } ++ } ++ } else { ++ u16 *buf = p.trans->rx_buf; ++ ++ if (buf) { ++ buf[p.byte] = ++ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff) << 0) | ++ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0] & 0xff)) << 8); ++ DBG("RD %04x\n", buf ? buf[p.byte] : 0xffff); ++ } ++ } ++ slot++; ++ n--; ++ p.msg->actual_length++; ++ if (p.mspi_16bit) { ++ p.byte++; ++ p.msg->actual_length++; ++ } ++ ++ find_next_byte(priv, &p, completed, FNB_BREAK_NONE); ++ } ++ ++ priv->pos = p; ++ priv->outstanding_bytes = 0; ++} ++ ++static void write_to_hw(struct bcmspi_priv *priv) ++{ ++ struct position p; ++ int slot = 0, fnb = 0; ++ struct spi_message *msg = NULL; ++ ++ DBG("%s\n", __func__); ++ ++ bcmspi_disable_bspi(priv); ++ ++ p = priv->pos; ++ ++ while (1) { ++ if (p.msg == NULL) ++ break; ++ if (!msg) { ++ msg = p.msg; ++ bcmspi_update_parms(priv, msg->spi, p.trans, ++ PARMS_OVERRIDE); ++ } else { ++ /* break if the speed, bits, etc. changed */ ++ if (bcmspi_update_parms(priv, msg->spi, p.trans, ++ PARMS_NO_OVERRIDE)) { ++ DBG("parms don't match, breaking\n"); ++ break; ++ } ++ } ++ if (p.trans->bits_per_word <= 8) { ++ const u8 *buf = p.trans->tx_buf; ++ ++ priv->mspi_hw->txram[slot << 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); ++ ++ if (priv->pos.mspi_16bit) { ++ /* Using 16-bit SPI transfers for performance */ ++ p.byte++; ++ priv->mspi_hw->txram[(slot << 1) + 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); ++ } else { ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0x8e); ++ } ++ ++ } else { ++ const u16 *buf = p.trans->tx_buf; ++ ++ priv->mspi_hw->txram[(slot << 1) + 0] = cpu_to_le32(buf ? ++ (buf[p.byte] >> 8) : 0xff); ++ priv->mspi_hw->txram[(slot << 1) + 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %04x\n", buf ? buf[p.byte] : 0xffff); ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); ++ } ++ slot++; ++ ++ fnb = find_next_byte(priv, &p, NULL, FNB_BREAK_TX); ++ ++ if (fnb & FNB_BREAK_CS_CHANGE) ++ priv->cs_change = 1; ++ if (fnb & FNB_BREAK_DELAY) ++ priv->next_udelay = p.trans->delay_usecs; ++ if (fnb || (slot == NUM_CDRAM)) ++ break; ++ } ++ ++ if (slot) { ++ DBG("submitting %d slots\n", slot); ++ priv->mspi_hw->newqp = 0; ++ priv->mspi_hw->endqp = cpu_to_le32(slot - 1); ++ ++ /* deassert CS on the final byte */ ++ if (fnb & FNB_BREAK_DESELECT) ++ priv->mspi_hw->cdram[slot - 1] &= cpu_to_le32(~0x80); ++ ++ /* tell HIF_MSPI which CS to use */ ++ bcmspi_set_chip_select(priv, msg->spi->chip_select); ++ ++ priv->mspi_hw->write_lock = cpu_to_le32(1); ++ priv->mspi_hw->spcr2 = cpu_to_le32(0xe0); /* cont | spe | spifie */ ++ ++ priv->state = STATE_RUNNING; ++ priv->outstanding_bytes = slot; ++ } else { ++ priv->mspi_hw->write_lock = 0; ++ priv->state = STATE_IDLE; ++ } ++} ++ ++#define DWORD_ALIGNED(a) (!(((unsigned long)(a)) & 3)) ++#define ACROSS_16MB(a, l) (((a) ^ ((a) + (l) - 1)) & 0xFF000000) ++ ++static int bcmspi_emulate_flash_read(struct bcmspi_priv *priv, ++ struct spi_message *msg) ++{ ++ u32 addr, len; ++ int idx = 0; /* Also used for checking continuation */ ++ unsigned long flags = 0; ++ ++ /* Check if it's a continuation */ ++ if (priv->raf_next_len != 0) { ++ ++ /* Continuation (read across 16MB boundary) */ ++ addr = priv->raf_next_addr; ++ len = priv->raf_next_len; ++ ++ /* Update upper address byte */ ++ if (bcmspi_is_4_byte_mode(priv)) { ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); ++ /* Flush prefecth buffers since upper byte changed */ ++ bcmspi_flush_prefetch_buffers(priv); ++ } ++ ++ } else { ++ ++ /* It's the first session of this transfer */ ++ struct spi_transfer *trans; ++ u8 *buf; ++ ++ /* acquire lock when the MSPI is idle */ ++ while (1) { ++ spin_lock_irqsave(&priv->lock, flags); ++ if (priv->state == STATE_IDLE) ++ break; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ if (priv->state == STATE_SHUTDOWN) ++ return -EIO; ++ udelay(1); ++ } ++ bcmspi_set_chip_select(priv, msg->spi->chip_select); ++ ++ /* first transfer - OPCODE_READ + 3-byte address */ ++ trans = list_entry(msg->transfers.next, struct spi_transfer, ++ transfer_list); ++ buf = (void *)trans->tx_buf; ++ ++ idx = 1; ++ ++ /* Check upper address byte for 4-byte mode */ ++ if (bcmspi_is_4_byte_mode(priv)) { ++ addr = buf[idx++] << 24; ++ } else { ++ addr = 0; ++ } ++ ++ /* ++ * addr coming into this function is a raw flash offset ++ * we need to convert it to the BSPI address ++ */ ++ addr |= (buf[idx] << 16) | (buf[idx+1] << 8) | buf[idx+2]; ++ ++ /* second transfer - read result into buffer */ ++ trans = list_entry(msg->transfers.next->next, struct spi_transfer, ++ transfer_list); ++ ++ buf = (void *)trans->rx_buf; ++ ++ len = trans->len; ++ ++ /* non-aligned and very short transfers are handled by MSPI */ ++ if (unlikely(!DWORD_ALIGNED(addr) || ++ !DWORD_ALIGNED(buf) || ++ len < sizeof(u32) || ++ !priv->bspi_hw_raf)) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return -1; ++ } ++ ++ /* Flush prefetch buffers only if upper address byte changed */ ++ if ((addr & 0xFF000000) != le32_to_cpu(priv->bspi_hw->flash_upper_addr_byte)) { ++ bcmspi_flush_prefetch_buffers(priv); ++ /* Update upper address byte */ ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); ++ } ++ ++ /* Switching to BSPI */ ++ bcmspi_enable_bspi(priv); ++ ++ DBG("%s: dst %p src %p len %x addr BSPI %06x\n", ++ __func__, buf, addr, len, addr); ++ ++ /* initialize software parameters */ ++ priv->xfer_status = 0; ++ priv->cur_xfer = trans; ++ priv->cur_xfer_idx = 0; ++ priv->cur_msg = msg; ++ priv->actual_length = idx + 4 + trans->len; ++ } ++ ++ if (bcmspi_is_4_byte_mode(priv) && ACROSS_16MB(addr, len)) { ++ ++ /* Size for the first session */ ++ u32 bytes = 0x1000000 - (addr & 0x00FFFFFF); ++ ++ /* Address and size for remaining sessions */ ++ priv->raf_next_addr = addr + bytes; ++ priv->raf_next_len = len - bytes; ++ ++ len = bytes; ++ ++ } else { ++ priv->raf_next_len = 0; ++ } ++ ++ /* Length for this session */ ++ priv->cur_xfer_len = len; ++ ++ /* setup hardware */ ++ /* address must be 4-byte aligned */ ++ priv->bspi_hw_raf->start_address = cpu_to_le32(addr & 0x00FFFFFF); ++ priv->bspi_hw_raf->num_words = cpu_to_le32((len + 3) >> 2); ++ priv->bspi_hw_raf->watermark = 0; ++ ++ DBG("READ: %08x %08x (%08x)\n", addr, ((len + 3) >> 2), len); ++ ++ bcmspi_clear_interrupt(priv, 0xffffffff); ++ bcmspi_enable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ bcmspi_lr_start(priv); ++ ++ if (idx) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ } ++ ++ return 0; ++} ++ ++/* ++ * m25p80_read() calls wait_till_ready() before each read to check ++ * the flash status register for pending writes. ++ * ++ * This can be safely skipped if our last transaction was just an ++ * emulated BSPI read. ++ */ ++static int bcmspi_emulate_flash_rdsr(struct bcmspi_priv *priv, ++ struct spi_message *msg) ++{ ++ u8 *buf; ++ struct spi_transfer *trans; ++ ++ if (priv->bspi_enabled == 0) ++ return 1; ++ ++ trans = list_entry(msg->transfers.next->next, struct spi_transfer, ++ transfer_list); ++ ++ buf = (void *)trans->rx_buf; ++ *buf = 0x00; ++ ++ msg->actual_length = 2; ++ msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ spi_finalize_current_message(priv->master); ++#else ++ msg->complete(msg->context); ++#endif ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++static int bcmspi_prepare_transfer(struct spi_master *master) ++{ ++ return 0; ++} ++ ++static int bcmspi_unprepare_transfer(struct spi_master *master) ++{ ++ return 0; ++} ++#endif ++ ++static int bcmspi_transfer_one(struct spi_master *master, struct spi_message *msg) ++{ ++ struct bcmspi_priv *priv = spi_master_get_devdata(master); ++ unsigned long flags; ++ ++ if (is_bspi_chip_select(priv, msg->spi->chip_select)) { ++ struct spi_transfer *trans; ++ ++ trans = list_entry(msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ if (trans && trans->len && trans->tx_buf) { ++ u8 command = ((u8 *)trans->tx_buf)[0]; ++ switch (command) { ++ case OPCODE_FAST_READ: ++ if (bcmspi_emulate_flash_read(priv, msg) == 0) ++ return 0; ++ break; ++ case OPCODE_RDSR: ++ if (bcmspi_emulate_flash_rdsr(priv, msg) == 0) ++ return 0; ++ break; ++ case OPCODE_EN4B: ++ DBG("ENABLE 4-BYTE MODE\n"); ++ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_4BYTES, -1); ++ break; ++ case OPCODE_EX4B: ++ DBG("DISABLE 4-BYTE MODE\n"); ++ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_3BYTES, -1); ++ break; ++ case OPCODE_BRWR: ++ { ++ u8 enable = ((u8 *)trans->tx_buf)[1]; ++ DBG("%s 4-BYTE MODE\n", enable ? "ENABLE" : "DISABLE"); ++ bcmspi_set_mode(priv, -1, ++ enable ? BSPI_ADDRLEN_4BYTES : ++ BSPI_ADDRLEN_3BYTES, -1); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ /* Mark prefetch buffers dirty (by using upper byte) if needed */ ++ switch(command) { ++ case OPCODE_RDID: ++ case OPCODE_WREN: ++ case OPCODE_WRDI: ++ case OPCODE_RCR: ++ case OPCODE_READ: ++ case OPCODE_RDSR: ++ case OPCODE_WRSR: ++ case OPCODE_RDFSR: ++ case OPCODE_FAST_READ: ++ case OPCODE_FAST_READ_4B: ++ case OPCODE_EN4B: ++ case OPCODE_EX4B: ++ case OPCODE_BRWR: ++ /* These are known opcodes that are not writing/erasing */ ++ break; ++ default: ++ /* Could be writing/erasing; mark buffers dirty */ ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(0x80); ++ break; ++ } ++ } ++ } ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->state == STATE_SHUTDOWN) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return -EIO; ++ } ++ ++ msg->actual_length = 0; ++ ++ list_add_tail(&msg->queue, &priv->msg_queue); ++ ++ if (priv->state == STATE_IDLE) { ++ BUG_ON(priv->pos.msg != NULL); ++ priv->pos.msg = msg; ++ priv->pos.trans = list_entry(msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ priv->pos.byte = 0; ++ ++ write_to_hw(priv); ++ } ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) ++static int bcmspi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ return bcmspi_transfer_one(spi->master, msg); ++} ++#endif ++ ++static void bcmspi_cleanup(struct spi_device *spi) ++{ ++ struct bcmspi_parms *xp = spi_get_ctldata(spi); ++ ++ DBG("%s\n", __func__); ++ ++ kfree(xp); ++} ++ ++static irqreturn_t bcmspi_interrupt(int irq, void *dev_id) ++{ ++ struct bcmspi_priv *priv = dev_id; ++ ++ if (priv->bspi_enabled && priv->cur_xfer) { ++ int done = 0; ++ u32 status = bcmspi_read_interrupt(priv); ++ u32 *buf = (u32 *)priv->cur_xfer->rx_buf; ++ if (status & BSPI_LR_INTERRUPTS_DATA) { ++ while (!bcmspi_lr_is_fifo_empty(priv)) { ++ u32 data = bcmspi_lr_read_fifo(priv); ++ if (likely(priv->cur_xfer_len >= 4)) { ++ buf[priv->cur_xfer_idx++] = data; ++ priv->cur_xfer_len -= 4; ++ } else { ++ /* ++ * Read out remaining bytes, make sure ++ * we do not cross the buffer boundary ++ */ ++ u8 *cbuf = ++ (u8 *)&buf[priv->cur_xfer_idx]; ++ data = cpu_to_le32(data); ++ while (priv->cur_xfer_len) { ++ *cbuf++ = (u8)data; ++ data >>= 8; ++ priv->cur_xfer_len--; ++ } ++ } ++ } ++ } ++ if (status & BSPI_LR_INTERRUPTS_ERROR) { ++ dev_err(&priv->pdev->dev, "ERROR %02x\n", status); ++ priv->xfer_status = -EIO; ++ } else if ((status & QSPI_INTR_BSPI_LR_SESSION_DONE_MASK) && ++ priv->cur_xfer_len == 0) { ++ ++ if (priv->raf_next_len) { ++ ++ /* Continuation for reading across 16MB boundary */ ++ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ bcmspi_emulate_flash_read(priv, NULL); ++ return IRQ_HANDLED; ++ ++ } else { ++ done = 1; ++ } ++ } ++ ++ if (done) { ++ priv->cur_xfer = NULL; ++ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ ++ if (priv->xfer_status) { ++ bcmspi_lr_clear(priv); ++ } else { ++ if (priv->cur_msg) { ++ priv->cur_msg->actual_length = priv->actual_length; ++ priv->cur_msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ spi_finalize_current_message(priv->master); ++#else ++ priv->cur_msg->complete(priv->cur_msg->context); ++#endif ++ } ++ } ++ priv->cur_msg = NULL; ++ } ++ bcmspi_clear_interrupt(priv, status); ++ return IRQ_HANDLED; ++ } ++ ++ if (priv->mspi_hw->mspi_status & cpu_to_le32(1)) { ++ /* clear interrupt */ ++ priv->mspi_hw->mspi_status &= cpu_to_le32(~1); ++ bcmspi_clear_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); ++ ++ tasklet_schedule(&priv->tasklet); ++ return IRQ_HANDLED; ++ } else ++ return IRQ_NONE; ++} ++ ++static void bcmspi_complete(void *arg) ++{ ++ complete(arg); ++} ++ ++static void bcmspi_tasklet(unsigned long param) ++{ ++ struct bcmspi_priv *priv = (void *)param; ++ struct list_head completed; ++ struct spi_message *msg; ++ unsigned long flags; ++ ++ INIT_LIST_HEAD(&completed); ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->next_udelay) { ++ udelay(priv->next_udelay); ++ priv->next_udelay = 0; ++ } ++ ++ msg = priv->pos.msg; ++ ++ read_from_hw(priv, &completed); ++ if (priv->cs_change) { ++ udelay(10); ++ priv->cs_change = 0; ++ } ++ ++ write_to_hw(priv); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ while (!list_empty(&completed)) { ++ msg = list_first_entry(&completed, struct spi_message, queue); ++ list_del(&msg->queue); ++ msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ if (msg->complete == bcmspi_complete) ++ msg->complete(msg->context); ++ else ++ spi_finalize_current_message(priv->master); ++#else ++ if (msg->complete) ++ msg->complete(msg->context); ++#endif ++ ++ } ++} ++ ++static struct spi_master *default_master; ++ ++static int bcmspi_simple_transaction(struct bcmspi_parms *xp, ++ const void *tx_buf, int tx_len, void *rx_buf, int rx_len) ++{ ++ DECLARE_COMPLETION_ONSTACK(fini); ++ struct spi_message m; ++ struct spi_transfer t_tx, t_rx; ++ struct spi_device spi; ++ int ret; ++ ++ memset(&spi, 0, sizeof(spi)); ++ spi.max_speed_hz = xp->speed_hz; ++ spi.chip_select = xp->chip_select; ++ spi.mode = xp->mode; ++ spi.bits_per_word = xp->bits_per_word; ++ spi.master = default_master; ++ ++ spi_message_init(&m); ++ m.complete = bcmspi_complete; ++ m.context = &fini; ++ m.spi = &spi; ++ ++ memset(&t_tx, 0, sizeof(t_tx)); ++ memset(&t_rx, 0, sizeof(t_rx)); ++ t_tx.tx_buf = tx_buf; ++ t_tx.len = tx_len; ++ t_rx.rx_buf = rx_buf; ++ t_rx.len = rx_len; ++ ++ if (tx_len) ++ spi_message_add_tail(&t_tx, &m); ++ if (rx_len) ++ spi_message_add_tail(&t_rx, &m); ++ ++ ret = bcmspi_transfer_one(default_master, &m); ++ if (!ret) ++ wait_for_completion(&fini); ++ return ret; ++} ++ ++static void bcmspi_hw_init(struct bcmspi_priv *priv) ++{ ++ const struct bcmspi_parms bcmspi_default_parms_cs0 = { ++ .speed_hz = DEFAULT_SPEED_HZ, ++ .chip_select = 0, ++ .mode = SPI_MODE_3, ++ .bits_per_word = 8, ++ }; ++ ++ priv->mspi_hw->spcr1_lsb = 0; ++ priv->mspi_hw->spcr1_msb = 0; ++ priv->mspi_hw->newqp = 0; ++ priv->mspi_hw->endqp = 0; ++ priv->mspi_hw->spcr2 = cpu_to_le32(0x20); /* spifie */ ++ ++ bcmspi_hw_set_parms(priv, &bcmspi_default_parms_cs0); ++ ++ priv->bspi_enabled = 1; ++ bcmspi_disable_bspi(priv); ++} ++ ++static void bcmspi_hw_uninit(struct bcmspi_priv *priv) ++{ ++ priv->mspi_hw->spcr2 = 0x0; /* disable irq and enable bits */ ++ bcmspi_enable_bspi(priv); ++} ++ ++static int bcmbspi_flash_type(struct bcmspi_priv *priv) ++{ ++ char tx_buf[4]; ++ unsigned char jedec_id[5] = {0}; ++ int bspi_flash; ++ ++ /* Read ID */ ++ tx_buf[0] = OPCODE_RDID; ++ bcmspi_simple_transaction(&priv->last_parms, tx_buf, 1, &jedec_id, 5); ++ ++ switch (jedec_id[0]) { ++ case 0x01: /* Spansion */ ++ case 0xef: ++ bspi_flash = BSPI_FLASH_TYPE_SPANSION; ++ break; ++ case 0xc2: /* Macronix */ ++ bspi_flash = BSPI_FLASH_TYPE_MACRONIX; ++ break; ++ case 0xbf: /* SST */ ++ bspi_flash = BSPI_FLASH_TYPE_SST; ++ break; ++ case 0x89: /* Numonyx */ ++ bspi_flash = BSPI_FLASH_TYPE_NUMONYX; ++ break; ++ default: ++ bspi_flash = BSPI_FLASH_TYPE_UNKNOWN; ++ break; ++ } ++ return bspi_flash; ++} ++ ++static int bcmspi_set_quad_mode(struct bcmspi_priv *priv, int _enable) ++{ ++ char tx_buf[4]; ++ unsigned char cfg_reg, sts_reg; ++ ++ switch (bcmbspi_flash_type(priv)) { ++ case BSPI_FLASH_TYPE_SPANSION: ++ /* RCR */ ++ tx_buf[0] = OPCODE_RCR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ if (_enable) ++ cfg_reg |= 0x2; ++ else ++ cfg_reg &= ~0x2; ++ /* WREN */ ++ tx_buf[0] = OPCODE_WREN; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, NULL, 0); ++ /* WRR */ ++ tx_buf[0] = OPCODE_WRR; ++ tx_buf[1] = 0; /* status register */ ++ tx_buf[2] = cfg_reg; /* configuration register */ ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 3, NULL, 0); ++ /* wait till ready */ ++ do { ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &sts_reg, 1); ++ udelay(1); ++ } while (sts_reg & 1); ++ break; ++ case BSPI_FLASH_TYPE_MACRONIX: ++ /* RDSR */ ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ if (_enable) ++ cfg_reg |= 0x40; ++ else ++ cfg_reg &= ~0x40; ++ /* WREN */ ++ tx_buf[0] = OPCODE_WREN; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, NULL, 0); ++ /* WRSR */ ++ tx_buf[0] = OPCODE_WRSR; ++ tx_buf[1] = cfg_reg; /* status register */ ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 2, NULL, 0); ++ /* wait till ready */ ++ do { ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &sts_reg, 1); ++ udelay(1); ++ } while (sts_reg & 1); ++ /* RDSR */ ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ break; ++ case BSPI_FLASH_TYPE_SST: ++ case BSPI_FLASH_TYPE_NUMONYX: ++ /* TODO - send Quad mode control command */ ++ break; ++ default: ++ return _enable ? -1 : 0; ++ } ++ ++ return 0; ++} ++ ++static int bcmspi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct brcmspi_platform_data *pdata; ++ struct bcmspi_priv *priv; ++ struct spi_master *master; ++ struct resource *res; ++ struct clk *clk; ++ int ret; ++ u32 irq; ++ ++ DBG("bcmspi_probe\n"); ++ ++ pdata = (struct brcmspi_platform_data *)pdev->dev.platform_data; ++ ++ master = spi_alloc_master(dev, sizeof(struct bcmspi_priv)); ++ if (!master) { ++ dev_err(&pdev->dev, "error allocating spi_master\n"); ++ return -ENOMEM; ++ } ++ ++ priv = spi_master_get_devdata(master); ++ ++ priv->pdev = pdev; ++ priv->state = STATE_IDLE; ++ priv->pos.msg = NULL; ++ priv->pos.mspi_16bit = 0; ++ priv->master = master; ++ priv->raf_next_len = 0; ++ ++ master->bus_num = pdev->id; ++ master->num_chipselect = 1; ++ master->mode_bits = SPI_MODE_3; ++ ++ master->setup = bcmspi_setup; ++ master->cleanup = bcmspi_cleanup; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ master->prepare_transfer_hardware = bcmspi_prepare_transfer; ++ master->unprepare_transfer_hardware = bcmspi_unprepare_transfer; ++ master->transfer_one_message = bcmspi_transfer_one; ++ master->transfer = NULL; ++#else ++ master->transfer = bcmspi_transfer; ++#endif ++ ++ priv->mspi_hw = NULL; ++ priv->bspi_hw = NULL; ++ priv->bspi_hw_raf = NULL; ++ priv->qspi_intr = NULL; ++ priv->idm_qspi = NULL; ++ priv->irq = -1; ++ ++#ifdef CONFIG_MACH_CYGNUS ++ /* Get MSPI reference clock and max speed hz */ ++ clk = clk_get_sys(NULL, MSPI_REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ MSPI_REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ ++ if(clk < 0xc0008000) ++ { ++ printk(KERN_INFO "ERROR-Cygnus: QSPI clk=0x%x \n"); ++ } ++ ++ priv->mspi_refclk = 310000 * 2 ;//(unsigned int)25000000 * 2; ++ ++#else ++ /* Get MSPI reference clock and max speed hz */ ++ clk = clk_get_sys(MSPI_REFCLK_SOURCE_DEVID, MSPI_REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ MSPI_REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ priv->mspi_refclk = (unsigned int)clk_get_rate(clk) * 2; ++#endif /* CONFIG_MACH_CYGNUS */ ++ ++ priv->max_speed_hz = priv->mspi_refclk / (2 * SPBR_MIN); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't get resource 0\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ /* MSPI register range */ ++ priv->mspi_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->mspi_hw) { ++ dev_err(&pdev->dev, "can't ioremap\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->mspi_hw=%p\n", priv->mspi_hw); ++ ++ /* BSPI register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (res) { ++ priv->bspi_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->bspi_hw) { ++ dev_err(&pdev->dev, "can't ioremap BSPI range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else ++ priv->bspi_hw = NULL; ++ DBG("priv->bspi_hw=%p\n", priv->bspi_hw); ++ ++ /* BSPI_RAF register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (res) { ++ priv->bspi_hw_raf = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->bspi_hw_raf) { ++ dev_err(&pdev->dev, "can't ioremap BSPI_RAF range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else ++ priv->bspi_hw_raf = NULL; ++ DBG("priv->bspi_hw_raf=%p\n", priv->bspi_hw_raf); ++ ++ /* QSPI interrupt register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 3); ++ if (res) { ++ priv->qspi_intr = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->qspi_intr) { ++ dev_err(&pdev->dev, "can't ioremap QSPI interrupt range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 3\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->qspi_intr=%p\n", priv->qspi_intr); ++ ++ /* IDM QSPI io ctrl register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 4); ++ if (res) { ++ priv->idm_qspi = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->idm_qspi) { ++ dev_err(&pdev->dev, "can't ioremap IDM QSPI range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 4\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->idm_qspi=%p\n", priv->idm_qspi); ++ ++ /* CRU control register */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 5); ++ if (res) { ++ priv->cru_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->cru_hw) { ++ dev_err(&pdev->dev, "can't ioremap CRU range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 4\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->cru_hw=%p\n", priv->cru_hw); ++ ++ /* IRQ */ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no IRQ defined\n"); ++ ret = -ENODEV; ++ goto err2; ++ } ++ ++ /* Basic initialization (before enabling interrupts) */ ++ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); ++ bcmspi_disable_interrupt(priv, 0xffffffff); ++ bcmspi_clear_interrupt(priv, 0xffffffff); ++ bcmspi_enable_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); ++ ++ /* Request all IRQs */ ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ ret = request_irq(irq, bcmspi_interrupt, 0, "qspi_iproc", priv); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "unable to allocate IRQ\n"); ++ goto err1; ++ } ++ } ++ ++ bcmspi_hw_init(priv); ++ priv->curr_cs = -1; ++ ++ priv->bspi_chip_select = (priv->bspi_hw && pdata) ? (1 << pdata->flash_cs) : 0; ++ ++ INIT_LIST_HEAD(&priv->msg_queue); ++ spin_lock_init(&priv->lock); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ tasklet_init(&priv->tasklet, bcmspi_tasklet, (unsigned long)priv); ++ ++ ret = spi_register_master(master); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "can't register master\n"); ++ goto err0; ++ } ++ if (!default_master) ++ default_master = master; ++ ++ /* default values - undefined */ ++ priv->flex_mode.width = ++ priv->flex_mode.addrlen = ++ priv->flex_mode.hp = -1; ++ ++ if (priv->bspi_chip_select) { ++ int bspi_width = BSPI_WIDTH_1BIT; ++ ++ /* Module parameter validation */ ++ if (io_mode != 0) { ++ if (read_opcode < 0 || read_opcode > 255) { ++ dev_err(&pdev->dev, "invalid read_opcode\n"); ++ io_mode = 0; ++ } else if (dummy_cycles < 0 || dummy_cycles > 255) { ++ dev_err(&pdev->dev, "invalid dummy_cycles\n"); ++ io_mode = 0; ++ } ++ } ++ if (io_mode == 2) { ++ bspi_width = BSPI_WIDTH_4BIT; ++ } else if (io_mode == 1) { ++ bspi_width = BSPI_WIDTH_2BIT; ++ } else if (io_mode != 0) { ++ dev_err(&pdev->dev, "invalid io_mode (0/1/2)\n"); ++ } ++ ++ if (io_mode == 2) ++ bcmspi_set_quad_mode(priv, 1); ++ ++ bcmspi_set_mode(priv, bspi_width, BSPI_ADDRLEN_3BYTES, bspi_hp); ++ } ++ ++ return 0; ++ ++err0: ++ bcmspi_hw_uninit(priv); ++err1: ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ free_irq(irq, priv); ++ } ++err2: ++ if (priv->idm_qspi) { ++ iounmap(priv->idm_qspi); ++ } ++ if (priv->qspi_intr) { ++ iounmap(priv->qspi_intr); ++ } ++ if (priv->bspi_hw_raf) { ++ iounmap(priv->bspi_hw_raf); ++ } ++ if (priv->bspi_hw) { ++ iounmap(priv->bspi_hw); ++ } ++ if (priv->mspi_hw) { ++ iounmap(priv->mspi_hw); ++ } ++ spi_master_put(master); ++ return ret; ++} ++ ++static int bcmspi_remove(struct platform_device *pdev) ++{ ++ struct bcmspi_priv *priv = platform_get_drvdata(pdev); ++ unsigned long flags; ++ struct resource *res; ++ u32 irq; ++ ++ /* acquire lock when the MSPI is idle */ ++ while (1) { ++ spin_lock_irqsave(&priv->lock, flags); ++ if (priv->state == STATE_IDLE) ++ break; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ udelay(100); ++ } ++ priv->state = STATE_SHUTDOWN; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ tasklet_kill(&priv->tasklet); ++ platform_set_drvdata(pdev, NULL); ++ bcmspi_hw_uninit(priv); ++ if (priv->bspi_hw_raf) ++ iounmap(priv->bspi_hw_raf); ++ if (priv->bspi_hw) ++ iounmap((volatile void __iomem *)priv->bspi_hw); ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (res) { ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ free_irq(irq, priv); ++ } ++ } ++ iounmap((volatile void __iomem *)priv->mspi_hw); ++ spi_unregister_master(priv->master); ++ ++ return 0; ++} ++ ++static struct platform_driver driver = { ++ .driver = { ++ .name = "qspi_iproc", ++ .bus = &platform_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .probe = bcmspi_probe, ++ .remove = __devexit_p(bcmspi_remove), ++}; ++ ++static int __init bcmspi_spi_init(void) ++{ ++ platform_driver_register(&driver); ++ return 0; ++} ++ ++static void __exit bcmspi_spi_exit(void) ++{ ++ platform_driver_unregister(&driver); ++} ++ ++module_init(bcmspi_spi_init); ++module_exit(bcmspi_spi_exit); ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("iProc QSPI driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/smbus/.gitignore b/drivers/bcmdrivers/smbus/.gitignore +new file mode 100644 +index 0000000..0f97013 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch new file mode 100644 index 00000000..1217b7b1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_.gitignore.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_i2c.o.cmd ++/.iproc_smbus.o.cmd ++/built-in.o ++/iproc_i2c.o ++/iproc_smbus.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/smbus/Kconfig b/drivers/bcmdrivers/smbus/Kconfig +new file mode 100644 +index 0000000..9ae0f71 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch new file mode 100644 index 00000000..754166ae --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Kconfig.patch @@ -0,0 +1,14 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_I2C ++ tristate "I2C support" ++ depends on ARCH_IPROC ++ default n ++ help ++ I2C support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/smbus/Makefile b/drivers/bcmdrivers/smbus/Makefile +new file mode 100644 +index 0000000..812c7a1 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch new file mode 100644 index 00000000..bb58dce0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_Makefile.patch @@ -0,0 +1,9 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_I2C) += iproc_i2c.o ++iproc_i2c-objs := iproc_smbus.o +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus.c b/drivers/bcmdrivers/smbus/iproc_smbus.c +new file mode 100644 +index 0000000..49e25d6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch new file mode 100644 index 00000000..7c597837 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.c.patch @@ -0,0 +1,2049 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus.c +@@ -0,0 +1,2043 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iproc_smbus_regs.h" ++#include "iproc_smbus_defs.h" ++#include "iproc_smbus.h" ++#include ++#include ++#include ++#include ++#include ++ ++//#define IPROC_SMB_DBG 1 ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) ++#define init_MUTEX(x) sema_init(x,1) ++#endif ++ ++int brcm_get_hx4_model(void); ++ ++static struct proc_dir_entry *gProcParent; ++static int use_svk_version; ++ ++static int smb_in_intr; ++ ++static struct iproc_smb_drv_int_data *iproc_smbus_list = NULL; ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev); ++ ++/* Function to read a value from specified register. */ ++static unsigned int iproc_smb_reg_read(unsigned long reg_addr) ++{ ++ unsigned int val; ++ ++ val = ioread32((void *)reg_addr); ++ ++#ifdef IPROC_SMB_DBG ++ if (!smb_in_intr) { ++ printk(KERN_DEBUG "\nRd: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); ++ } ++#endif ++ ++ return(val); ++} ++ ++/* Function to write a value ('val') in to a specified register. */ ++static int iproc_smb_reg_write(unsigned long reg_addr, unsigned int val) ++{ ++ iowrite32(val, (void *)reg_addr); ++ ++#ifdef IPROC_SMB_DBG ++ if (!smb_in_intr) { ++ printk(KERN_DEBUG "\nWr: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); ++ } ++#endif ++ ++ return (0); ++} ++ ++static int iproc_dump_smb_regs(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ ++ printk(KERN_DEBUG "\n----------------------------------------------"); ++ ++ printk(KERN_DEBUG "\nBase addr=0x%08X", (unsigned int)base_addr); ++ ++ printk(KERN_DEBUG "%s: Dumping SMBus registers... ", __func__); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_CFG_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_CFG_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_TIMGCFG_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_ADDR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_ADDR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRFIFOCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRFIFOCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVFIFOCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVFIFOCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_BITBANGCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_BITBANGCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRCMD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRCMD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVCMD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVCMD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_EVTEN_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_EVTSTS_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATAWR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATAWR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATARD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATARD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATAWR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVDATAWR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATARD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVDATARD_REG=0x%08X", regval); ++ ++ printk(KERN_DEBUG "\n----------------------------------------------\n\n"); ++ ++ return(0); ++} ++ ++static irqreturn_t iproc_smb_isr(int irq, void*devid) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)devid; ++ unsigned int intsts; ++ unsigned int regval; ++ ++ ++ smb_in_intr = 1; ++ ++ intsts = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTSTS_REG); ++ ++ dev->smb_counters.last_int_sts = intsts; ++ ++ if (!intsts) { ++ ++ /* Likely received a spurious interrupt */ ++ ++ return IRQ_NONE; ++ ++ } ++ ++ /* Clear interrupts */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTSTS_REG, intsts); ++ ++ /* Master read or write complete */ ++ if ((intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) || ++ (intsts & CCB_SMB_MSTRRXEVTSTS_MASK)) { ++ ++ if (intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) { ++ ++ dev->smb_counters.mstr_start_busy_cnt++; ++ ++ } ++ ++ if (intsts & CCB_SMB_MSTRRXEVTSTS_MASK) { ++ ++ dev->smb_counters.mstr_rx_evt_cnt++; ++ ++ } ++ ++ /* In case of a receive transaction, data will be copied in the recv ++ * function ++ */ ++ complete(&dev->ses_done); ++ ++ } ++ ++ /* If RX FIFO was full we can either read and then flush the FIFO. Or, only ++ * flush the FIFO (since the client process did not read the data on time), ++ * and then the client process can restart the transaction ++ * For now, we will flush the later action. ++ */ ++ if (intsts & CCB_SMB_MSTRRXFIFOFULLSTS_MASK) { ++ ++ dev->smb_counters.mstr_rx_fifo_full_cnt++; ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRFIFOCTL_REG); ++ ++ regval |= CCB_SMB_MSTRRXFIFOFLSH_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRFIFOCTL_REG, regval); ++ ++ complete(&dev->ses_done); ++ ++ } ++ ++ smb_in_intr = 0; ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Function to ensure that the previous transaction was completed before ++ * initiating a new transaction. It can also be used in polling mode to ++ * check status of completion of a command ++ */ ++static int iproc_smb_startbusy_wait(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* Check if an operation is in progress. During probe it won't be. ++ * But when shutdown/remove was called we want to make sure that ++ * the transaction in progress completed ++ */ ++ if (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { ++ unsigned int i = 0; ++ ++ do { ++ ++ msleep(1); /* Wait for 1 msec */ ++ ++ i++; ++ ++ regval = iproc_smb_reg_read( ++ (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG); ++ ++ /* If start-busy bit cleared, exit the loop */ ++ } while ((regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) && ++ (i < IPROC_SMB_MAX_RETRIES)); ++ ++ if (i >= IPROC_SMB_MAX_RETRIES) { ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: %s START_BUSY bit didn't clear, exiting\n", ++ __func__, dev->adapter.name); ++#endif ++ return -ETIMEDOUT; ++ ++ } ++ ++ } ++ ++ return 0; ++} ++ ++ ++static unsigned int smbus0_sdaRecoveryCnt = 0, smbus0_sdaFailedCnt = 0, smbus0_startBusyCnt = 0; ++static unsigned int smbus1_sdaRecoveryCnt = 0, smbus1_sdaFailedCnt = 0, smbus1_startBusyCnt = 0; ++ ++/* ++ * Function to recover SMB hangs caused stuck master START_BUSY. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_startbusy_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ int rc = -1; ++ unsigned int recoveryCnt; ++ ++ if (dev->adapter.nr == 0) { ++ recoveryCnt = ++smbus0_startBusyCnt; ++ } ++ else { ++ recoveryCnt = ++smbus1_startBusyCnt; ++ } ++ ++ printk(KERN_INFO "%s: %s START_BUSY recovery #%d \n", __func__, dev->adapter.name, recoveryCnt); ++ ++ /* reset the SMBus block, wait a minimum of 50 uSecs and then re-initialize */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, CCB_SMB_CFG_RST_MASK); ++ udelay(60); ++ ++ if ( iproc_smbus_block_init(dev) == 0 ) { ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device holding SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++ ++static int iproc_smb_sda_low_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, cfgReg, cfgSave, recoveryCnt, failedCnt, i; ++ int rc = -1; ++ ++ ++ /* enable bit-bang */ ++ cfgSave = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ cfgReg = cfgSave; ++ cfgReg |= CCB_SMB_CFG_BITBANGEN_MASK; ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); ++ udelay(50); ++ ++ /* start with clock and SDA set high */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ ++ bbReg |= (CCB_SMB_SMBCLKOUTEN_MASK | CCB_SMB_SMBDATAOUTEN_MASK); ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); /* should be sufficient for 100 KHz bus */ ++ ++ /* set up to toggle the clock line with SDA out held high for 9 cycles */ ++ for (i=0; i<18; i++) ++ { ++ /* toggle CLK out */ ++ if ( (bbReg & CCB_SMB_SMBCLKOUTEN_MASK) == 0 ) { ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ } ++ else { ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ } ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); ++ } ++ ++ /* check bit 29 -- SMBDAT_IN and make sure SDA not being held low any more */ ++ for ( i=0; i<10; i++ ) ++ { ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= CCB_SMB_SMBDATAIN_MASK; ++ ++ if (bbReg) ++ break; ++ ++ udelay(1); ++ } ++ ++ if ( bbReg == 0 ) { ++ /* SDA is still low */ ++ if (dev->adapter.nr == 0) { ++ failedCnt = ++smbus0_sdaFailedCnt; ++ } ++ else { ++ failedCnt = ++smbus1_sdaFailedCnt; ++ } ++ printk(KERN_INFO "\n%s: %s SDA release #%d FAILED.\n", __func__, dev->adapter.name, failedCnt); ++ } ++ else { ++ if (dev->adapter.nr == 0) { ++ recoveryCnt = ++smbus0_sdaRecoveryCnt; ++ } ++ else { ++ recoveryCnt = ++smbus1_sdaRecoveryCnt; ++ } ++ ++ printk(KERN_INFO "%s: %s SDA release #%d SUCCESSFUL.\n", __func__, dev->adapter.name, recoveryCnt); ++ rc = 0; ++ } ++ ++ ++ /* manually issue a stop by transitioning SDA from low to high with clock held high */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ bbReg &= ~CCB_SMB_SMBDATAOUTEN_MASK; /* drop SDA low */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); ++ ++ bbReg |= CCB_SMB_SMBDATAOUTEN_MASK; /* pull SDA high */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ ++ /* disable bit-bang and then re-enable the SMB with the saved configuration */ ++ cfgReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ cfgReg &= ~CCB_SMB_CFG_BITBANGEN_MASK; ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); ++ udelay(10); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgSave); ++ ++ return rc; ++} ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device hold SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_timeout_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, mCmdReg; ++ int rc = -1; ++ ++ /* read bit-bang control. If SDA low, attempt SDA release recovery */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ ++ if ( (bbReg & CCB_SMB_SMBDATAIN_MASK) == 0 ) { ++ if ( iproc_smb_sda_low_recovery( dev ) == 0 ) { ++ rc = 0; ++ } ++ } ++ ++ /* regardless of whether there was an SDA hang or not, see if START_BUSY stuck high */ ++ mCmdReg = iproc_smb_reg_read( (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG ); ++ if ( mCmdReg & CCB_SMB_MSTRSTARTBUSYCMD_MASK ) { ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) == 0) { ++ rc = 0; ++ } ++ } ++ ++ return rc; ++ ++} ++ ++/* ++ * This function copies data to SMBus's Tx FIFO. Valid for write transactions ++ * only ++ * ++ * base_addr: Mapped address of this SMBus instance ++ * dev_addr: SMBus (I2C) device address. We are assuming 7-bit addresses ++ * initially ++ * info: Data to copy in to Tx FIFO. For read commands, the size should be ++ * set to zero by the caller ++ * ++ */ ++static void iproc_smb_write_trans_data(unsigned long base_addr, ++ unsigned short dev_addr, ++ struct iproc_xact_info *info) ++{ ++ unsigned int regval; ++ unsigned int i; ++ unsigned int num_data_bytes = 0; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: dev_addr=0x%X, offset=%u, cmd_valid=%u, size=%u\n", __func__, dev_addr, info->command, info->cmd_valid, info->size); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Write SMBus device address first */ ++ /* Note, we are assuming 7-bit addresses for now. For 10-bit addresses, ++ * we may have one more write to send the upper 3 bits of 10-bit addr ++ */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, dev_addr); ++ ++ /* If the protocol needs command code, copy it */ ++ if (info->cmd_valid == true) { ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->command); ++ ++ } ++ ++ /* Depending on the SMBus protocol, we need to write additional transaction ++ * data in to Tx FIFO. Refer to section 5.5 of SMBus spec for sequence for a ++ * transaction ++ */ ++ switch (info->smb_proto) { ++ ++ case SMBUS_PROT_RECV_BYTE: ++ /* No additional data to be written */ ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_SEND_BYTE: ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_RD_BYTE: ++ case SMBUS_PROT_RD_WORD: ++ case SMBUS_PROT_BLK_RD: ++ /* Write slave address with R/W~ set (bit #0) */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, ++ dev_addr | 0x1); ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_WR_BYTE: ++ case SMBUS_PROT_WR_WORD: ++ /* No additional bytes to be written. Data portion is written in the ++ * 'for' loop below ++ */ ++ num_data_bytes = info->size; ++ ++ /* Note for hx4 eeprom (at24c64). the low addr bytes can be passed ++ * in to 1st byte of info->data ++ */ ++ break; ++ ++ case SMBUS_PROT_BLK_WR: ++ /* 3rd byte is byte count */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: ++ /* Write byte count */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); ++ num_data_bytes = info->size; ++ break; ++ ++ default: ++ break; ++ ++ } ++ ++ /* Copy actual data from caller, next. In general, for reads, no data is ++ * copied ++ */ ++ for (i = 0; num_data_bytes; --num_data_bytes, i++) { ++ ++ /* For the last byte, set MASTER_WR_STATUS bit. For block rd/wr process ++ * call, we need to program slave addr after copying data byte(s), so ++ * master status bit is set later, after the loop ++ */ ++ if ((num_data_bytes == 1) && ++ (info->smb_proto != SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ regval = info->data[i] | CCB_SMB_MSTRWRSTS_MASK; ++ } ++ else { ++ regval = info->data[i]; ++ } ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, regval); ++ ++ } ++ ++ if (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL) { ++ /* Write device address needed during repeat start condition */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, ++ CCB_SMB_MSTRWRSTS_MASK | dev_addr | 0x1); ++ } ++ ++ return; ++} ++ ++static int iproc_smb_data_send(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: Send: %s bus is busy, attempt recovery \n", ++ __func__, dev->adapter.name); ++#endif ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) { ++ ++ return rc; ++ ++ } ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* Enable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval |= CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ /* Mark as incomplete before sending the data */ ++ INIT_COMPLETION(dev->ses_done); ++ ++ } ++ ++ /* Write transaction bytes to Tx FIFO */ ++ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG, regval); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* ++ * Block waiting for the transaction to finish. When it's finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); ++ ++ /* Disable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval &= ~CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ if (time_left == 0) { ++ ++ printk (KERN_INFO "%s: Send: %s timeout accessing device x%02x\n", ++ __func__, dev->adapter.name, addr); ++ ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if ( rc != 0 ) { ++ ++ return -ETIMEDOUT; ++ ++ } ++ else { ++ return -ECOMM; ++ } ++ ++ } ++ ++ } ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++ ++ /* We can flush Tx FIFO here */ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n\n%s:Send: %s Error in transaction %d to device x%02x, exiting\n", ++ __func__, dev->adapter.name, regval, addr); ++#endif ++ return -EREMOTEIO; ++ ++ } ++ } ++ ++ return(0); ++} ++ ++static int iproc_smb_data_recv(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info, ++ unsigned int *num_bytes_read) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: Receive: %s bus is busy, attempt recovery \n", __func__, dev->adapter.name); ++#endif ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) { ++ return rc; ++ } ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* Enable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ /* Set Rx_event_en bit for notification of reception event */ ++ regval |= (CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ /* Mark as incomplete before sending the data */ ++ INIT_COMPLETION(dev->ses_done); ++ ++ } ++ ++ /* Program all transaction bytes into master Tx FIFO */ ++ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK | info->size; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG, regval); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* ++ * Block waiting for the transaction to finish. When it's finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); ++ ++ /* Disable start_busy and rx_event interrupts. Above call has handled ++ * the interrupt ++ */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval &= ~(CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ if (time_left == 0) { ++ ++ printk (KERN_INFO "\n%s: Receive: %s timeout accessing device 0x%02x\n", ++ __func__, dev->adapter.name, addr); ++ ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if ( rc != 0 ) { ++ return -ETIMEDOUT; ++ } ++ else { ++ return -ECOMM; ++ } ++ } ++ ++ } ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++#ifdef IPROC_SMB_DBG ++ /* We can flush Tx FIFO here */ ++ printk(KERN_INFO "\n%s: %s Error in transaction %d to device x%02x, exiting\n", ++ __func__, dev->adapter.name, regval, addr); ++#endif ++ return -EREMOTEIO; ++ ++ } ++ ++ } ++ ++ /* In the isr we will read the received byte, and also deal with ++ * rx fifo full event. The above check is for timeout error. If needed ++ * we may move it to rx isr ++ */ ++ ++ /* Read received byte(s) */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ /* For block read, protocol (hw) returns byte count, as the first byte */ ++ if ((info->smb_proto == SMBUS_PROT_BLK_RD) || ++ (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ ++ int i; ++ ++ *num_bytes_read = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ /* Limit to reading a max of 32 bytes only; just a safeguard. If ++ * # bytes read is a number > 32, check transaction set up, and contact ++ * hw engg. Assumption: PEC is disabled ++ */ ++ for (i = 0; (i < *num_bytes_read) && (i < I2C_SMBUS_BLOCK_MAX); i++) { ++ ++ /* Read Rx FIFO for data bytes */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ info->data[i] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ } ++ ++ } ++ else { ++ ++ *info->data = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ *num_bytes_read = 1; ++ ++ if (info->smb_proto == SMBUS_PROT_RD_WORD) { ++ /* Read Rx FIFO for data bytes */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ info->data[1] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ *num_bytes_read = 2; ++ } ++ } ++ ++ return(0); ++} ++ ++static int iproc_smb_xfer(struct i2c_adapter *i2c_adap, u16 addr, ++ unsigned short flags, char read_write, ++ u8 command, int size, union i2c_smbus_data *data) ++{ ++ int rc; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(i2c_adap); ++ struct iproc_xact_info info; ++ unsigned int num_bytes_read = 0; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: dev=0x%08X\n", __func__, (unsigned int)dev); ++#endif ++ ++ down(&dev->xfer_lock); ++ ++ addr <<= 1; ++ ++ switch (size /* protocol */) { ++ ++ case I2C_SMBUS_QUICK: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ info.smb_proto = SMBUS_PROT_QUICK_CMD; ++ info.data = &data->byte; /* not used */ ++ info.size = 0; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ addr |= 0x1; /* read operation */ ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ if (read_write == I2C_SMBUS_WRITE) { ++ ++ info.data = &command; ++ ++ } ++ else { ++ ++ info.data = &data->byte; ++ ++ } ++ info.size = 1; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ addr |= 0x1; /* Read operation */ ++ ++ info.smb_proto = SMBUS_PROT_RECV_BYTE; ++ info.data = &data->byte; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_SEND_BYTE; ++ ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->byte; ++ info.size = 1; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ info.smb_proto = SMBUS_PROT_RD_BYTE; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_WR_BYTE; ++ //info.smb_proto = SMBUS_PROT_WR_WORD; /* TEMP chg. remove later */ ++ ++ } ++ break; ++ ++ case I2C_SMBUS_WORD_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = (unsigned char *)(&data->word); ++ info.size = 2; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ info.smb_proto = SMBUS_PROT_RD_WORD; ++ } ++ else { ++ info.smb_proto = SMBUS_PROT_WR_WORD; ++ } ++ ++ break; ++ ++ case I2C_SMBUS_BLOCK_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ info.smb_proto = SMBUS_PROT_BLK_RD; ++ ++ /* Protocol(hw) returns data byte count as part of response */ ++ info.size = 0; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_BLK_WR; ++ ++ info.size = data->block[0]; /* i2c-core passes the length in ++ this field */ ++ ++ } ++ ++ break; ++ ++ case I2C_SMBUS_BLOCK_PROC_CALL: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ info.smb_proto = SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: Unsupported transaction %d\n", __func__, size); ++ up(&dev->xfer_lock); ++ return -EINVAL; ++ ++ } ++ ++ ++ if (read_write == I2C_SMBUS_READ) { ++ /* Refer to i2c_smbus_read_byte for params passed. */ ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); ++ ++ /* if failed due to bus hang, but recovered, retry once */ ++ if (rc == -ECOMM) { ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); ++ } ++ ++ /* For block read call, we pass the actual amount of data sent by ++ * slave, as expected by std Linux API ++ */ ++ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || ++ (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ ++ if (rc == 0) { ++ ++ data->block[0] = num_bytes_read; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: num bytes read=%u\n", ++ __func__, data->block[0]); ++#endif ++ ++ } ++ } ++ ++ } ++ else { ++ ++ /* Refer to i2c_smbus_write_byte params passed. */ ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ ++ /* if failed due to bus hang, but recovered, retry */ ++ if (rc == -ECOMM) { ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ } ++ ++ } ++ ++ if (rc < 0) { ++#ifdef PROC_SMB_DBG ++ printk(KERN_INFO "%s %s: %s error accessing device 0x%X rc=%d", __func__, dev->adapter.name, ++ (read_write == I2C_SMBUS_READ) ? "Read" : "Write", addr, rc); ++#endif ++ up(&dev->xfer_lock); ++ ++ return -EREMOTEIO; ++ ++ } ++ ++ up(&dev->xfer_lock); ++ ++ return (rc); ++} ++ ++static int ++proc_debug_read(char *buffer, ++ char **start, ++ off_t off, ++ int count, ++ int *eof, ++ void *data) ++{ ++ unsigned int len = 0; ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ ++ if (off > 0) ++ return 0; ++ ++ len += sprintf(buffer + len, "Debug print is %s\n", ++ dev->debug ? "enabled" : "disabled"); ++ ++ return len; ++} ++ ++/* Command interface for reading/writing to various I2C/SMBus devices */ ++static int ++proc_debug_write(struct file *file, ++ const char __user *buffer, ++ unsigned long count, ++ void *data) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ unsigned char kbuf[MAX_PROC_BUF_SIZE]; ++ union i2c_smbus_data i2cdata; ++ unsigned int val, i2cdev_addr, rd_wr_op; ++ int addr; ++ ++ if (count > MAX_PROC_BUF_SIZE) { ++ ++ count = MAX_PROC_BUF_SIZE; ++ ++ } ++ ++ rc = copy_from_user(kbuf, buffer, count); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); ++ ++ return -EFAULT; ++ ++ } ++ ++ rc = sscanf(kbuf, "%u %u %d %u", &rd_wr_op, &i2cdev_addr, &addr, &val); ++ ++ if (rc != 4) { ++ ++ printk(KERN_ERR "\necho args > %s", PROC_ENTRY_DEBUG); ++ printk(KERN_ERR "\nargs (all values should be in decimal)):"); ++ printk(KERN_ERR "\nrd_wr_op: 1 = read, 0 = write"); ++ printk(KERN_ERR "\ni2cdev_addr: I2C device address in decimal"); ++ printk(KERN_ERR "\noffset: offset of location within I2C device"); ++ printk(KERN_ERR "\naddr -1 if offset not applicable"); ++ printk(KERN_ERR "\nval: For write op: 8-bit value.\n" ++ " For read op: not used, may be 0\n\n"); ++ ++ return count; ++ ++ } ++ ++ printk(KERN_DEBUG "\n\nArg values :"); ++ printk(KERN_DEBUG "\nrd_wr_op = %u", rd_wr_op); ++ printk(KERN_DEBUG "\ni2cdev_addr = 0x%X", i2cdev_addr); ++ printk(KERN_DEBUG "\noffset = %d", addr); ++ printk(KERN_DEBUG "\nval = %u", val); ++ ++ if (rd_wr_op > 1) { ++ ++ printk(KERN_ERR "\nError: Invalid rd_wr_op value %u\n\n", rd_wr_op); ++ return count; ++ ++ } ++ ++ if (i2cdev_addr > 127) { ++ ++ printk(KERN_ERR "\nError: i2cdev_addr must be 7-bit value\n\n"); ++ return count; ++ ++ } ++ ++ if (addr > 255) { ++ ++ printk(KERN_ERR "\nError: offset out of range for this device\n\n"); ++ return count; ++ ++ } ++ ++ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ if (rd_wr_op == 0) { /* Write operation */ ++ ++ i2cdata.byte = val; ++ ++ if (addr == -1) { ++ ++ /* Device does not support, or require an offset to write to the ++ * location ++ */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, ++ I2C_SMBUS_WRITE, (unsigned char)0, ++ I2C_SMBUS_BYTE, &i2cdata); ++ ++ } ++ else { ++ ++ /* Address required for write access */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, ++ I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, ++ &i2cdata); ++ } ++ ++ if (rc) { ++ ++ printk (KERN_ERR "\n%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); ++ ++ /* return -EFAULT; */ ++ ++ } ++ else { ++ ++ printk(KERN_ERR "\nWrite OK.\nWrote 0x%X at addr %u\n\n", ++ val, addr); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ if (rd_wr_op == 1) { /* Read operation */ ++ ++ if (addr == -1) { ++ ++ /* Device does not support, or require an offset to read from the ++ * location ++ */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, ++ (unsigned char)0, I2C_SMBUS_BYTE, &i2cdata); ++ ++ } ++ else { ++ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, ++ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ } ++ ++ if (rc) { ++ ++ printk (KERN_ERR "\n%s: iproc_smb_xfer failed status=%d\n", ++ __func__, rc); ++ ++ /* return -EFAULT; */ ++ ++ } ++ else { ++ ++ printk(KERN_ERR "\nRead OK.\n--------Value read at %u = 0x%X\n\n", ++ addr, i2cdata.byte); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", ++ dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return count; ++} ++ ++/* Written for SVK boards */ ++static int ++proc_debug_write_svk(struct file *file, ++ const char __user *buffer, ++ unsigned long count, ++ void *data) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ unsigned int debug; ++ unsigned char kbuf[MAX_PROC_BUF_SIZE]; ++ union i2c_smbus_data i2cdata; ++ unsigned int val, addr; ++ ++ if (count > MAX_PROC_BUF_SIZE) { ++ ++ count = MAX_PROC_BUF_SIZE; ++ ++ } ++ ++ rc = copy_from_user(kbuf, buffer, count); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); ++ ++ return -EFAULT; ++ ++ } ++ ++ if (sscanf(kbuf, "%u", &debug) != 1) { ++ ++ printk(KERN_ERR "%s: echo > %s\n", __func__, PROC_ENTRY_DEBUG); ++ ++ return count; ++ ++ } ++ ++ if (debug) { ++ ++ dev->debug = 1; ++ ++ } ++ else { ++ ++ dev->debug = 0; ++ ++ } ++ ++ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ if (!dev->debug) { ++ ++ val = 0xFF; /* Initial value to write */ ++ ++ for(addr = 0x0; addr < 256; val--, addr++) { ++ ++ i2cdata.byte = val; ++ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, ++ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X", __func__, rc, addr, val); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nWrite OK.\nWrote 0x%X at addr %u\n\n", ++ val, addr); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ } ++ else { ++ ++ int i; ++ ++ /* Note about address expected by AT24C02: To write in correct order ++ * to AT24C02 using block write, refer bottom of page 9 (Write ++ * Operations) of the data sheet regarding internal incrementing of ++ * address. Based on that explanation, we program the addr value below. ++ * Select the 'highest' address in that page (7, 15, 23, and so on) to ++ * write to that page ++ */ ++ addr = debug - 1; ++ ++ val = jiffies % 256; ++ ++ printk(KERN_DEBUG "\nEEPROM page write. Page start addr = %u," ++ " write data: \n\n", debug - 8); ++ ++ for (i = 1; i <= 8; i++) { ++ ++ i2cdata.block[i] = val % 256; /* Fill a sequence pattern */ ++ ++ val++; ++ ++ printk(KERN_DEBUG "\nbyte%d = 0x%02X\n", i, i2cdata.block[i]); ++ ++ } ++ ++ i2cdata.block[0] = 8; ++ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, ++ addr, I2C_SMBUS_BLOCK_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X", __func__, rc, addr, val); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nBlock Write OK.\n\n"); ++ ++ } ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", ++ dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return count; ++} ++ ++/* Written for SVK boards */ ++static int ++proc_debug_read_svk(char *buffer, ++ char **start, ++ off_t off, ++ int count, ++ int *eof, ++ void *data) ++{ ++ unsigned int len = 0; ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ union i2c_smbus_data i2cdata; ++ unsigned int addr; ++ ++ if (off > 0) { ++ ++ return 0; ++ ++ } ++ ++ len += sprintf(buffer + len, "Read\n"); ++ ++ printk(KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ for(addr = 0x0; addr < 256; addr++) { ++ ++ /* Read operation */ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_READ, addr, ++ I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer failed status=%d", __func__, rc); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nRead OK.\n--------Value read at %u = 0x%X\n", ++ addr, i2cdata.byte); ++ ++ } ++ ++ msleep(1); ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return len; ++} ++ ++static int proc_init(struct platform_device *pdev) ++{ ++ int rc, id; ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct procfs *proc = &dev->proc; ++ struct proc_dir_entry *proc_debug; ++ ++ if (pdev->dev.of_node) { ++ id = of_alias_get_id(pdev->dev.of_node, "i2c-controller");; ++ } else { ++ id = pdev->id; ++ } ++ snprintf(proc->name, sizeof(proc->name), "%s%d", PROC_GLOBAL_PARENT_DIR, id); ++ ++ /* sub directory */ ++ proc->parent = proc_mkdir(proc->name, gProcParent); ++ ++ if (proc->parent == NULL) { ++ ++ return -ENOMEM; ++ ++ } ++ ++ proc_debug = create_proc_entry(PROC_ENTRY_DEBUG, 0644, proc->parent); ++ ++ if (proc_debug == NULL) { ++ ++ rc = -ENOMEM; ++ ++ goto err_del_parent; ++ } ++ ++ use_svk_version = 0; /* Do not use SVK version */ ++ ++ if (use_svk_version) { ++ ++ proc_debug->read_proc = proc_debug_read_svk; ++ proc_debug->write_proc = proc_debug_write_svk; ++ ++ } ++ else { ++ ++ proc_debug->read_proc = proc_debug_read; ++ proc_debug->write_proc = proc_debug_write; ++ ++ } ++ ++ proc_debug->data = dev; ++ ++ return 0; ++ ++err_del_parent: ++ remove_proc_entry(proc->name, gProcParent); ++ ++ return rc; ++} ++ ++static int proc_term(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct procfs *proc = &dev->proc; ++ ++ remove_proc_entry(PROC_ENTRY_DEBUG, proc->parent); ++ remove_proc_entry(proc->name, gProcParent); ++ ++ return 0; ++} ++ ++/* ++ * This function set clock frequency for SMBus block. As per hardware ++ * engineering, the clock frequency can be changed dynamically. ++ */ ++static int iproc_smb_set_clk_freq(struct iproc_smb_drv_int_data *iproc_i2c) ++{ ++ /* Default clock frequency is 100KHz */ ++ unsigned int bus_speed = 100000; ++ unsigned long base_addr = (unsigned long)iproc_i2c->block_base_addr; ++ unsigned int regval; ++ unsigned int val; ++ int ret; ++ ++ if (iproc_i2c->dev->of_node) { ++ /* DT based instantiation */ ++ ret = of_property_read_u32(iproc_i2c->dev->of_node, ++ "clock-frequency", &bus_speed); ++ if (ret < 0) { ++ dev_info(iproc_i2c->dev, ++ "unable to interpret clock-frequency DT property\n"); ++ bus_speed = 100000; ++ } ++ } else { ++ /* Non-DT based instantiation */ ++ bus_speed = 100000; ++ } ++ ++ if (bus_speed < 100000) { ++ dev_err(iproc_i2c->dev, "%d Hz bus speed not supported\n", ++ bus_speed); ++ dev_err(iproc_i2c->dev, ++ "valid speeds are 100khz and 400khz\n"); ++ return -EINVAL; ++ } else if (bus_speed < 400000) { ++ bus_speed = 100000; ++ } else { ++ bus_speed = 400000; ++ } ++ ++ switch (bus_speed) { ++ case 100000: ++ val = 0; ++ break; ++ ++ case 400000: ++ val = 1; ++ break; ++ ++ default: ++ return -EINVAL; ++ break; ++ ++ } ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); ++ ++ SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK, ++ CCB_SMB_TIMGCFG_MODE400_SHIFT); ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_TIMGCFG_REG, regval); ++ ++ dev_info(iproc_i2c->dev, "bus set to %u Hz\n", bus_speed); ++ return(0); ++} ++ ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev) ++{ ++ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ /* Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. ++ * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts ++ */ ++ regval = CCB_SMB_MSTRRXFIFOFLSH_MASK | CCB_SMB_MSTRTXFIFOFLSH_MASK; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRFIFOCTL_REG, regval); ++ ++ /* Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero ++ * since there will be only one master ++ */ ++ regval = CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_CFG_REG, regval); ++ ++ /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ ++ udelay(100); ++ ++ ++ /* Set default clock frequency baed on device tree */ ++ iproc_smb_set_clk_freq(dev); ++ ++ /* Disable intrs */ ++ regval = 0x0; ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Clear intrs (W1TC) */ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTSTS_REG, regval); ++ ++ return(0); ++} ++ ++/* This function enables interrupts */ ++static int iproc_intr_enable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) ++{ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ ++ regval |= bmap; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Store all interrupts enabled so far. Note bmap can have only 'incremental' ++ * set of events ++ */ ++ dev->evt_enable_bmap = regval; ++ ++ return(0); ++} ++ ++/* This function disables interrupts */ ++static int iproc_intr_disable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) ++{ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ ++ regval &= ~bmap; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ dev->evt_enable_bmap = regval; ++ ++ return(0); ++} ++ ++/* Verify this sequence with hw engg */ ++static int iproc_smbus_block_deinit(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ int rc; ++ ++ /* Disable all interrupts */ ++ regval = 0x0; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Check if a transaction is in progress */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ ++ /* Do not exit the function, since we are most likely shutting down */ ++ printk(KERN_ERR "%s: A transaction is still in progress," ++ "but still continuing ", __func__); ++ ++ } ++ ++ /* Disable SMBus block */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ ++ /* Wait for some time */ ++ udelay(100); ++ ++ /* Put the block under reset. Note the RESET bit in reg 0x0 is ++ * self clearing ++ */ ++ regval = CCB_SMB_CFG_RST_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ return(0); ++} ++ ++static u32 iproc_smb_funcs(struct i2c_adapter *adapter) ++{ ++ /* Note: Other SMBus commands can be supported if we know the requirements ++ * more precisely ++ */ ++ return (I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_QUICK | ++ I2C_FUNC_SMBUS_READ_BYTE); ++} ++ ++static struct i2c_algorithm iproc_smb_algorithm = { ++ /* .name = "iproc-smb", */ ++ .smbus_xfer = iproc_smb_xfer, ++ .master_xfer = NULL, ++ .functionality = iproc_smb_funcs, ++}; ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++static int __devinit iproc_smb_probe(struct platform_device *pdev) ++{ ++ int rc=0, irq, id; ++ struct iproc_smb_drv_int_data *dev; ++ struct i2c_adapter *adap; ++ struct resource *iomem; ++ struct resource *ioarea; ++ ++ if (pdev->dev.of_node) { ++ id = of_alias_get_id(pdev->dev.of_node, "i2c-controller");; ++ } else { ++ id = pdev->id; ++ } ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: Entering probe\n", __func__); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Get register memory resource */ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (!iomem) { ++ ++ printk(KERN_ERR "%s: No mem resource\n", __func__); ++ ++ return -ENODEV; ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot iomem 0x%p\n", iomem); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Get the interrupt number */ ++ irq = platform_get_irq(pdev, 0); ++ ++ if (irq == -ENXIO) { ++ if (brcm_get_hx4_model() == 0) { ++ printk(KERN_ERR "%s: No irq resource\n", __func__); ++ return -ENODEV; ++ } ++ /* Accton AS4610-54 or DNI-3448P */ ++ if (id == 0) { ++ irq = 127; ++ } else if (id == 1) { ++ irq = 128; ++ } else { ++ printk(KERN_ERR "%s: No irq resource\n", __func__); ++ return -ENODEV; ++ } ++ } ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot irqnum %d\n", irq); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Mark the memory region as used */ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), ++ pdev->name); ++ if (!ioarea) { ++ ++ printk(KERN_ERR "%s: SMBus region already claimed\n", __func__); ++ ++ return -EBUSY; ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot ioarea 0x%p\n", ioarea); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Allocate memory for driver's internal data structure */ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ ++ if (!dev) { ++ ++ printk(KERN_ERR "%s: Couldn't allocate memory for driver's internaldb\n", __func__); ++ ++ rc = -ENOMEM; ++ ++ goto err_release_mem_region; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot dev 0x%p\n", dev); ++#endif /* IPROC_SMB_DBG */ ++ ++ dev->dev = &pdev->dev; ++ init_MUTEX(&dev->xfer_lock); ++ init_completion(&dev->ses_done); ++ dev->irq = irq; ++ ++ dev->block_base_addr = ioremap(iomem->start, resource_size(iomem)); ++ ++ if (!dev->block_base_addr) { ++ ++ printk(KERN_ERR "%s: ioremap of register space failed\n", __func__); ++ ++ rc = -ENOMEM; ++ ++ goto err_free_dev_mem; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n ==== Got block_base_addr=0x%08X\n", (unsigned int)dev->block_base_addr); ++ /* iproc_dump_smb_regs(dev); */ ++#endif /* IPROC_SMB_DBG */ ++ ++ dev->enable_evts = ENABLE_INTR; /* Default value, can be changed after ++ initial testing */ ++ ++ platform_set_drvdata(pdev, dev); ++ ++ adap = &dev->adapter; ++ i2c_set_adapdata(adap, dev); /* Verify if this place is OK */ ++ adap->owner = THIS_MODULE; ++ adap->class = UINT_MAX; /* Can be used by any I2C device */ ++ snprintf(adap->name, sizeof(adap->name), "iproc-smb%d", id); ++ adap->algo = &iproc_smb_algorithm; ++ adap->dev.parent = &pdev->dev; /* */ ++ adap->nr = id; ++ adap->dev.of_node = pdev->dev.of_node; ++ ++ /* Init internal regs, disable intrs (and then clear intrs), set fifo ++ * thresholds, etc. ++ */ ++ iproc_smbus_block_init(dev); ++ ++ /* Register ISR handler */ ++ rc = request_irq(dev->irq, iproc_smb_isr, IRQF_SHARED, pdev->name, dev); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: failed to request irq %d, rc=%d\n", __func__, dev->irq, rc); ++ ++ goto err_smb_deinit; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nrequest_irq succeeded\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* ++ * I2C device drivers may be active on return from ++ * i2c_add_numbered_adapter() ++ */ ++ rc = i2c_add_numbered_adapter(adap); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: Failed to add I2C adapter, rc=%d\n", ++ __func__, rc); ++ ++ goto err_free_irq; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\ni2c_add_numbered_adapter succeeded\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ of_i2c_register_devices(adap); ++ /* Turn on default set of interrupts */ ++ /* For Rx, enable RX fifo full, threshold hit interrupts. Other rx ++ * interrupts will be set in the read/recv transactions, as required ++ * For Tx, enable fifo under run intr. Other intrs will be set in send ++ * write access functions ++ */ ++ iproc_intr_enable(dev, CCB_SMB_MSTRRXFIFOFULLEN_MASK); ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\niproc_intr_enable complete, intrs enabled\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ rc = proc_init(pdev); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: Failed to install procfs entry, rc=%d\n", ++ __func__, rc); ++ ++ goto err_proc_term; ++ ++ } ++ ++ dev->next = iproc_smbus_list; ++ iproc_smbus_list = dev; ++ ++#ifdef IPROC_SMB_DBG ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "%s: probe successful", __func__); ++ ++#endif /* IPROC_SMB_DBG */ ++ ++ return 0; ++ ++err_proc_term: ++ proc_term(pdev); ++ ++err_free_irq: ++ free_irq(dev->irq, dev); ++ ++err_smb_deinit: ++ iproc_smbus_block_deinit(dev); ++ ++ iounmap(dev->block_base_addr); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++err_free_dev_mem: ++ kfree(dev); ++ ++err_release_mem_region: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ printk(KERN_ERR "%s: probe failed, error=%d", __func__, rc); ++ ++ return (rc); ++} ++ ++static int iproc_smb_remove(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct resource *iomem; ++ unsigned int regval; ++ ++ /* Disable interrupts. */ ++ /* Verify: Should we wait for any in-progress xact to complete? */ ++ iproc_intr_disable(dev, ~0); ++ ++ /* Disable SMbus block */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ i2c_del_adapter(&dev->adapter); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ free_irq(dev->irq, dev); ++ ++ iproc_smbus_block_deinit(dev); ++ ++ iounmap(dev->block_base_addr); ++ ++ kfree(dev); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ return 0; ++} ++ ++static int iproc_smb_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return (0); ++} ++ ++static int iproc_smb_resume(struct platform_device *pdev) ++{ ++ return (0); ++} ++ ++static struct platform_device_id iproc_smb_id_table[] = { ++ { .name = "iproc-smb", 0 }, ++}; ++MODULE_DEVICE_TABLE(platform, iproc_smb_id_table); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id bcm_iproc_smb_of_match[] = { ++ { .compatible = "iproc-smb" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_smb_of_match); ++#endif ++ ++static struct platform_driver iproc_smb_driver = { ++ .driver = { ++ .name = "iproc-smb", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_iproc_smb_of_match, ++ }, ++ .probe = iproc_smb_probe, ++ .remove = iproc_smb_remove, ++ .suspend = iproc_smb_suspend, ++ .resume = iproc_smb_resume, ++ .id_table = iproc_smb_id_table, ++}; ++ ++ ++static int __init iproc_smb_init(void) ++{ ++ int rc; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "%s: Entering init", __func__); ++#endif /* IPROC_SMB_DBG */ ++ ++ gProcParent = proc_mkdir(PROC_GLOBAL_PARENT_DIR, NULL); ++ ++ if (gProcParent == NULL) { ++ ++ printk(KERN_ERR "%s: SMBus driver procfs failed\n", __func__); ++ ++ return -ENOMEM; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nproc_mkdir succeeded, gProcParent=0x%08X\n", (unsigned int)gProcParent); ++#endif /* IPROC_SMB_DBG */ ++ ++ rc = platform_driver_register(&iproc_smb_driver); ++ ++ if (rc < 0) { ++ ++ printk(KERN_ERR "%s: SMBus driver init failed, error %d\n", __func__, rc); ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: Called platform_driver_register, rc=%d\n", __func__, rc); ++#endif /* IPROC_SMB_DBG */ ++ ++ ++ iproc_smbus_list = NULL; ++ ++ /* Should we set RESET bit (reg 0x0) here?: Not necessary as per hw engg */ ++ ++ return rc; ++} ++ ++static void __exit iproc_smb_exit(void) ++{ ++ platform_driver_unregister(&iproc_smb_driver); ++ ++ remove_proc_entry(PROC_GLOBAL_PARENT_DIR, NULL); ++} ++ ++module_init(iproc_smb_init); ++module_exit(iproc_smb_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("IPROC I2C (SMBus) Bus Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus.h b/drivers/bcmdrivers/smbus/iproc_smbus.h +new file mode 100644 +index 0000000..d2c4973 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch new file mode 100644 index 00000000..d6f033eb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus.h.patch @@ -0,0 +1,195 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus.h +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_H__ ++#define __IPROC_SMBUS_H__ ++ ++#define IPROC_I2C_INVALID_ADDR 0xFF ++ ++#define MAX_PROC_BUF_SIZE 256 ++#define MAX_PROC_NAME_SIZE 15 ++#define PROC_GLOBAL_PARENT_DIR "iproc-i2c" ++#define PROC_ENTRY_DEBUG "iproc-i2c-dbg" ++ ++#define IPROC_SMB_MAX_RETRIES 35 ++ ++#define GETREGFLDVAL(regval, mask, startbit) (((regval) & (mask)) >> (startbit)) ++ ++#define SETREGFLDVAL(regval, fldval, mask, startbit) regval = \ ++ (regval & ~(mask)) | \ ++ ((fldval) << (startbit)) ++ ++/* Enum to specify clock speed. The user will provide it during initialization. ++ * If needed, it can be changed dynamically ++ */ ++typedef enum iproc_smb_clk_freq { ++ I2C_SPEED_100KHz = 0, ++ I2C_SPEED_400KHz = 1, ++ I2C_SPEED_INVALID = 255 ++} smb_clk_freq_t; ++ ++/* This enum will be used to notify the user of status of a data transfer ++ * request ++ */ ++typedef enum iproc_smb_error_code { ++ I2C_NO_ERR = 0, ++ I2C_TIMEOUT_ERR = 1, ++ I2C_INVALID_PARAM_ERR = 2, /* Invalid parameter(s) passed to the driver */ ++ I2C_OPER_IN_PROGRESS = 3, /* The driver API was called before the present ++ transfer was completed */ ++ I2C_OPER_ABORT_ERR = 4, /* Transfer aborted unexpectedly, for example a NACK ++ received, before last byte was read/written */ ++ I2C_FUNC_NOT_SUPPORTED = 5, /* Feature or function not supported ++ (e.g., 10-bit addresses, or clock speeds ++ other than 100KHz, 400KHz) */ ++} iproc_smb_error_code_t; ++ ++/* Counters will be used mainly for testing and debugging */ ++struct iproc_smb_counters { ++ unsigned int num_read_requests; ++ unsigned int num_write_requests; ++ unsigned int num_read_errors; ++ unsigned int num_write_errors; ++ unsigned int mstr_rx_evt_cnt; /* ISR counter to check recv event */ ++ unsigned int mstr_start_busy_cnt; /* ISR counter to checking xact sts */ ++ unsigned int mstr_rx_fifo_full_cnt; /* ISR counter to detect rx fifo full */ ++ unsigned int last_int_sts; /* last value of intr status reg */ ++}; ++ ++ ++/* This enum may be used in a call back function to provide the user of the ++ * type of request sent by the user. It can also be used for testing and ++ * debugging purposes ++ */ ++typedef enum iproc_smb_message_type { ++ I2C_DISABLE_MSG = 0, /* To be used after hardware initialization. ++ Driver will _not_ respond to API calls */ ++ I2C_ENABLE_MSG = 1, /* Used after hardware initialization, if required. ++ Driver will start responding to API calls. ++ Will not (re-)program the hardware. */ ++ I2C_READ_MSG = 2, /* I2C read request from application */ ++ I2C_WRITE_MSG = 3 /* I2C write request from application */ ++} iproc_smb_message_type_t; ++ ++/* For debugging purposes, we will store the information about the last ++ * (latest) transfer request from the client application ++ */ ++struct iproc_smb_dbg_trans_info ++{ ++ iproc_smb_message_type_t i2c_last_mesg_type; ++ unsigned int i2c_last_dev_addr; ++ unsigned int i2c_last_num_bytes_xfer_req; ++}; ++ ++struct procfs { ++ char name[MAX_PROC_NAME_SIZE]; ++ struct proc_dir_entry *parent; ++}; ++ ++/* This structure will be used internally by the driver to maintain its ++ * configuration information as well as information programmed in to the ++ * hardware ++ */ ++struct iproc_smb_drv_int_data { ++ struct device *dev; ++ struct iproc_smb_drv_int_data *next; ++ ++ int irq; ++ ++ unsigned int drv_state_init; /* 1 = Initialized, 0 = not initialized */ ++ ++ unsigned int drv_state_open; /* 1 = Accepting transaction requests, ++ 0 = Not accepting transaction requests */ ++ smb_clk_freq_t clk_speed; ++ ++ void __iomem *block_base_addr; /* iomapped virtual base address for ++ register access */ ++ ++ struct i2c_adapter adapter; ++ ++ unsigned int i2c_slave_addr; /* Up to four 7-bit SMB slave addresses can be ++ assigned, we will assume only one for now. ++ Valid only if SMBus will act as a slave ++ device */ ++ ++ struct semaphore xfer_lock; /* Lock for data transfer */ ++ ++ struct completion ses_done; /* To signal the command completion */ ++ ++ struct procfs proc; ++ ++ volatile int debug; ++ ++ unsigned int master_rx_fifo_thr; /* Master FIFO threshold. Interrupt will be ++ generated if the threshold is exceeded */ ++ ++ unsigned int slave_rx_fifo_thr; /* Slave FIFO threshold. Interrupt will be ++ generated if the threshold is exceeded */ ++ ++ unsigned int enable_evts; /* If true, enable interrupts. If false, ++ disable interrupts. Default is false */ ++ unsigned int evt_enable_bmap; /* Bit map of events enabled by the driver */ ++ ++ struct iproc_smb_counters smb_counters; /* Statistics maintained by driver. A caller ++ can request them through an API */ ++}; ++ ++/* Data to be supplied by the platform to initialise the IPROC SMBus (I2C). ++ * block ++ * init: Function called during driver initialization. Used by platform to ++ * configure GPIO functions and similar. ++ */ ++struct iproc_smb_platform_data { ++ int (*init)(struct iproc_smb_drv_int_data *iproc_i2c_info_ptr, int flags); ++ ++ unsigned int flags; ++}; ++ ++/* This structure will be used by the user during driver initialization to pass ++ * initial configuration information to the driver ++ */ ++struct iproc_smb_init_params { ++ unsigned int intr_mode; /* TRUE (1) for enabling interrupt mode, ++ FALSE (0) for polling mode */ ++ unsigned int clock_freq; /* 0=100KHz, 1=400KHz */ ++ void (*i2c_callback_func)(unsigned char *data); /* Application can ++ register a callback ++ function for driver to ++ notify the application ++ of any asynchronous ++ event(s), or exception. ++ Can be NULL */ ++}; ++ ++/* Structure used to pass information to read/write functions. */ ++struct iproc_xact_info { ++ bool cmd_valid; /* true if command field below is valid. Otherwise, false */ ++ unsigned short command; /* Passed by caller to send SMBus command code */ ++ unsigned char *data; /* actual data pased by the caller */ ++ unsigned int size; /* Size of data buffer passed */ ++ unsigned short flags; /* Sent by caller specifying PEC, 10-bit addresses */ ++ unsigned char smb_proto; /* SMBus protocol to use to perform transaction */ ++}; ++ ++#define XACT_TIMEOUT (msecs_to_jiffies(100)) /* Verify if 100 is OK */ ++ ++#endif /* __IPROC_SMBUS_H__ */ +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus_defs.h b/drivers/bcmdrivers/smbus/iproc_smbus_defs.h +new file mode 100644 +index 0000000..856418a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch new file mode 100644 index 00000000..a6c8d2ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch @@ -0,0 +1,53 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus_defs.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_DEFS_H__ ++#define __IPROC_SMBUS_DEFS_H__ ++ ++/* Transaction error codes defined in Master command register (0x30) */ ++#define MSTR_STS_XACT_SUCCESS 0 ++#define MSTR_STS_LOST_ARB 1 ++#define MSTR_STS_NACK_FIRST_BYTE 2 ++#define MSTR_STS_NACK_NON_FIRST_BYTE 3 /* NACK on a byte other than ++ the first byte */ ++#define MSTR_STS_TTIMEOUT_EXCEEDED 4 ++#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5 ++#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6 ++ ++/* SMBUS protocol values defined in register 0x30 */ ++#define SMBUS_PROT_QUICK_CMD 0 ++#define SMBUS_PROT_SEND_BYTE 1 ++#define SMBUS_PROT_RECV_BYTE 2 ++#define SMBUS_PROT_WR_BYTE 3 ++#define SMBUS_PROT_RD_BYTE 4 ++#define SMBUS_PROT_WR_WORD 5 ++#define SMBUS_PROT_RD_WORD 6 ++#define SMBUS_PROT_BLK_WR 7 ++#define SMBUS_PROT_BLK_RD 8 ++#define SMBUS_PROT_PROC_CALL 9 ++#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10 ++ ++#define BUS_BUSY_COUNT 100000 /* Number can be changed later */ ++ ++#define DISABLE_INTR 0 ++#define ENABLE_INTR 1 ++#endif /* __IPROC_SMBUS_DEFS_H__ */ +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus_regs.h b/drivers/bcmdrivers/smbus/iproc_smbus_regs.h +new file mode 100644 +index 0000000..197be7d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch new file mode 100644 index 00000000..17eac90f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch @@ -0,0 +1,296 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus_regs.h +@@ -0,0 +1,290 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_REGS_H__ ++#define __IPROC_SMBUS_REGS_H__ ++ ++/* --- */ ++#define CCB_SMB_CFG_REG 0x0 ++ ++#define CCB_SMB_CFG_RST_MASK 0x80000000 ++#define CCB_SMB_CFG_RST_SHIFT 31 ++ ++#define CCB_SMB_CFG_SMBEN_MASK 0x40000000 ++#define CCB_SMB_CFG_SMBEN_SHIFT 30 ++ ++#define CCB_SMB_CFG_BITBANGEN_MASK 0x20000000 ++#define CCB_SMB_CFG_BITBANGEN_SHIFT 29 ++ ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000 ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28 ++ ++#define CCB_SMB_CFG_PROMISCMODE_MASK 0x08000000 ++#define CCB_SMB_CFG_PROMISCMODE_SHIFT 27 ++ ++#define CCB_SMB_CFG_TSTMPCNTEN_MASK 0x04000000 ++#define CCB_SMB_CFG_TSTMPCNTEN_SHIFT 26 ++ ++#define CCB_SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000 ++#define CCB_SMB_CFG_MSTRRTRYCNT_SHIFT 16 ++ ++ ++/* --- */ ++#define CCB_SMB_TIMGCFG_REG 0x4 ++ ++#define CCB_SMB_TIMGCFG_MODE400_MASK 0x80000000 ++#define CCB_SMB_TIMGCFG_MODE400_SHIFT 31 ++ ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000 ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_SHIFT 24 ++ ++#define CCB_SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000 ++#define CCB_SMB_TIMGCFG_PERSLVSTR_SHIFT 16 ++ ++#define CCB_SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00 ++#define CCB_SMB_TIMGCFG_IDLTIME_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_ADDR_REG 0x8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR3_MASK 0x80000000 ++#define CCB_SMB_EN_NIC_SMBADDR3_SHIFT 31 ++ ++#define CCB_SMB_NIC_SMBADDR3_MASK 0x7F000000 ++#define CCB_SMB_NIC_SMBADDR3_SHIFT 24 ++ ++#define CCB_SMB_EN_NIC_SMBADDR2_MASK 0x00800000 ++#define CCB_SMB_EN_NIC_SMBADDR2_SHIFT 23 ++ ++#define CCB_SMB_NIC_SMBADDR2_MASK 0x007F0000 ++#define CCB_SMB_NIC_SMBADDR2_SHIFT 16 ++ ++#define CCB_SMB_EN_NIC_SMBADDR1_MASK 0x00008000 ++#define CCB_SMB_EN_NIC_SMBADDR1_SHIFT 15 ++ ++#define CCB_SMB_NIC_SMBADDR1_MASK 0x00007F00 ++#define CCB_SMB_NIC_SMBADDR1_SHIFT 8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR0_MASK 0x00000080 ++#define CCB_SMB_EN_NIC_SMBADDR0_SHIFT 7 ++ ++#define CCB_SMB_NIC_SMBADDR0_MASK 0x0000007F ++#define CCB_SMB_NIC_SMBADDR0_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_MSTRFIFOCTL_REG 0xC ++ ++#define CCB_SMB_MSTRRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_MSTRTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_MSTRTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_MSTRRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_MSTRRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_MSTRRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_SLVFIFOCTL_REG 0x10 ++ ++#define CCB_SMB_SLVRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_SLVRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_SLVTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_SLVTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_SLVRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_SLVRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_SLVRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_SLVRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_BITBANGCTL_REG 0x14 ++ ++#define CCB_SMB_SMBCLKIN_MASK 0x80000000 ++#define CCB_SMB_SMBCLKIN_SHIFT 31 ++ ++#define CCB_SMB_SMBCLKOUTEN_MASK 0x40000000 ++#define CCB_SMB_SMBCLKOUTEN_SHIFT 30 ++ ++#define CCB_SMB_SMBDATAIN_MASK 0x20000000 ++#define CCB_SMB_SMBDATAIN_SHIFT 29 ++ ++#define CCB_SMB_SMBDATAOUTEN_MASK 0x10000000 ++#define CCB_SMB_SMBDATAOUTEN_SHIFT 28 ++ ++/* --- */ ++#define CCB_SMB_MSTRCMD_REG 0x30 ++ ++#define CCB_SMB_MSTRSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_MSTRSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_MSTRABORT_MASK 0x40000000 ++#define CCB_SMB_MSTRABORT_SHIFT 30 ++ ++#define CCB_SMB_MSTRSTS_MASK 0x0E000000 ++#define CCB_SMB_MSTRSTS_SHIFT 25 ++ ++#define CCB_SMB_MSTRSMBUSPROTO_MASK 0x00001E00 ++#define CCB_SMB_MSTRSMBUSPROTO_SHIFT 9 ++ ++#define CCB_SMB_MSTRPEC_MASK 0x00000100 ++#define CCB_SMB_MSTRPEC_SHIFT 8 ++ ++#define CCB_SMB_MSTRRDBYTECNT_MASK 0x000000FF ++#define CCB_SMB_MSTRRDBYTECNT_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_SLVCMD_REG 0x34 ++ ++#define CCB_SMB_SLVSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_SLVSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_SLVABORT_MASK 0x40000000 ++#define CCB_SMB_SLVABORT_SHIFT 30 ++ ++#define CCB_SMB_SLVSTS_MASK 0x03800000 ++#define CCB_SMB_SLVSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVPEC_MASK 0x00000100 ++#define CCB_SMB_SLVPEC_SHIFT 8 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTEN_REG 0x38 ++ ++#define CCB_SMB_MSTRRXFIFOFULLEN_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLEN_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTEN_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTEN_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYEN_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYEN_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDEN_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDEN_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLEN_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLEN_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITEN_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTEN_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTEN_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYEN_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYEN_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDEN_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDEN_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTEN_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTEN_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTSTS_REG 0x3C ++ ++#define CCB_SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTSTS_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTSTS_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYSTS_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYSTS_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDSTS_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDSTS_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLSTS_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLSTS_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTSTS_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTSTS_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYSTS_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDSTS_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDSTS_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTSTS_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTSTS_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATAWR_REG 0x40 ++ ++#define CCB_SMB_MSTRWRSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRWRSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRWRDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATARD_REG 0x44 ++ ++#define CCB_SMB_MSTRRDSTS_MASK 0xC0000000 ++#define CCB_SMB_MSTRRDSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRDPECERR_MASK 0x20000000 ++#define CCB_SMB_MSTRRDPECERR_SHIFT 29 ++ ++#define CCB_SMB_MSTRRDDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRRDDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATAWR_REG 0x48 ++ ++#define CCB_SMB_SLVWRSTS_MASK 0x80000000 ++#define CCB_SMB_SLVWRSTS_SHIFT 31 ++ ++#define CCB_SMB_SLVWRDATA_MASK 0x000000FF ++#define CCB_SMB_SLVWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATARD_REG 0x4C ++ ++#define CCB_SMB_SLVRDSTS_MASK 0xC0000000 ++#define CCB_SMB_SLVRDSTS_SHIFT 30 ++ ++#define CCB_SMB_SLVRDERRSTS_MASK 0x30000000 ++#define CCB_SMB_SLVRDERRSTS_SHIFT 28 ++ ++#define CCB_SMB_SLVRDDATA_MASK 0x000000FF ++#define CCB_SMB_SLVRDDATA_SHIFT 0 ++ ++#endif /* __IPROC_SMBUS_REGS_H__ */ +diff --git a/drivers/bcmdrivers/timer/.gitignore b/drivers/bcmdrivers/timer/.gitignore +new file mode 100644 +index 0000000..d741861 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch new file mode 100644 index 00000000..797dc6c0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_.gitignore.patch @@ -0,0 +1,10 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/timer/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/timer/Kconfig b/drivers/bcmdrivers/timer/Kconfig +new file mode 100644 +index 0000000..9dc584f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch new file mode 100644 index 00000000..51aa314a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Kconfig.patch @@ -0,0 +1,12 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/timer/Kconfig +@@ -0,0 +1,6 @@ ++config IPROC_CCB_TIMER ++ tristate "ChipcommonB Timer support" ++ depends on ARCH_IPROC ++ help ++ This selects a driver for the ChipcommonB SP804 Timer on Broadcom ++ iProc chips. +diff --git a/drivers/bcmdrivers/timer/Makefile b/drivers/bcmdrivers/timer/Makefile +new file mode 100644 +index 0000000..630ff37 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch new file mode 100644 index 00000000..45041229 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_Makefile.patch @@ -0,0 +1,8 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/timer/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_IPROC_CCB_TIMER) += iproc_timer.o +diff --git a/drivers/bcmdrivers/timer/iproc_timer.c b/drivers/bcmdrivers/timer/iproc_timer.c +new file mode 100644 +index 0000000..b9d11fc diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch new file mode 100644 index 00000000..3d2f4445 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_timer_iproc_timer.c.patch @@ -0,0 +1,485 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/timer/iproc_timer.c +@@ -0,0 +1,479 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iproc_timer.h" ++ ++/* ++ * Configurations ++ */ ++#define DRV_NAME "iproc_ccb_timer" ++#define REFCLK_SOURCE "c_clk125" ++#define REFCLK_SOURCE_DEVID "iproc_slow" ++#define MAX_NUMBER_OF_TIMERS (4) ++ ++/* ++ * Register offset ++ */ ++#define TIMER_LOAD_OFFSET 0x00 ++#define TIMER_VALUE_OFFSET 0x04 ++#define TIMER_CONTROL_OFFSET 0x08 ++#define TIMER_INTCLR_OFFSET 0x0c ++#define TIMER_RIS_OFFSET 0x10 ++#define TIMER_MIS_OFFSET 0x14 ++ ++/* ++ * Timer Control Register Bits ++ */ ++#define TIMER_CTRL_16BIT (0 << 1) /* 16-bit counter mode */ ++#define TIMER_CTRL_32BIT (1 << 1) /* 32-bit counter mode */ ++#define TIMER_CTRL_IE (1 << 5) /* Interrupt enable */ ++#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic mode */ ++#define TIMER_CTRL_EN (1 << 7) /* Timer enable */ ++#define TIMER_CTRL_ONESHOTMODE (1 << 0) ++#define TIMER_CTRL_DIV1 (0 << 2) ++#define TIMER_CTRL_PREBY16 (1 << 2) ++#define TIMER_CTRL_PREBY256 (2 << 2) ++ ++/* In case we use physical addresses */ ++#define IO_ADDRESS(x) (x) ++ ++/* Timer instance */ ++typedef struct { ++ int32_t id; /* id for this timer */ ++ uint32_t base; /* timer base address */ ++ uint32_t vec; /* interrupt vector */ ++ int started; /* Whether it has started */ ++ uint64_t interval; /* Interval in ticks; 0 if not inited */ ++ int periodic; /* 1 for periodic; 0 for one-shot */ ++ uint32_t load; /* Actual value to load */ ++ iproc_timer_isr_t isr; /* User interrupt handler */ ++ void * cookie; /* Cookie for user isr */ ++ uint32_t prescale; /* Prescale bits */ ++} timer_map_t; ++ ++/* Actual number of timers */ ++static int timer_count; ++ ++/* Mapping from logical timer to physical timer */ ++static timer_map_t timers_map[MAX_NUMBER_OF_TIMERS]; ++ ++/* Reference clock */ ++static uint32_t timer_refclk; ++ ++/* ++ * Disable timer ++ */ ++static inline void ++hw_timer_disable(timer_map_t *ptimer) ++{ ++ register uint32_t timer_base; ++ ++ timer_base = ptimer->base; ++ writel( ++ readl(IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET)) & ~TIMER_CTRL_EN, ++ IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET) ++ ); ++ ++ /* Clear pending interrupt */ ++ writel(1, IO_ADDRESS(timer_base + TIMER_INTCLR_OFFSET)); ++} ++ ++/* ++ * Configure timer ++ */ ++int ++iproc_timer_configure(int timer_id, int periodic, uint64_t interval, ++ iproc_timer_isr_t isr, void *cookie) ++{ ++ timer_map_t *ptimer; ++ uint32_t ctrl = TIMER_CTRL_32BIT; ++ ++ if (timer_id < 0 || timer_id >= timer_count || ++ interval == 0 || interval > iproc_timer_get_max_interval()) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ /* Cannot configure while it's started */ ++ if (ptimer->started) { ++ return -EBUSY; ++ } ++ ++ /* Check how much we need to prescale */ ++ if ((interval >> 32) == 0) { ++ ptimer->prescale = 0; ++ ctrl |= TIMER_CTRL_DIV1; ++ } else { ++ if ((interval >> 36) == 0) { ++ ptimer->prescale = 4; ++ ctrl |= TIMER_CTRL_PREBY16; ++ } else { ++ ptimer->prescale = 8; ++ ctrl |= TIMER_CTRL_PREBY256; ++ } ++ } ++ ++ /* Actual value to load */ ++ ptimer->load = (uint32_t)(interval >> ptimer->prescale); ++ ++ /* Configure periodic/one-shot mode */ ++ ptimer->periodic = periodic; ++ if (periodic) { ++ ++ /* ++ * For periodic mode, don't enable interrupt if user isr is not set ++ * This is to avoid frequent IRQs and degrade system performance. ++ */ ++ if (isr) { ++ ctrl |= TIMER_CTRL_IE; ++ } ++ ctrl |= TIMER_CTRL_PERIODIC; ++ ++ } else { ++ /* For one-shot mode, interrupt must be enabled (to mark it stopped) */ ++ ctrl |= TIMER_CTRL_ONESHOTMODE | TIMER_CTRL_IE; ++ } ++ ++ /* Write to control register */ ++ writel(ctrl, IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET)); ++ ++ /* Record user specified arguments */ ++ ptimer->interval = interval; ++ ptimer->isr = isr; ++ ptimer->cookie = cookie; ++ ++ return 0; ++} ++ ++/* ++ * Start timer ++ */ ++int ++iproc_timer_start(int timer_id) ++{ ++ timer_map_t *ptimer; ++ register uint32_t timer_base; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ if (ptimer->interval == 0) { ++ return -EPERM; ++ } ++ ++ if (ptimer->started) { ++ return -EBUSY; ++ } ++ ++ ptimer->started = 1; ++ timer_base = ptimer->base; ++ writel(ptimer->load, IO_ADDRESS(timer_base + TIMER_LOAD_OFFSET)); ++ writel( ++ readl(IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET)) | TIMER_CTRL_EN, ++ IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET) ++ ); ++ ++ return 0; ++} ++ ++/* ++ * Stop timer ++ */ ++int ++iproc_timer_stop(int timer_id) ++{ ++ timer_map_t *ptimer; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ if (ptimer->started == 0) { ++ return 0; ++ } ++ ++ ptimer->started = 0; ++ hw_timer_disable(ptimer); ++ ++ return 0; ++} ++ ++/* ++ * Returns timer's counter ++ */ ++uint64_t ++iproc_timer_get_current_ticks(int timer_id) ++{ ++ timer_map_t *ptimer; ++ uint64_t ticks; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ if (!ptimer->interval || !ptimer->started) { ++ return 0; ++ } ++ ++ /* To return the elapsed ticks, not remaining ticks */ ++ ticks = ++ ptimer->load - readl(IO_ADDRESS(ptimer->base + TIMER_VALUE_OFFSET)); ++ ++ /* Scale back */ ++ return ticks << ptimer->prescale; ++} ++ ++/* ++ * Timer info ++ */ ++int ++iproc_timer_get_info(int timer_id, iproc_timer_info_t *info) ++{ ++ timer_map_t *ptimer; ++ ++ if (timer_id < 0 || timer_id >= timer_count || info == NULL) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ info->configured = ptimer->interval? 1 : 0; ++ info->started = ptimer->started; ++ info->periodic = ptimer->periodic; ++ info->interval = ptimer->interval; ++ info->isr = ptimer->isr; ++ info->cookie = ptimer->cookie; ++ ++ return 0; ++} ++ ++/* ++ * Ticking rate (reference clock frequency): ticks per second ++ */ ++uint32_t ++iproc_timer_get_ticking_rate(void) ++{ ++ return timer_refclk; ++} ++ ++/* ++ * Get max interval in ticks ++ */ ++uint64_t ++iproc_timer_get_max_interval(void) ++{ ++ return (uint64_t)0xFFFFFFFFULL << 8; ++} ++ ++/* ++ * Get number of timers ++ */ ++uint32_t ++iproc_timer_count(void) ++{ ++ return timer_count; ++} ++ ++/* ++ * IRQ handler for the timer ++ */ ++static irqreturn_t ++hw_timer_interrupt(int irq, void *dev_id) ++{ ++ timer_map_t *ptimer = (timer_map_t *)dev_id; ++ ++ /* Check if it's for us */ ++ if (!(readl(IO_ADDRESS(ptimer->base + TIMER_MIS_OFFSET)) & 1)) { ++ return IRQ_NONE; ++ } ++ ++ /* clear the interrupt */ ++ writel(1, IO_ADDRESS(ptimer->base + TIMER_INTCLR_OFFSET)); ++ ++ /* Double confirm if it's enabled by user */ ++ if (ptimer->interval && ptimer->started) { ++ ++ /* If it's one-shot, mark it 'stopped' first */ ++ if (ptimer->periodic == 0) { ++ ptimer->started = 0; ++ ++ /* It doesn't clear the EN bit automatically */ ++ writel( ++ readl( ++ IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET)) & ++ ~TIMER_CTRL_EN, ++ IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET) ++ ); ++ } ++ ++ /* Call user specified ISR */ ++ if (ptimer->isr) { ++ (*ptimer->isr)(ptimer->id, ptimer->cookie); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/*********************************************************************** ++ * Platform driver setup ++ ***********************************************************************/ ++ ++static int __devinit ++iproc_timer_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int i; ++ int ret = 0; ++ struct clk *clk; ++ ++ /* Retrieve reference clock frequency */ ++ clk = clk_get_sys(REFCLK_SOURCE_DEVID, REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ timer_refclk = (uint32_t)clk_get_rate(clk); ++ ++ /* Retrieve IRQ from resources (also determine number of timers) */ ++ timer_count = 0; ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no IRQ defined\n"); ++ ret = -ENODEV; ++ goto err2; ++ } ++ for(i = (int)res->start; i <= (int)res->end; i++) { ++ timers_map[timer_count].vec = i; ++ timer_count++; ++ } ++ ++ /* Retrieve register space (in virtual addresses) from resources */ ++ for(i=0; idev, "can't get resource for register space\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ timers_map[i].base = (uint32_t)res->start; ++ } ++ ++ /* Perform basic initialization */ ++ for(i=0; idev, "unable to allocate IRQ\n"); ++ goto err1; ++ } ++ } ++ ++ printk(KERN_INFO "iProc Timer driver: %u timers running at %uHz\n", ++ timer_count, timer_refclk); ++ ++ return 0; ++ ++err1: ++ for(i=0; i ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "usbh_cfg.h" ++ ++#include "bcm_usbh.h" ++ ++#define DEBUG ++#ifdef DEBUG ++#define dbg_printk(fmt, args...) printk(KERN_INFO "%s: " fmt, __func__, ## args) ++#else ++#define dbg_printk(fmt, args...) ++#endif ++ ++#define IPROC_USB2_CLK_CONTROL_ENABLE (0x1800C180) ++#define IPROC_USB2_CLK_CONTROL_ENABLE_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2_CLK_CONTROL_ENABLE) ++#define IPROC_USB2_CLK_CONTROL_PLL (0x1800C164) ++#define IPROC_USB2_CLK_CONTROL_PLL_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2_CLK_CONTROL_PLL) ++#define IPROC_STRAP_SKU_VECTOR (0x1810D500) ++#define IPROC_STRAP_SKU_VECTOR_VA HW_IO_PHYS_TO_VIRT(IPROC_STRAP_SKU_VECTOR) ++#define IPROC_IDM_USB2_RESET_CONTROL (0x18115800) ++#define IPROC_IDM_USB2_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_USB2_RESET_CONTROL) ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_IDM_USB2_IO_CONTROL_DIRECT USB2_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_USB2_IO_CONTROL_DIRECT) ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_XGPLL 0x1803fc2c ++#define IPROC_XGPLL_VA HW_IO_PHYS_TO_VIRT(IPROC_XGPLL) ++#define IPROC_USB_PHY_CTRL IPROC_WRAP_USBPHY_CTRL ++#define IPROC_USB_PHY_CTRL_VA HW_IO_PHYS_TO_VIRT(IPROC_USB_PHY_CTRL) ++#define IPROC_WRAP_MISC_STATUS 0x1803fc28 ++#define IPROC_WRAP_MISC_STATUS_VA HW_IO_PHYS_TO_VIRT(IPROC_WRAP_MISC_STATUS) ++#define IPROC_CLK_NDIV_40 0x80 ++#define IPROC_CLK_NDIV_20 0x8C ++#define USB_CLK_NDIV_MASK 0xFE7FFE00 ++#define USB_CLK_PLL_RESET_MASK 0xFF7FFE00 ++#define USB_CLK_PHY_RESET_MASK 0xFFFFFE00 ++#define USB_CLK_NDIV_40 0x30 ++#define USB_CLK_NDIV_20 0x60 ++#define ChipcommonA_GPIOIn_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOInput) ++#define ChipcommonA_GPIOOut_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOOut) ++#define ChipcommonA_GPIOOutEn_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOOutEn) ++#define SUPPLY_USBD_POWER 0xfffffffd ++#endif ++ ++#define IPROC_SKU_STRAP_MASK 0xC ++ ++struct usbh_ctrl_regs { ++ u32 mode; ++#define MODE_ULPI_TTL (1<<0) ++#define MODE_ULPI_PHY (1<<1) ++#define MODE_UTMI_TTL (1<<2) ++#define MODE_UTMI_PHY (1<<3) ++#define MODE_PORT_CFG(port, mode) ((mode) << (4 * port)) ++ ++ u32 strap_q; ++#define STRAP_PWR_STATE_VALID (1 << 7) /* ss_power_state_valid */ ++#define STRAP_SIM_MODE (1 << 6) /* ss_simulation_mode */ ++#define STRAP_OHCI_CNTSEL_SIM (1 << 5) /* ohci_0_cntsel_i_n */ ++#define STRAP_PWR_STATE_NXT_VALID (1 << 4) /* ss_nxt_power_state_valid_i */ ++#define STRAP_PWR_STATE_NXT_SHIFT 2 /* ss_next_power_state_i */ ++#define STRAP_PWR_STATE_NXT_MASK (3 << STRAP_PWR_STATE_NXT_SHIFT) ++#define STRAP_PWR_STATE_SHIFT 0 /* ss_power_state_i */ ++#define STRAP_PWR_STATE_MASK (3 << STRAP_PWR_STATE_SHIFT) ++ ++ u32 framelen_adj_q; ++ u32 framelen_adj_qx[USBH_NUM_PORTS]; ++ u32 misc; ++#define MISC_RESUME_R23_ENABLE (1 << 4) /* ss_utmi_backward_enb_i */ ++#define MISC_RESUME_R23_UTMI_PLUS_DISABLE (1 << 3) /* ss_resume_utmi_pls_dis_i */ ++#define MISC_ULPI_BYPASS_ENABLE (1 << 2) /* ulpi_bypass_en_i */ ++#define MISC_PORT_PWRDWN_OVERCURRENT (1 << 1) /* ss_autoppd_on_overcur_en_i */ ++#define MISC_OHCI_CLK_RESTART (1 << 0) /* app_start_clk_i */ ++ ++}; ++ ++struct usbh_priv { ++ atomic_t probe_done; ++ volatile int init_cnt; ++ struct mutex lock; ++ struct device *dev; ++ struct usbh_cfg hw_cfg; ++ struct clk *peri_clk; ++ struct clk *ahb_clk; ++ struct clk *opt_clk; ++ struct usbh_ctrl_regs __iomem *ctrl_regs; ++}; ++ ++static struct usbh_priv usbh_data; ++ ++int bcm_usbh_suspend(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_suspend); ++ ++int bcm_usbh_resume(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_resume); ++ ++/* ++ * Function to initialize USB host related low level hardware including PHY, ++ * clocks, etc. ++ * ++ * TODO: expand support for more than one host in the future if needed ++ */ ++int bcm_usbh_init(unsigned int host_index) ++{ ++#ifdef CONFIG_MACH_NS ++ int usb2_clk_cntrl, usb2_clk_enable, sku_vect; ++ ++ sku_vect = readl_relaxed(IPROC_STRAP_SKU_VECTOR_VA); ++ if ((sku_vect & IPROC_SKU_STRAP_MASK) != 0x0) ++ { ++ /* enable clocks */ ++ writel_relaxed(0xEA68, IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ ++ usb2_clk_cntrl = readl_relaxed(IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ // printk("USB clk control enable register is: %08x\n", usb2_clk_cntrl); ++ writel_relaxed(0xDD10C3, IPROC_USB2_CLK_CONTROL_PLL_VA); ++ ++ usb2_clk_enable = readl_relaxed(IPROC_USB2_CLK_CONTROL_PLL_VA); ++ // printk("USB clk enable register is: %08x\n", usb2_clk_enable); ++ writel_relaxed(0x0, IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ ++ usb2_clk_cntrl = readl_relaxed(IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ // printk("USB clk control enable register is: %08x\n", usb2_clk_cntrl); ++ } ++#endif ++ return 0; ++} ++ ++EXPORT_SYMBOL(bcm_usbh_init); ++ ++/* ++ * Function to terminate USB host related low level hardware including PHY, ++ * clocks, etc. ++ * ++ * TODO: expand support for more than one host in the future if needed ++ */ ++int bcm_usbh_term(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_term); ++ ++int InUSBDMode(void) ++{ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ int usbd_detect; ++ usbd_detect = readl_relaxed(ChipcommonA_GPIOIn_VA); ++ if (usbd_detect & 1) ++ { ++ printk("%s: %d gpioin val %08x, ohci host mode will not be functional since in USBD mode\n", __FUNCTION__, __LINE__, usbd_detect); ++ printk("%s: %d to make ohci host mode work, appropriate jumper is needed on the board. Please refer to board schematics.\n", ++ __FUNCTION__, __LINE__); ++ } ++ ++ return (usbd_detect & 1); ++#else ++ return 0; ++#endif ++} ++ ++static int __devinit usbh_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct resource *iomem, *ioarea; ++ ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ ++ if (pdev->dev.platform_data == NULL) { ++ dev_err(&pdev->dev, "platform_data missing\n"); ++ ret = -EFAULT; ++ goto err_exit; ++ } ++ memcpy(&usbh_data.hw_cfg, pdev->dev.platform_data, ++ sizeof(usbh_data.hw_cfg)); ++ usbh_data.dev = &pdev->dev; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ dev_err(&pdev->dev, "no mem resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ /* mark the memory region as used */ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), ++ pdev->name); ++ if (!ioarea) { ++ dev_err(&pdev->dev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ /* now map the I/O memory */ ++ usbh_data.ctrl_regs = (struct usbh_ctrl_regs __iomem *) ++ ioremap(iomem->start, sizeof(usbh_data.ctrl_regs)); ++ if (!usbh_data.ctrl_regs) { ++ dev_err(&pdev->dev, "failed to remap registers\n"); ++ ret = -ENOMEM; ++ goto err_free_mem_region; ++ } ++ ++ platform_set_drvdata(pdev, &usbh_data); ++ mutex_init(&usbh_data.lock); ++ usbh_data.init_cnt = 0; ++ atomic_set(&usbh_data.probe_done, 1); ++ ++ return 0; ++ ++err_free_mem_region: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ return ret; ++} ++ ++static int __devexit usbh_remove(struct platform_device *pdev) ++{ ++ struct usbh_priv *drv_data = platform_get_drvdata(pdev); ++ struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ atomic_set(&drv_data->probe_done, 0); ++ platform_set_drvdata(pdev, NULL); ++ iounmap(drv_data->ctrl_regs); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ ++ return 0; ++} ++ ++static struct platform_driver usbh_driver = ++{ ++ .driver = { ++ .name = "usbh", ++ .owner = THIS_MODULE, ++ }, ++ .probe = usbh_probe, ++ .remove = usbh_remove, ++}; ++ ++static int __init usbh_init(void) ++{ ++ int usb2_reset_state; ++ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ int clk_enable, k; ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ unsigned int iClk; ++#endif ++ unsigned int USBClk, usbdgpiopwr, pllStatus; ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ /* turn off power for USB device connected to the host */ ++ usbdgpiopwr = readl_relaxed(ChipcommonA_GPIOOut_VA); ++ usbdgpiopwr |= 0x2; ++ writel_relaxed(usbdgpiopwr, ChipcommonA_GPIOOut_VA); ++ writel_relaxed(0x2, ChipcommonA_GPIOOutEn_VA); ++#endif ++ ++ /* Do USB PHY reset */ ++ mdelay(100); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ /* bring phy pll out of reset if not done already */ ++ if ((USBClk & 0x01000000) == 0 ) ++ { ++ USBClk |= 0x01000000; ++ writel_relaxed(USBClk, IPROC_USB_PHY_CTRL_VA); ++ pllStatus = readl_relaxed(IPROC_WRAP_MISC_STATUS_VA); ++ for (k = 0; k < 100000; k++) ++ { ++ if ((pllStatus & 2) == 2) ++ { ++ printk("USB phy pll locked\n"); ++ break; ++ } ++ pllStatus = readl_relaxed(IPROC_WRAP_MISC_STATUS_VA); ++ } ++ } ++ writel_relaxed(USBClk & (~(1<<23)), IPROC_USB_PHY_CTRL_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock is: %08x\n", clk_enable); ++ clk_enable |= 1; ++ writel_relaxed(clk_enable, IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock now is: %08x\n", clk_enable); ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ iClk = readl_relaxed(IPROC_XGPLL_VA); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ if ((iClk & 0xff) == IPROC_CLK_NDIV_40) ++ { ++ writel_relaxed((USBClk & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ } ++ else if ((iClk & 0xff) == IPROC_CLK_NDIV_20) ++ { ++ writel_relaxed((USBClk & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ } ++#endif ++ mdelay(100); ++ writel_relaxed(USBClk | (1<<23), IPROC_USB_PHY_CTRL_VA); ++ udelay(100); ++#endif ++#if defined(CONFIG_MACH_NSP) ++ int clk_enable; ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock is: %08x\n", clk_enable); ++ clk_enable |= 1; ++ writel_relaxed(clk_enable, IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock now is: %08x\n", clk_enable); ++#endif ++ ++ usb2_reset_state = readl_relaxed(IPROC_IDM_USB2_RESET_CONTROL_VA); ++ printk("Initial usb2_reset_state is: %08x\n", usb2_reset_state); ++ if ((usb2_reset_state & 1) == 1) ++ { ++ writel_relaxed(0x0, IPROC_IDM_USB2_RESET_CONTROL_VA); ++ usb2_reset_state = readl_relaxed(IPROC_IDM_USB2_RESET_CONTROL_VA); ++ printk("usb2_reset_state is set and now it is: %08x\n", usb2_reset_state); ++ } ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ /* supply power for USB device connected to the host */ ++ mdelay(100); ++ usbdgpiopwr = readl_relaxed(ChipcommonA_GPIOOut_VA); ++ usbdgpiopwr &= SUPPLY_USBD_POWER; ++ writel_relaxed(usbdgpiopwr, ChipcommonA_GPIOOut_VA); ++ writel_relaxed(0x2, ChipcommonA_GPIOOutEn_VA); ++#endif ++ return platform_driver_register(&usbh_driver); ++} ++ ++static void __exit usbh_exit(void) ++{ ++ platform_driver_unregister(&usbh_driver); ++} ++ ++module_init(usbh_init); ++module_exit(usbh_exit); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("Broadcom USB host low-level driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/usb2h/bcm_usbh.h b/drivers/bcmdrivers/usb2h/bcm_usbh.h +new file mode 100644 +index 0000000..019589a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch new file mode 100644 index 00000000..d11e8cab --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_bcm_usbh.h.patch @@ -0,0 +1,31 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/bcm_usbh.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BCM_USBH_H_ ++#define _BCM_USBH_H_ ++ ++extern int bcm_usbh_init(unsigned int host_index); ++extern int bcm_usbh_term(unsigned int host_index); ++extern int bcm_usbh_suspend(unsigned int host_index); ++extern int bcm_usbh_resume(unsigned int host_index); ++ ++#endif +diff --git a/drivers/bcmdrivers/usb2h/ehci-bcm.c b/drivers/bcmdrivers/usb2h/ehci-bcm.c +new file mode 100644 +index 0000000..62534b8 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch new file mode 100644 index 00000000..09f5fc32 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ehci-bcm.c.patch @@ -0,0 +1,389 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/ehci-bcm.c +@@ -0,0 +1,383 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "bcm_usbh.h" ++ ++#define BCM_USBEHCI_MODULE_DESCRIPTION "Broadcom USB EHCI driver" ++#define BCM_USBEHCI_MODULE_VERSION "1.0.0" ++ ++#define BCM_USBEHCI_IRQF_FLAGS (IRQF_DISABLED | IRQF_SHARED) ++#define BCM_USBEHCI_NAME "bcm-ehci" ++ ++#define EHCI_INFO(pdev, fmt, args...) dev_info(&pdev->dev, fmt, ## args) ++#define EHCI_ERR(pdev, fmt, args...) dev_err(&pdev->dev, fmt, ## args) ++#define BCM_USB_FIFO_THRESHOLD 0x00800040 ++ ++struct usb_cfg ++{ ++ void *virt_reg_base; ++ struct usb_hcd *hcd; ++}; ++ ++extern int usb_disabled(void); ++static int hcd_init(struct usb_hcd *hcd); ++ ++static const struct hc_driver ehci_hcd_driver = ++{ ++ .description = hcd_name, ++ .product_desc = BCM_USBEHCI_NAME, ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ehci_irq, ++ .flags = HCD_USB2 | HCD_MEMORY | HCD_LOCAL_MEM, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .reset = hcd_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ehci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++#ifdef CONFIG_PM ++ .bus_suspend = ehci_bus_suspend, ++ .bus_resume = ehci_bus_resume, ++#endif ++ .relinquish_port = ehci_relinquish_port, ++ .port_handed_over = ehci_port_handed_over, ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++int hcd_init(struct usb_hcd *hcd) ++{ ++ struct ehci_hcd *ehci; ++ int err; ++ ++ if (!hcd) { ++ printk(KERN_ERR "invalid hcd pointer in %s\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ ehci = hcd_to_ehci(hcd); ++ ++ if ((err = ehci_halt(ehci)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_halt() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ if ((err = ehci_init(hcd)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_init() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ /* ++ * Not sure why this is not set by ehci_init(). Convention seems to be ++ * to do it here for reasons unknown. This is a "packed release number". ++ */ ++ ehci->sbrn = 0x20; ++ ++ if ((err = ehci_reset(ehci)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_reset() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int bcm_ehci_probe(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb; ++ struct usb_hcd *hcd; ++ struct ehci_hcd *ehci; ++ struct resource *iomem, *ioarea; ++ int ret, irq; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ EHCI_ERR(pdev, "no mem resource\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* get the irq info */ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ EHCI_ERR(pdev, "no irq resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), pdev->name); ++ if (!ioarea) { ++ EHCI_ERR(pdev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ usb = kzalloc(sizeof(*usb), GFP_KERNEL); ++ if (!usb) { ++ EHCI_ERR(pdev, "unable to allocate memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_iomem; ++ } ++ ++ usb->virt_reg_base = ioremap(iomem->start, resource_size(iomem)); ++ if (!usb->virt_reg_base) { ++ EHCI_ERR(pdev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_free_private_mem; ++ } ++ ++ /* enable clock and PHY */ ++ ret = bcm_usbh_init(pdev->id); ++ if (ret < 0) { ++ EHCI_ERR(pdev, "clock and PHY initialization failed\n"); ++ goto err_io_unmap; ++ } ++ ++ hcd = usb_create_hcd(&ehci_hcd_driver, &pdev->dev, (char *)pdev->name); ++ if (!hcd) { ++ EHCI_ERR(pdev, "usb_create_hcd failed\n"); ++ ret = -ENOMEM; ++ goto err_usb_term; ++ } ++ ++ /* struct ehci_regs def'd in Linux ehci.h which is included by Linux ehci-hcd.c */ ++ usb->hcd = hcd; ++ hcd->rsrc_start = (unsigned int)usb->virt_reg_base; ++ hcd->rsrc_len = sizeof(struct ehci_regs); ++ hcd->regs = usb->virt_reg_base; ++ ++ ehci = hcd_to_ehci(hcd); ++ ehci->caps = hcd->regs; ++ ehci->regs = hcd->regs + HC_LENGTH(ehci,ehci_readl(ehci, &ehci->caps->hc_capbase)); ++ ++ /* cache this readonly data; minimize chip reads */ ++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ++ ++ ret = usb_add_hcd(hcd, irq, BCM_USBEHCI_IRQF_FLAGS); ++ if (ret) { ++ EHCI_ERR(pdev, "usb_add_hcd failed\n"); ++ goto err_remove_hcd; ++ } ++ ++ ehci_writel(ehci,BCM_USB_FIFO_THRESHOLD, &ehci->regs->reserved4[6]); ++ ++ ++ platform_set_drvdata(pdev, usb); ++ ++ EHCI_INFO(pdev, "probe done\n"); ++ return 0; ++ ++err_remove_hcd: ++ //usb_remove_hcd(hcd); ++ //usb_put_hcd(hcd); ++ ++err_usb_term: ++ bcm_usbh_term(pdev->id); ++ ++err_io_unmap: ++ iounmap(usb->virt_reg_base); ++ ++err_free_private_mem: ++ kfree(usb); ++ ++err_free_iomem: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ EHCI_ERR(pdev, "probe failed: %d\n", ret); ++ return ret; ++} ++ ++int bcm_ehci_remove(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct resource *iomem; ++ ++ usb_remove_hcd(hcd); ++ usb_put_hcd(hcd); ++ ++ bcm_usbh_term(pdev->id); ++ iounmap(usb->virt_reg_base); ++ kfree(usb); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void bcm_ehci_shutdown(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++#ifdef CONFIG_PM ++static int bcm_ehci_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ if (time_before(jiffies, ehci->next_statechange)) ++ msleep(10); ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave (&ehci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ehci_writel(ehci, 0, &ehci->regs->intr_enable); ++ (void)ehci_readl(ehci, &ehci->regs->intr_enable); ++ ++ /* make sure snapshot being resumed re-enumerates everything */ ++ if (message.event == PM_EVENT_PRETHAW) { ++ ehci_halt(ehci); ++ ehci_reset(ehci); ++ } ++ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ rc = bcm_usbh_suspend(pdev->id); ++ ++bail: ++ spin_unlock_irqrestore (&ehci->lock, flags); ++ ++ return rc; ++} ++ ++static int bcm_ehci_resume(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ int rc; ++ ++ if (time_before(jiffies, ehci->next_statechange)) ++ msleep(100); ++ ++ rc = bcm_usbh_resume(pdev->id); ++ ++ /* Mark hardware accessible again as we are out of D3 state by now */ ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ++ /* If CF is still set, we maintained PCI Vaux power. ++ * Just undo the effect of ehci_pci_suspend(). ++ */ ++ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { ++ int mask = INTR_MASK; ++ ++ if (!hcd->self.root_hub->do_remote_wakeup) ++ mask &= ~STS_PCD; ++ ehci_writel(ehci, mask, &ehci->regs->intr_enable); ++ ehci_readl(ehci, &ehci->regs->intr_enable); ++ return 0; ++ } ++ ++ ehci_dbg(ehci, "lost power, restarting\n"); ++ usb_root_hub_lost_power(hcd->self.root_hub); ++ ++ /* ++ * Else reset, to cope with power loss or flush-to-storage ++ * style "resume" having let BIOS kick in during reboot. ++ */ ++ (void)ehci_halt(ehci); ++ (void)ehci_reset(ehci); ++ ++ /* emptying the schedule aborts any urbs */ ++ spin_lock_irq(&ehci->lock); ++#warning "TODO: ehci->reclaim no longer part of struct ehci_hcd" ++ ehci_work(ehci); ++ spin_unlock_irq(&ehci->lock); ++ ++ ehci_writel(ehci, ehci->command, &ehci->regs->command); ++ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); ++ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ ++ ++ /* here we "know" root ports should always stay powered */ ++ ehci_port_power(ehci, 1); ++ ++ hcd->state = HC_STATE_SUSPENDED; ++ ++ return 0; ++} ++ ++#else ++#define bcm_ehci_suspend NULL ++#define bcm_ehci_resume NULL ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver ehci_bcm_driver = ++{ ++ .probe = bcm_ehci_probe, ++ .remove = bcm_ehci_remove, ++ .shutdown = bcm_ehci_shutdown, ++ .suspend = bcm_ehci_suspend, ++ .resume = bcm_ehci_resume, ++ .driver = { ++ .name = BCM_USBEHCI_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_DESCRIPTION(BCM_USBEHCI_MODULE_DESCRIPTION); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(BCM_USBEHCI_MODULE_VERSION); +diff --git a/drivers/bcmdrivers/usb2h/ohci-bcm.c b/drivers/bcmdrivers/usb2h/ohci-bcm.c +new file mode 100644 +index 0000000..24b21fe diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch new file mode 100644 index 00000000..c47146dc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_ohci-bcm.c.patch @@ -0,0 +1,320 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/ohci-bcm.c +@@ -0,0 +1,314 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "bcm_usbh.h" ++ ++#define BCM_USBOHCI_MODULE_DESCRIPTION "Broadcom USB OHCI driver" ++#define BCM_USBOHCI_MODULE_VERSION "1.0.0" ++ ++#define BCM_USBOHCI_IRQF_FLAGS (IRQF_DISABLED | IRQF_SHARED) ++#define BCM_USBOHCI_NAME "bcm-ohci" ++ ++#define OHCI_INFO(pdev, fmt, args...) dev_info(&pdev->dev, fmt, ## args) ++#define OHCI_ERR(pdev, fmt, args...) dev_err(&pdev->dev, fmt, ## args) ++ ++struct usb_cfg ++{ ++ void *virt_reg_base; ++ struct usb_hcd *hcd; ++}; ++ ++extern int usb_disabled(void); ++extern int InUSBDMode(void); ++static int bcm_ohci_start(struct usb_hcd *hcd); ++ ++static const struct hc_driver ohci_hcd_driver = ++{ ++ .description = hcd_name, ++ .product_desc = BCM_USBOHCI_NAME, ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .start = bcm_ohci_start, ++ .stop = ohci_stop, ++ .shutdown = ohci_shutdown, ++#ifdef CONFIG_PM ++ .bus_suspend = ohci_bus_suspend, ++ .bus_resume = ohci_bus_resume, ++#endif ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ohci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++}; ++ ++static int bcm_ohci_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci; ++ int err; ++ ++ if (!hcd) { ++ printk(KERN_ERR "invalid hcd pointer in %s\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ ohci = hcd_to_ohci(hcd); ++ ++ if ((err = ohci_init(ohci)) < 0) { ++ printk(KERN_ERR "busnum %d: ohci_init() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ if ((err = ohci_run(ohci)) < 0) { ++ printk(KERN_ERR "busnum %d: ohci_run() failed, err=%d\n", hcd->self.busnum, err); ++ ohci_stop(hcd); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int bcm_ohci_probe(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb; ++ struct usb_hcd *hcd; ++ struct resource *iomem, *ioarea; ++ int ret, irq; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ if (InUSBDMode()) ++ return -ENODEV; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ OHCI_ERR(pdev, "no mem resource\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* get the irq info */ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ OHCI_ERR(pdev, "no irq resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), pdev->name); ++ if (!ioarea) { ++ OHCI_ERR(pdev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ usb = kzalloc(sizeof(*usb), GFP_KERNEL); ++ if (!usb) { ++ OHCI_ERR(pdev, "unable to allocate memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_iomem; ++ } ++ ++ usb->virt_reg_base = ioremap(iomem->start, resource_size(iomem)); ++ if (!usb->virt_reg_base) { ++ OHCI_ERR(pdev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_free_private_mem; ++ } ++ ++ /* enable clock and PHY */ ++ ret = bcm_usbh_init(pdev->id); ++ if (ret < 0) { ++ OHCI_ERR(pdev, "clock and PHY initialization failed\n"); ++ goto err_io_unmap; ++ } ++ ++ hcd = usb_create_hcd(&ohci_hcd_driver, &pdev->dev, (char *)pdev->name); ++ if (!hcd) { ++ OHCI_ERR(pdev, "usb_create_hcd failed\n"); ++ ret = -ENOMEM; ++ goto err_usb_term; ++ } ++ ++ /* struct ohci_regs def'd in Linux ohci.h which is included by Linux ohci-hcd.c */ ++ usb->hcd = hcd; ++ hcd->rsrc_start = (unsigned int)usb->virt_reg_base; ++ hcd->rsrc_len = sizeof(struct ohci_regs); ++ hcd->regs = usb->virt_reg_base; ++ ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ ret = usb_add_hcd(hcd, irq, BCM_USBOHCI_IRQF_FLAGS); ++ if (ret) { ++ OHCI_ERR(pdev, "usb_add_hcd failed\n"); ++ goto err_remove_hcd; ++ } ++ ++ platform_set_drvdata(pdev, usb); ++ ++ OHCI_INFO(pdev, "probe done\n"); ++ return 0; ++ ++err_remove_hcd: ++ //usb_remove_hcd(hcd); ++ //usb_put_hcd(hcd); ++ ++err_usb_term: ++ bcm_usbh_term(pdev->id); ++ ++err_io_unmap: ++ iounmap(usb->virt_reg_base); ++ ++err_free_private_mem: ++ kfree(usb); ++ ++err_free_iomem: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ OHCI_ERR(pdev, "probe failed: %d\n", ret); ++ return ret; ++} ++ ++int bcm_ohci_remove(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct resource *iomem; ++ ++ usb_remove_hcd(hcd); ++ usb_put_hcd(hcd); ++ ++ bcm_usbh_term(pdev->id); ++ iounmap(usb->virt_reg_base); ++ kfree(usb); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void bcm_ohci_shutdown(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++#ifdef CONFIG_PM ++static int bcm_ohci_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave(&ohci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); ++ (void)ohci_readl(ohci, &ohci->regs->intrdisable); ++ ++ /* make sure snapshot being resumed re-enumerates everything */ ++ if (message.event == PM_EVENT_PRETHAW) ++ ohci_usb_reset(ohci); ++ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ rc = bcm_usbh_suspend(pdev->id); ++ ++bail: ++ spin_unlock_irqrestore(&ohci->lock, flags); ++ return rc; ++} ++ ++static int bcm_ohci_resume(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ bcm_usbh_resume(pdev->id); ++ ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ohci_finish_controller_resume(hcd); ++ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++/* ++ * Generic platform device driver definition. ++ */ ++static struct platform_driver ohci_bcm_driver = ++{ ++ .probe = bcm_ohci_probe, ++ .remove = bcm_ohci_remove, ++ .shutdown = bcm_ohci_shutdown, ++#ifdef CONFIG_PM ++ .suspend = bcm_ohci_suspend, ++ .resume = bcm_ohci_resume, ++#endif ++ .driver = { ++ .name = BCM_USBOHCI_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_DESCRIPTION(BCM_USBOHCI_MODULE_DESCRIPTION); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(BCM_USBOHCI_MODULE_VERSION); +diff --git a/drivers/bcmdrivers/usb2h/usbh_cfg.h b/drivers/bcmdrivers/usb2h/usbh_cfg.h +new file mode 100644 +index 0000000..c00b0ae diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch new file mode 100644 index 00000000..8aa7e9ee --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_usb2h_usbh_cfg.h.patch @@ -0,0 +1,57 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/usbh_cfg.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __ISLAND_USBH_CFG_H ++#define __ISLAND_USBH_CFG_H ++ ++#define USBH_NUM_PORTS 3 ++ ++struct usbh_port_cfg { ++ /* GPIO for host power */ ++ int pwr_gpio; ++ ++ /* GPIO for power fault (over-current) detection */ ++ int pwr_flt_gpio; ++ ++ /* GPIO for PHY reset */ ++ int reset_gpio; ++}; ++ ++/* ++ * USB Host related HW parameters ++ */ ++struct usbh_cfg { ++ /* peripheral clock name string */ ++ char *peri_clk_name; ++ ++ /* AHB bus clock name string */ ++ char *ahb_clk_name; ++ ++ /* the block might require optional clock to be enabled */ ++ char *opt_clk_name; ++ ++ unsigned int num_ports; ++ ++ struct usbh_port_cfg port[USBH_NUM_PORTS]; ++}; ++ ++#endif +diff --git a/drivers/bcmdrivers/wdt/.gitignore b/drivers/bcmdrivers/wdt/.gitignore +new file mode 100644 +index 0000000..d741861 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch new file mode 100644 index 00000000..eccb0994 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_.gitignore.patch @@ -0,0 +1,10 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/wdt/Kconfig b/drivers/bcmdrivers/wdt/Kconfig +new file mode 100644 +index 0000000..ad0b803 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch new file mode 100644 index 00000000..cd1e4edb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Kconfig.patch @@ -0,0 +1,13 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/Kconfig +@@ -0,0 +1,7 @@ ++config IPROC_WDT ++ tristate "Watchdog Timer support" ++ select WATCHDOG ++ depends on ARCH_IPROC && MACH_NS ++ help ++ This selects a driver for the hardware watchdog on Broadcom ++ iProc chips. +diff --git a/drivers/bcmdrivers/wdt/Makefile b/drivers/bcmdrivers/wdt/Makefile +new file mode 100644 +index 0000000..aefed3e diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch new file mode 100644 index 00000000..43a19555 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_Makefile.patch @@ -0,0 +1,8 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_IPROC_WDT) += iproc_wdt.o +diff --git a/drivers/bcmdrivers/wdt/iproc_wdt.c b/drivers/bcmdrivers/wdt/iproc_wdt.c +new file mode 100755 +index 0000000..33812fa diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch new file mode 100644 index 00000000..11fe49be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_bcmdrivers_wdt_iproc_wdt.c.patch @@ -0,0 +1,496 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/iproc_wdt.c +@@ -0,0 +1,491 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++#include ++#endif ++ ++/* Chip specific */ ++#define IPROC_WATCHDOG_CLK_HZ 125000000UL ++#define IPROC_WATCHDOG_COUNTER_BITS (28) ++ ++/* Default values */ ++#define TIMEOUT_MAX \ ++ ((int)((1 << IPROC_WATCHDOG_COUNTER_BITS) - 1) / IPROC_WATCHDOG_CLK_HZ) ++#define TIMEOUT_DEFAULT (TIMEOUT_MAX > 60? (int)60 : (int)TIMEOUT_MAX) ++ ++/* module parameters */ ++static int timeout = TIMEOUT_DEFAULT; ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout, ++ "Timeout value. (default=" ++ __MODULE_STRING(TIMEOUT_DEFAULT) ")"); ++ ++static int nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++/* Watchdog register offsets and field */ ++#define IPROC_REG_WDT_INTSTATUS 0x20 ++#define IPROC_FLD_WDT_INTSTATUS_WDT_RESET_MASK 0x80000000 ++#define IPROC_REG_WDT_WATCHDOG_COUNTER 0x80 ++ ++/* Register access macro */ ++#define wdt_readl(dev, reg) \ ++ readl_relaxed((dev)->regs + (reg)) ++#define wdt_writel(dev, reg, value) \ ++ writel_relaxed((value), (dev)->regs + (reg)) ++ ++/* Driver specific data */ ++struct wdt_iproc { ++ volatile void *regs; ++ spinlock_t io_lock; ++ int timeout; ++ int boot_status; ++ unsigned long users; ++ struct miscdevice miscdev; ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ SWRR_HANDLE swrr; ++#endif ++}; ++static struct wdt_iproc *wdt; ++static char expect_release; ++ ++/* ++ * Disable the watchdog. ++ */ ++static inline void ++iproc_wdt_stop(void) ++{ ++ spin_lock(&wdt->io_lock); ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) ++ swreset_record_set(wdt->swrr, 0); ++#endif ++ wdt_writel(wdt, ++ IPROC_REG_WDT_WATCHDOG_COUNTER, ++ 0 ++ ); ++ spin_unlock(&wdt->io_lock); ++} ++ ++/* ++ * Enable and reset the watchdog. ++ */ ++static inline void ++iproc_wdt_start(void) ++{ ++ spin_lock(&wdt->io_lock); ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) ++ swreset_record_set(wdt->swrr, 1); ++#endif ++ wdt_writel(wdt, ++ IPROC_REG_WDT_WATCHDOG_COUNTER, ++ wdt->timeout * IPROC_WATCHDOG_CLK_HZ ++ ); ++ spin_unlock(&wdt->io_lock); ++} ++ ++/* ++ * Pat the watchdog timer. ++ */ ++static inline void ++iproc_wdt_pat(void) ++{ ++ iproc_wdt_start(); ++} ++ ++/* ++ * Watchdog device is opened, and watchdog starts running. ++ */ ++static int ++iproc_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(1, &wdt->users)) ++ return -EBUSY; ++ ++ iproc_wdt_start(); ++ return nonseekable_open(inode, file); ++} ++ ++/* ++ * Close the watchdog device. ++ */ ++static int ++iproc_wdt_close(struct inode *inode, struct file *file) ++{ ++ if (expect_release == 1) { ++ iproc_wdt_stop(); ++ } else { ++ dev_dbg(wdt->miscdev.parent, ++ "unexpected close, not stopping watchdog!\n"); ++ iproc_wdt_pat(); ++ } ++ clear_bit(1, &wdt->users); ++ expect_release = 0; ++ return 0; ++} ++ ++/* ++ * Change the watchdog time interval. ++ */ ++static int ++iproc_wdt_settimeout(int time) ++{ ++ if (time < 0 || time > TIMEOUT_MAX) { ++ return -EINVAL; ++ } ++ ++ /* ++ * Set new watchdog time. It will be used when iproc_wdt_start() is ++ * called. ++ */ ++ wdt->timeout = time; ++ return 0; ++} ++ ++/* ++ * Get the watchdog status. ++ */ ++static int ++iproc_wdt_get_status(void) ++{ ++ if (wdt_readl(wdt, IPROC_REG_WDT_INTSTATUS) & ++ IPROC_FLD_WDT_INTSTATUS_WDT_RESET_MASK) { ++ return WDIOF_CARDRESET; ++ } ++ ++ return 0; ++} ++ ++static const struct watchdog_info iproc_wdt_info = { ++ .identity = "iproc watchdog", ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++}; ++ ++/* ++ * Handle commands from user-space. ++ */ ++static long ++iproc_wdt_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret = -ENOTTY; ++ int time; ++ void __user *argp = (void __user *)arg; ++ int __user *p = argp; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user(argp, &iproc_wdt_info, ++ sizeof(iproc_wdt_info)) ? -EFAULT : 0; ++ break; ++ case WDIOC_GETSTATUS: ++ ret = put_user(0, p); ++ break; ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(wdt->boot_status, p); ++ break; ++ case WDIOC_SETOPTIONS: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ if (time & WDIOS_DISABLECARD) ++ iproc_wdt_stop(); ++ if (time & WDIOS_ENABLECARD) ++ iproc_wdt_start(); ++ ret = 0; ++ break; ++ case WDIOC_KEEPALIVE: ++ iproc_wdt_pat(); ++ ret = 0; ++ break; ++ case WDIOC_SETTIMEOUT: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ ret = iproc_wdt_settimeout(time); ++ if (ret) ++ break; ++ /* Enable new time value */ ++ iproc_wdt_start(); ++ /* fall through */ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(wdt->timeout, p); ++ break; ++ } ++ ++ return ret; ++} ++ ++static ssize_t ++iproc_wdt_write(struct file *file, const char __user *data, ++ size_t len, loff_t *ppos) ++{ ++ /* See if we got the magic character 'V' and reload the timer */ ++ if (len) { ++ if (!nowayout) { ++ size_t i; ++ ++ /* ++ * note: just in case someone wrote the magic ++ * character five months ago... ++ */ ++ expect_release = 0; ++ ++ /* ++ * scan to see whether or not we got the magic ++ * character ++ */ ++ for (i = 0; i != len; i++) { ++ char c; ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ if (c == 'V') ++ expect_release = 1; ++ } ++ } ++ /* someone wrote to us, we should pat the watchdog */ ++ iproc_wdt_pat(); ++ } ++ return len; ++} ++ ++static int ++iproc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) ++{ ++ if (code == SYS_DOWN || code == SYS_HALT) { ++ /* Turn the watchdog off */ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) { ++ swreset_record_set(wdt->swrr, 0); ++ } ++#endif ++ iproc_wdt_stop(); ++ } ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block iproc_wdt_notifier = { ++ .notifier_call = iproc_wdt_notify_sys, ++}; ++ ++static const struct file_operations iproc_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = iproc_wdt_ioctl, ++ .open = iproc_wdt_open, ++ .release = iproc_wdt_close, ++ .write = iproc_wdt_write, ++}; ++ ++static int __init ++iproc_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ int ret; ++ ++ if (wdt) { ++ dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); ++ return -EBUSY; ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_dbg(&pdev->dev, "missing resource 0\n"); ++ return -ENXIO; ++ } ++ ++ wdt = kzalloc(sizeof(struct wdt_iproc), GFP_KERNEL); ++ if (!wdt) { ++ dev_dbg(&pdev->dev, "no memory for wdt structure\n"); ++ return -ENOMEM; ++ } ++ ++ wdt->regs = ioremap(regs->start, resource_size(regs)); ++ if (!wdt->regs) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "could not map I/O memory\n"); ++ goto err_free; ++ } ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (swreset_record_get_record_count() == 0) { ++ /* No software reset record support */ ++ wdt->swrr = NULL; ++ wdt->boot_status = iproc_wdt_get_status(); ++ } else { ++ wdt->swrr = swreset_record_register("iproc_cca_watchdog"); ++ if (wdt->swrr == NULL) { ++ /* All software reset records are used (unlikely) */ ++ dev_warn(&pdev->dev, "Boot status is not available!\n"); ++ /* Still try to use original watchdog reset status */ ++ wdt->boot_status = iproc_wdt_get_status(); ++ } else { ++ /* Get previous value */ ++ swreset_record_get(wdt->swrr, &wdt->boot_status); ++ /* Clear it */ ++ swreset_record_set(wdt->swrr, 0); ++ } ++ } ++#else ++ wdt->boot_status = iproc_wdt_get_status(); ++#endif ++ ++ /* To avoid treating manual reboot as a watchdog reset */ ++ ret = register_reboot_notifier(&iproc_wdt_notifier); ++ if (ret) { ++ /* In this case, manual reboot could be mistaken as watchdog reset */ ++ dev_dbg(&pdev->dev, "could not register reboot notifier\n"); ++ } ++ ++ expect_release = 0; ++ spin_lock_init(&wdt->io_lock); ++ wdt->users = 0; ++ ++ wdt->miscdev.minor = WATCHDOG_MINOR; ++ wdt->miscdev.name = "watchdog"; ++ wdt->miscdev.fops = &iproc_wdt_fops; ++ wdt->miscdev.parent = &pdev->dev; ++ ++ platform_set_drvdata(pdev, wdt); ++ ++ if (iproc_wdt_settimeout(timeout)) { ++ iproc_wdt_settimeout(TIMEOUT_DEFAULT); ++ dev_dbg(&pdev->dev, ++ "default timeout invalid, set to %d sec.\n", ++ TIMEOUT_DEFAULT); ++ } ++ ++ ret = misc_register(&wdt->miscdev); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); ++ goto err_register; ++ } ++ ++ dev_info(&pdev->dev, ++ "iProc Watchdog Timer - timeout=%d sec, nowayout=%d\n", ++ wdt->timeout, nowayout); ++ ++ return 0; ++ ++err_register: ++ platform_set_drvdata(pdev, NULL); ++ iounmap(wdt->regs); ++err_free: ++ kfree(wdt); ++ wdt = NULL; ++ return ret; ++} ++ ++static int __exit ++iproc_wdt_remove(struct platform_device *pdev) ++{ ++ if (wdt && platform_get_drvdata(pdev) == wdt) { ++ /* Stop the timer before we leave */ ++ if (!nowayout) ++ iproc_wdt_stop(); ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) { ++ swreset_record_set(wdt->swrr, 0); ++ swreset_record_unregister(wdt->swrr); ++ wdt->swrr = NULL; ++ } ++#endif ++ unregister_reboot_notifier(&iproc_wdt_notifier); ++ misc_deregister(&wdt->miscdev); ++ iounmap(wdt->regs); ++ kfree(wdt); ++ wdt = NULL; ++ platform_set_drvdata(pdev, NULL); ++ } ++ return 0; ++} ++ ++static void ++iproc_wdt_shutdown(struct platform_device *pdev) ++{ ++ iproc_wdt_stop(); ++} ++ ++#ifdef CONFIG_PM ++static int ++iproc_wdt_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ iproc_wdt_stop(); ++ return 0; ++} ++ ++static int ++iproc_wdt_resume(struct platform_device *pdev) ++{ ++ if (wdt->users) ++ iproc_wdt_start(); ++ return 0; ++} ++#else ++#define iproc_wdt_suspend NULL ++#define iproc_wdt_resume NULL ++#endif ++ ++/* work with hotplug and coldplug */ ++MODULE_ALIAS("platform:iproc_wdt"); ++ ++static struct platform_driver iproc_wdt_driver = { ++ .remove = __exit_p(iproc_wdt_remove), ++ .suspend = iproc_wdt_suspend, ++ .resume = iproc_wdt_resume, ++ .driver = { ++ .name = "iproc_wdt", ++ .owner = THIS_MODULE, ++ }, ++ .shutdown = iproc_wdt_shutdown, ++}; ++ ++static int __init ++iproc_wdt_init(void) ++{ ++ return platform_driver_probe(&iproc_wdt_driver, iproc_wdt_probe); ++} ++module_init(iproc_wdt_init); ++ ++static void __exit ++iproc_wdt_exit(void) ++{ ++ platform_driver_unregister(&iproc_wdt_driver); ++} ++module_exit(iproc_wdt_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Watchdog driver for Broadcom iProc chips"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index e9e8f3b..1d2ae23 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch new file mode 100644 index 00000000..18fdd68b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.c.patch @@ -0,0 +1,53 @@ +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -291,10 +291,10 @@ EXPORT_SYMBOL_GPL(cpuidle_disable_device); + static int __cpuidle_register_device(struct cpuidle_device *dev) + { + int ret; +- struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); ++ struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); + struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); + +- if (!sys_dev) ++ if (!dev) + return -EINVAL; + if (!try_module_get(cpuidle_driver->owner)) + return -EINVAL; +@@ -303,7 +303,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) + + per_cpu(cpuidle_devices, dev->cpu) = dev; + list_add(&dev->device_list, &cpuidle_detected_devices); +- if ((ret = cpuidle_add_sysfs(sys_dev))) { ++ if ((ret = cpuidle_add_sysfs(cpu_dev))) { + module_put(cpuidle_driver->owner); + return ret; + } +@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); + */ + void cpuidle_unregister_device(struct cpuidle_device *dev) + { +- struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); ++ struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); + struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); + + if (dev->registered == 0) +@@ -354,7 +354,7 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) + + cpuidle_disable_device(dev); + +- cpuidle_remove_sysfs(sys_dev); ++ cpuidle_remove_sysfs(cpu_dev); + list_del(&dev->device_list); + wait_for_completion(&dev->kobj_unregister); + per_cpu(cpuidle_devices, dev->cpu) = NULL; +@@ -411,7 +411,7 @@ static int __init cpuidle_init(void) + if (cpuidle_disabled()) + return -ENODEV; + +- ret = cpuidle_add_class_sysfs(&cpu_sysdev_class); ++ ret = cpuidle_add_interface(cpu_subsys.dev_root); + if (ret) + return ret; + +diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h +index 38c3fd8..7db1866 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch new file mode 100644 index 00000000..6f8f5282 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_cpuidle.h.patch @@ -0,0 +1,29 @@ +--- a/drivers/cpuidle/cpuidle.h ++++ b/drivers/cpuidle/cpuidle.h +@@ -5,7 +5,7 @@ + #ifndef __DRIVER_CPUIDLE_H + #define __DRIVER_CPUIDLE_H + +-#include ++#include + + /* For internal use only */ + extern struct cpuidle_governor *cpuidle_curr_governor; +@@ -23,11 +23,11 @@ extern void cpuidle_uninstall_idle_handler(void); + extern int cpuidle_switch_governor(struct cpuidle_governor *gov); + + /* sysfs */ +-extern int cpuidle_add_class_sysfs(struct sysdev_class *cls); +-extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls); ++extern int cpuidle_add_interface(struct device *dev); ++extern void cpuidle_remove_interface(struct device *dev); + extern int cpuidle_add_state_sysfs(struct cpuidle_device *device); + extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device); +-extern int cpuidle_add_sysfs(struct sys_device *sysdev); +-extern void cpuidle_remove_sysfs(struct sys_device *sysdev); ++extern int cpuidle_add_sysfs(struct device *dev); ++extern void cpuidle_remove_sysfs(struct device *dev); + + #endif /* __DRIVER_CPUIDLE_H */ +diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c +index 1e756e1..3fe41fe 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch new file mode 100644 index 00000000..11aae084 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_cpuidle_sysfs.c.patch @@ -0,0 +1,156 @@ +--- a/drivers/cpuidle/sysfs.c ++++ b/drivers/cpuidle/sysfs.c +@@ -22,8 +22,8 @@ static int __init cpuidle_sysfs_setup(char *unused) + } + __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup); + +-static ssize_t show_available_governors(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_available_governors(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t i = 0; +@@ -42,8 +42,8 @@ out: + return i; + } + +-static ssize_t show_current_driver(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_current_driver(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t ret; +@@ -59,8 +59,8 @@ static ssize_t show_current_driver(struct sysdev_class *class, + return ret; + } + +-static ssize_t show_current_governor(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t show_current_governor(struct device *dev, ++ struct device_attribute *attr, + char *buf) + { + ssize_t ret; +@@ -75,8 +75,8 @@ static ssize_t show_current_governor(struct sysdev_class *class, + return ret; + } + +-static ssize_t store_current_governor(struct sysdev_class *class, +- struct sysdev_class_attribute *attr, ++static ssize_t store_current_governor(struct device *dev, ++ struct device_attribute *attr, + const char *buf, size_t count) + { + char gov_name[CPUIDLE_NAME_LEN]; +@@ -109,50 +109,48 @@ static ssize_t store_current_governor(struct sysdev_class *class, + return count; + } + +-static SYSDEV_CLASS_ATTR(current_driver, 0444, show_current_driver, NULL); +-static SYSDEV_CLASS_ATTR(current_governor_ro, 0444, show_current_governor, +- NULL); ++static DEVICE_ATTR(current_driver, 0444, show_current_driver, NULL); ++static DEVICE_ATTR(current_governor_ro, 0444, show_current_governor, NULL); + +-static struct attribute *cpuclass_default_attrs[] = { +- &attr_current_driver.attr, +- &attr_current_governor_ro.attr, ++static struct attribute *cpuidle_default_attrs[] = { ++ &dev_attr_current_driver.attr, ++ &dev_attr_current_governor_ro.attr, + NULL + }; + +-static SYSDEV_CLASS_ATTR(available_governors, 0444, show_available_governors, +- NULL); +-static SYSDEV_CLASS_ATTR(current_governor, 0644, show_current_governor, +- store_current_governor); ++static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL); ++static DEVICE_ATTR(current_governor, 0644, show_current_governor, ++ store_current_governor); + +-static struct attribute *cpuclass_switch_attrs[] = { +- &attr_available_governors.attr, +- &attr_current_driver.attr, +- &attr_current_governor.attr, ++static struct attribute *cpuidle_switch_attrs[] = { ++ &dev_attr_available_governors.attr, ++ &dev_attr_current_driver.attr, ++ &dev_attr_current_governor.attr, + NULL + }; + +-static struct attribute_group cpuclass_attr_group = { +- .attrs = cpuclass_default_attrs, ++static struct attribute_group cpuidle_attr_group = { ++ .attrs = cpuidle_default_attrs, + .name = "cpuidle", + }; + + /** +- * cpuidle_add_class_sysfs - add CPU global sysfs attributes ++ * cpuidle_add_interface - add CPU global sysfs attributes + */ +-int cpuidle_add_class_sysfs(struct sysdev_class *cls) ++int cpuidle_add_interface(struct device *dev) + { + if (sysfs_switch) +- cpuclass_attr_group.attrs = cpuclass_switch_attrs; ++ cpuidle_attr_group.attrs = cpuidle_switch_attrs; + +- return sysfs_create_group(&cls->kset.kobj, &cpuclass_attr_group); ++ return sysfs_create_group(&dev->kobj, &cpuidle_attr_group); + } + + /** +- * cpuidle_remove_class_sysfs - remove CPU global sysfs attributes ++ * cpuidle_remove_interface - remove CPU global sysfs attributes + */ +-void cpuidle_remove_class_sysfs(struct sysdev_class *cls) ++void cpuidle_remove_interface(struct device *dev) + { +- sysfs_remove_group(&cls->kset.kobj, &cpuclass_attr_group); ++ sysfs_remove_group(&dev->kobj, &cpuidle_attr_group); + } + + struct cpuidle_attr { +@@ -365,16 +363,16 @@ void cpuidle_remove_state_sysfs(struct cpuidle_device *device) + + /** + * cpuidle_add_sysfs - creates a sysfs instance for the target device +- * @sysdev: the target device ++ * @dev: the target device + */ +-int cpuidle_add_sysfs(struct sys_device *sysdev) ++int cpuidle_add_sysfs(struct device *cpu_dev) + { +- int cpu = sysdev->id; ++ int cpu = cpu_dev->id; + struct cpuidle_device *dev; + int error; + + dev = per_cpu(cpuidle_devices, cpu); +- error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj, ++ error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj, + "cpuidle"); + if (!error) + kobject_uevent(&dev->kobj, KOBJ_ADD); +@@ -383,11 +381,11 @@ int cpuidle_add_sysfs(struct sys_device *sysdev) + + /** + * cpuidle_remove_sysfs - deletes a sysfs instance on the target device +- * @sysdev: the target device ++ * @dev: the target device + */ +-void cpuidle_remove_sysfs(struct sys_device *sysdev) ++void cpuidle_remove_sysfs(struct device *cpu_dev) + { +- int cpu = sysdev->id; ++ int cpu = cpu_dev->id; + struct cpuidle_device *dev; + + dev = per_cpu(cpuidle_devices, cpu); +diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c +index 87500e6..157d3ec 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch new file mode 100644 index 00000000..0a475e16 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-aes.c.patch @@ -0,0 +1,32 @@ +--- a/drivers/crypto/padlock-aes.c ++++ b/drivers/crypto/padlock-aes.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -503,12 +504,18 @@ static struct crypto_alg cbc_aes_alg = { + } + }; + ++static struct x86_cpu_id padlock_cpu_id[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_XCRYPT), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id); ++ + static int __init padlock_init(void) + { + int ret; + struct cpuinfo_x86 *c = &cpu_data(0); + +- if (!cpu_has_xcrypt) ++ if (!x86_match_cpu(padlock_cpu_id)) + return -ENODEV; + + if (!cpu_has_xcrypt_enabled) { +diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c +index 710f3cb..93d7753 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch new file mode 100644 index 00000000..050733ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_crypto_padlock-sha.c.patch @@ -0,0 +1,42 @@ +--- a/drivers/crypto/padlock-sha.c ++++ b/drivers/crypto/padlock-sha.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + + struct padlock_sha_desc { +@@ -526,6 +527,12 @@ static struct shash_alg sha256_alg_nano = { + } + }; + ++static struct x86_cpu_id padlock_sha_ids[] = { ++ X86_FEATURE_MATCH(X86_FEATURE_PHE), ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, padlock_sha_ids); ++ + static int __init padlock_init(void) + { + int rc = -ENODEV; +@@ -533,15 +540,8 @@ static int __init padlock_init(void) + struct shash_alg *sha1; + struct shash_alg *sha256; + +- if (!cpu_has_phe) { +- printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n"); +- return -ENODEV; +- } +- +- if (!cpu_has_phe_enabled) { +- printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); ++ if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled) + return -ENODEV; +- } + + /* Register the newly added algorithm module if on * + * VIA Nano processor, or else just do as before */ +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index a842317..19743e3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch new file mode 100644 index 00000000..dfd818e4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_Kconfig.patch @@ -0,0 +1,16 @@ +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -262,6 +262,11 @@ config NET_DMA + Say Y here if you enabled INTEL_IOATDMA or FSL_DMA, otherwise + say N. + ++config NET_DMA_DUMMY ++ bool ++ depends on DMA_ENGINE && NET ++ default (INTEL_IOATDMA || FSL_DMA) ++ + config ASYNC_TX_DMA + bool "Async_tx: Offload support for the async_tx api" + depends on DMA_ENGINE +diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c +index f993955..7021ecb 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch new file mode 100644 index 00000000..b2b34773 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_dma_imx-sdma.c.patch @@ -0,0 +1,16 @@ +--- a/drivers/dma/imx-sdma.c ++++ b/drivers/dma/imx-sdma.c +@@ -1152,10 +1152,8 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) + const struct sdma_script_start_addrs *addr; + unsigned short *ram_code; + +- if (!fw) { +- dev_err(sdma->dev, "firmware not found\n"); ++ if (!fw) + return; +- } + + if (fw->size < sizeof(*header)) + goto err_firmware; +diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c +index 20f7daa..335c173 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch new file mode 100644 index 00000000..8982f94b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_Kconfig.patch @@ -0,0 +1,49 @@ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -154,13 +154,13 @@ config GPIO_VR41XX + Say yes here to support the NEC VR4100 series General-purpose I/O Uint + + config GPIO_SCH +- tristate "Intel SCH/TunnelCreek GPIO" ++ tristate "Intel SCH/TunnelCreek/Centerton GPIO" + depends on PCI && X86 + select MFD_CORE + select LPC_SCH + help +- Say yes here to support GPIO interface on Intel Poulsbo SCH +- or Intel Tunnel Creek processor. ++ Say yes here to support GPIO interface on Intel Poulsbo SCH, ++ Intel Tunnel Creek processor or Intel Centerton processor. + The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are + powered by the core power rail and are turned off during sleep + modes (S3 and higher). The remaining four GPIOs are powered by +@@ -169,6 +169,9 @@ config GPIO_SCH + system from the Suspend-to-RAM state. + The Intel Tunnel Creek processor has 5 GPIOs powered by the + core power rail and 9 from suspend power supply. ++ The Intel Centerton processor has a total of 30 GPIO pins. ++ Twenty-one are powered by the core power rail and 9 from the ++ suspend power supply. + + config GPIO_U300 + bool "ST-Ericsson U300 COH 901 335/571 GPIO" +@@ -227,7 +230,7 @@ config GPIO_MAX732X_IRQ + controller. It requires the driver to be built in the kernel. + + config GPIO_PCA953X +- tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" ++ tristate "PCA953x, PCA955x, PCA9698, TCA64xx, and MAX7310 I/O ports" + depends on I2C + help + Say yes here to provide access to several register-oriented +@@ -241,6 +244,8 @@ config GPIO_PCA953X + + 16 bits: pca9535, pca9539, pca9555, tca6416 + ++ 40 bits: pca9698 ++ + config GPIO_PCA953X_IRQ + bool "Interrupt controller support for PCA953x" + depends on GPIO_PCA953X=y +diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c +index 34be13b..60e259f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch new file mode 100644 index 00000000..375f0bdf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-mpc8xxx.c.patch @@ -0,0 +1,12 @@ +--- a/drivers/gpio/gpio-mpc8xxx.c ++++ b/drivers/gpio/gpio-mpc8xxx.c +@@ -296,7 +296,6 @@ static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, + + irq_set_chip_data(virq, h->host_data); + irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); +- irq_set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; + } +diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c +index d3f3e8f..5a215fb 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch new file mode 100644 index 00000000..a6d1b572 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-pca953x.c.patch @@ -0,0 +1,837 @@ +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -28,6 +29,8 @@ + #define PCA953X_INVERT 2 + #define PCA953X_DIRECTION 3 + ++#define REG_ADDR_AI 0x80 ++ + #define PCA957X_IN 0 + #define PCA957X_INVRT 1 + #define PCA957X_BKEN 2 +@@ -43,6 +46,8 @@ + #define PCA957X_TYPE 0x2000 + + static const struct i2c_device_id pca953x_id[] = { ++ { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, ++ { "pca9506", 40 | PCA953X_TYPE | PCA_INT, }, + { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, + { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, + { "pca9536", 4 | PCA953X_TYPE, }, +@@ -55,6 +60,7 @@ static const struct i2c_device_id pca953x_id[] = { + { "pca9557", 8 | PCA953X_TYPE, }, + { "pca9574", 8 | PCA957X_TYPE | PCA_INT, }, + { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, ++ { "pca9698", 40 | PCA953X_TYPE, }, + + { "max7310", 8 | PCA953X_TYPE, }, + { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, +@@ -63,24 +69,29 @@ static const struct i2c_device_id pca953x_id[] = { + { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, + { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, + { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, +- /* NYET: { "tca6424", 24, }, */ ++ { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, + { } + }; + MODULE_DEVICE_TABLE(i2c, pca953x_id); + ++#define MAX_BANK 5 ++#define BANK_SZ 8 ++ ++#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ) ++ + struct pca953x_chip { + unsigned gpio_start; +- uint16_t reg_output; +- uint16_t reg_direction; ++ u8 reg_output[MAX_BANK]; ++ u8 reg_direction[MAX_BANK]; + struct mutex i2c_lock; + + #ifdef CONFIG_GPIO_PCA953X_IRQ + struct mutex irq_lock; +- uint16_t irq_mask; +- uint16_t irq_stat; +- uint16_t irq_trig_raise; +- uint16_t irq_trig_fall; +- int irq_base; ++ u8 irq_mask[MAX_BANK]; ++ u8 irq_stat[MAX_BANK]; ++ u8 irq_trig_raise[MAX_BANK]; ++ u8 irq_trig_fall[MAX_BANK]; ++ struct irq_domain *domain; + #endif + + struct i2c_client *client; +@@ -89,26 +100,68 @@ struct pca953x_chip { + int chip_type; + }; + +-static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) ++static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, ++ int off) ++{ ++ int ret; ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ++ int offset = off / BANK_SZ; ++ ++ ret = i2c_smbus_read_byte_data(chip->client, ++ (reg << bank_shift) + offset); ++ *val = ret; ++ ++ if (ret < 0) { ++ dev_err(&chip->client->dev, "failed reading register\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, ++ int off) ++{ ++ int ret = 0; ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ++ int offset = off / BANK_SZ; ++ ++ ret = i2c_smbus_write_byte_data(chip->client, ++ (reg << bank_shift) + offset, val); ++ ++ if (ret < 0) { ++ dev_err(&chip->client->dev, "failed writing register\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) + { + int ret = 0; + + if (chip->gpio_chip.ngpio <= 8) +- ret = i2c_smbus_write_byte_data(chip->client, reg, val); +- else { ++ ret = i2c_smbus_write_byte_data(chip->client, reg, *val); ++ else if (chip->gpio_chip.ngpio >= 24) { ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); ++ ret = i2c_smbus_write_i2c_block_data(chip->client, ++ (reg << bank_shift) | REG_ADDR_AI, ++ NBANK(chip), val); ++ } else { + switch (chip->chip_type) { + case PCA953X_TYPE: + ret = i2c_smbus_write_word_data(chip->client, +- reg << 1, val); ++ reg << 1, (u16) *val); + break; + case PCA957X_TYPE: + ret = i2c_smbus_write_byte_data(chip->client, reg << 1, +- val & 0xff); ++ val[0]); + if (ret < 0) + break; + ret = i2c_smbus_write_byte_data(chip->client, + (reg << 1) + 1, +- (val & 0xff00) >> 8); ++ val[1]); + break; + } + } +@@ -121,34 +174,42 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) + return 0; + } + +-static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) ++static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) + { + int ret; + +- if (chip->gpio_chip.ngpio <= 8) ++ if (chip->gpio_chip.ngpio <= 8) { + ret = i2c_smbus_read_byte_data(chip->client, reg); +- else +- ret = i2c_smbus_read_word_data(chip->client, reg << 1); ++ *val = ret; ++ } else if (chip->gpio_chip.ngpio >= 24) { ++ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + ++ ret = i2c_smbus_read_i2c_block_data(chip->client, ++ (reg << bank_shift) | REG_ADDR_AI, ++ NBANK(chip), val); ++ } else { ++ ret = i2c_smbus_read_word_data(chip->client, reg << 1); ++ val[0] = (u16)ret & 0xFF; ++ val[1] = (u16)ret >> 8; ++ } + if (ret < 0) { + dev_err(&chip->client->dev, "failed reading register\n"); + return ret; + } + +- *val = (uint16_t)ret; + return 0; + } + + static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u8 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); + + mutex_lock(&chip->i2c_lock); +- reg_val = chip->reg_direction | (1u << off); ++ reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -158,11 +219,11 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) + offset = PCA957X_CFG; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_direction = reg_val; ++ chip->reg_direction[off / BANK_SZ] = reg_val; + ret = 0; + exit: + mutex_unlock(&chip->i2c_lock); +@@ -173,7 +234,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + unsigned off, int val) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u8 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); +@@ -181,9 +242,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + mutex_lock(&chip->i2c_lock); + /* set output level */ + if (val) +- reg_val = chip->reg_output | (1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ | (1u << (off % BANK_SZ)); + else +- reg_val = chip->reg_output & ~(1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ & ~(1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -193,14 +256,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + offset = PCA957X_OUT; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_output = reg_val; ++ chip->reg_output[off / BANK_SZ] = reg_val; + + /* then direction */ +- reg_val = chip->reg_direction & ~(1u << off); ++ reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_DIRECTION; +@@ -209,11 +272,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, + offset = PCA957X_CFG; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_direction = reg_val; ++ chip->reg_direction[off / BANK_SZ] = reg_val; + ret = 0; + exit: + mutex_unlock(&chip->i2c_lock); +@@ -223,7 +286,7 @@ exit: + static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u32 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); +@@ -237,7 +300,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + offset = PCA957X_IN; + break; + } +- ret = pca953x_read_reg(chip, offset, ®_val); ++ ret = pca953x_read_single(chip, offset, ®_val, off); + mutex_unlock(&chip->i2c_lock); + if (ret < 0) { + /* NOTE: diagnostic already emitted; that's all we should +@@ -247,22 +310,24 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + return 0; + } + +- return (reg_val & (1u << off)) ? 1 : 0; ++ return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; + } + + static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) + { + struct pca953x_chip *chip; +- uint16_t reg_val; ++ u8 reg_val; + int ret, offset = 0; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); + + mutex_lock(&chip->i2c_lock); + if (val) +- reg_val = chip->reg_output | (1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ | (1u << (off % BANK_SZ)); + else +- reg_val = chip->reg_output & ~(1u << off); ++ reg_val = chip->reg_output[off / BANK_SZ] ++ & ~(1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -272,11 +337,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) + offset = PCA957X_OUT; + break; + } +- ret = pca953x_write_reg(chip, offset, reg_val); ++ ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + +- chip->reg_output = reg_val; ++ chip->reg_output[off / BANK_SZ] = reg_val; + exit: + mutex_unlock(&chip->i2c_lock); + } +@@ -307,21 +372,21 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) + struct pca953x_chip *chip; + + chip = container_of(gc, struct pca953x_chip, gpio_chip); +- return chip->irq_base + off; ++ return irq_create_mapping(chip->domain, off); + } + + static void pca953x_irq_mask(struct irq_data *d) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); + +- chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); ++ chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); + } + + static void pca953x_irq_unmask(struct irq_data *d) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); + +- chip->irq_mask |= 1 << (d->irq - chip->irq_base); ++ chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); + } + + static void pca953x_irq_bus_lock(struct irq_data *d) +@@ -334,17 +399,20 @@ static void pca953x_irq_bus_lock(struct irq_data *d) + static void pca953x_irq_bus_sync_unlock(struct irq_data *d) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +- uint16_t new_irqs; +- uint16_t level; ++ u8 new_irqs; ++ int level, i; + + /* Look for any newly setup interrupt */ +- new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; +- new_irqs &= ~chip->reg_direction; +- +- while (new_irqs) { +- level = __ffs(new_irqs); +- pca953x_gpio_direction_input(&chip->gpio_chip, level); +- new_irqs &= ~(1 << level); ++ for (i = 0; i < NBANK(chip); i++) { ++ new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; ++ new_irqs &= ~chip->reg_direction[i]; ++ ++ while (new_irqs) { ++ level = __ffs(new_irqs); ++ pca953x_gpio_direction_input(&chip->gpio_chip, ++ level + (BANK_SZ * i)); ++ new_irqs &= ~(1 << level); ++ } + } + + mutex_unlock(&chip->irq_lock); +@@ -353,8 +421,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) + static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) + { + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +- uint16_t level = d->irq - chip->irq_base; +- uint16_t mask = 1 << level; ++ int bank_nb = d->hwirq / BANK_SZ; ++ u8 mask = 1 << (d->hwirq % BANK_SZ); + + if (!(type & IRQ_TYPE_EDGE_BOTH)) { + dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", +@@ -363,14 +431,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) + } + + if (type & IRQ_TYPE_EDGE_FALLING) +- chip->irq_trig_fall |= mask; ++ chip->irq_trig_fall[bank_nb] |= mask; + else +- chip->irq_trig_fall &= ~mask; ++ chip->irq_trig_fall[bank_nb] &= ~mask; + + if (type & IRQ_TYPE_EDGE_RISING) +- chip->irq_trig_raise |= mask; ++ chip->irq_trig_raise[bank_nb] |= mask; + else +- chip->irq_trig_raise &= ~mask; ++ chip->irq_trig_raise[bank_nb] &= ~mask; + + return 0; + } +@@ -384,13 +452,13 @@ static struct irq_chip pca953x_irq_chip = { + .irq_set_type = pca953x_irq_set_type, + }; + +-static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) ++static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) + { +- uint16_t cur_stat; +- uint16_t old_stat; +- uint16_t pending; +- uint16_t trigger; +- int ret, offset = 0; ++ u8 cur_stat[MAX_BANK]; ++ u8 old_stat[MAX_BANK]; ++ u8 pendings = 0; ++ u8 trigger[MAX_BANK], triggers = 0; ++ int ret, i, offset = 0; + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -400,59 +468,88 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) + offset = PCA957X_IN; + break; + } +- ret = pca953x_read_reg(chip, offset, &cur_stat); ++ ret = pca953x_read_regs(chip, offset, cur_stat); + if (ret) + return 0; + + /* Remove output pins from the equation */ +- cur_stat &= chip->reg_direction; ++ for (i = 0; i < NBANK(chip); i++) ++ cur_stat[i] &= chip->reg_direction[i]; ++ ++ memcpy(old_stat, chip->irq_stat, NBANK(chip)); + +- old_stat = chip->irq_stat; +- trigger = (cur_stat ^ old_stat) & chip->irq_mask; ++ for (i = 0; i < NBANK(chip); i++) { ++ trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; ++ triggers += trigger[i]; ++ } + +- if (!trigger) ++ if (!triggers) + return 0; + +- chip->irq_stat = cur_stat; ++ memcpy(chip->irq_stat, cur_stat, NBANK(chip)); + +- pending = (old_stat & chip->irq_trig_fall) | +- (cur_stat & chip->irq_trig_raise); +- pending &= trigger; ++ for (i = 0; i < NBANK(chip); i++) { ++ pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | ++ (cur_stat[i] & chip->irq_trig_raise[i]); ++ pending[i] &= trigger[i]; ++ pendings += pending[i]; ++ } + +- return pending; ++ return pendings; + } + + static irqreturn_t pca953x_irq_handler(int irq, void *devid) + { + struct pca953x_chip *chip = devid; +- uint16_t pending; +- uint16_t level; +- +- pending = pca953x_irq_pending(chip); ++ u8 pending[MAX_BANK]; ++ u8 level; ++ int i; + +- if (!pending) ++ if (!pca953x_irq_pending(chip, pending)) + return IRQ_HANDLED; + +- do { +- level = __ffs(pending); +- handle_nested_irq(level + chip->irq_base); +- +- pending &= ~(1 << level); +- } while (pending); ++ for (i = 0; i < NBANK(chip); i++) { ++ while (pending[i]) { ++ level = __ffs(pending[i]); ++ handle_nested_irq(irq_find_mapping(chip->domain, ++ level + (BANK_SZ * i))); ++ pending[i] &= ~(1 << level); ++ } ++ } + + return IRQ_HANDLED; + } + ++static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_clear_status_flags(irq, IRQ_NOREQUEST); ++ irq_set_chip_data(irq, d->host_data); ++ irq_set_chip(irq, &pca953x_irq_chip); ++ irq_set_nested_thread(irq, true); ++#ifdef CONFIG_ARM ++ set_irq_flags(irq, IRQF_VALID); ++#else ++ irq_set_noprobe(irq); ++#endif ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops pca953x_irq_simple_ops = { ++ .map = pca953x_gpio_irq_map, ++ .xlate = irq_domain_xlate_twocell, ++}; ++ + static int pca953x_irq_setup(struct pca953x_chip *chip, + const struct i2c_device_id *id, + int irq_base) + { + struct i2c_client *client = chip->client; +- int ret, offset = 0; ++ int ret, i, offset = 0; + + if (irq_base != -1 + && (id->driver_data & PCA_INT)) { +- int lvl; + + switch (chip->chip_type) { + case PCA953X_TYPE: +@@ -462,37 +559,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + offset = PCA957X_IN; + break; + } +- ret = pca953x_read_reg(chip, offset, &chip->irq_stat); ++ ret = pca953x_read_regs(chip, offset, chip->irq_stat); + if (ret) +- goto out_failed; ++ return ret; + + /* + * There is no way to know which GPIO line generated the + * interrupt. We have to rely on the previous read for + * this purpose. + */ +- chip->irq_stat &= chip->reg_direction; ++ for (i = 0; i < NBANK(chip); i++) ++ chip->irq_stat[i] &= chip->reg_direction[i]; + mutex_init(&chip->irq_lock); + +- chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); +- if (chip->irq_base < 0) +- goto out_failed; +- +- for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { +- int irq = lvl + chip->irq_base; ++ chip->domain = irq_domain_add_simple(client->dev.of_node, ++ chip->gpio_chip.ngpio, ++ irq_base, ++ &pca953x_irq_simple_ops, ++ chip); ++ if (!chip->domain) ++ return -ENODEV; + +- irq_clear_status_flags(irq, IRQ_NOREQUEST); +- irq_set_chip_data(irq, chip); +- irq_set_chip(irq, &pca953x_irq_chip); +- irq_set_nested_thread(irq, true); +-#ifdef CONFIG_ARM +- set_irq_flags(irq, IRQF_VALID); +-#else +- irq_set_noprobe(irq); +-#endif +- } +- +- ret = request_threaded_irq(client->irq, ++ ret = devm_request_threaded_irq(&client->dev, ++ client->irq, + NULL, + pca953x_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, +@@ -500,26 +589,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + if (ret) { + dev_err(&client->dev, "failed to request irq %d\n", + client->irq); +- goto out_failed; ++ return ret; + } + + chip->gpio_chip.to_irq = pca953x_gpio_to_irq; + } + + return 0; +- +-out_failed: +- chip->irq_base = -1; +- return ret; + } + +-static void pca953x_irq_teardown(struct pca953x_chip *chip) +-{ +- if (chip->irq_base != -1) { +- irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); +- free_irq(chip->client->irq, chip); +- } +-} + #else /* CONFIG_GPIO_PCA953X_IRQ */ + static int pca953x_irq_setup(struct pca953x_chip *chip, + const struct i2c_device_id *id, +@@ -532,10 +610,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + + return 0; + } +- +-static void pca953x_irq_teardown(struct pca953x_chip *chip) +-{ +-} + #endif + + /* +@@ -547,7 +621,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip) + * WARNING: This is DEPRECATED and will be removed eventually! + */ + static void +-pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) ++pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) + { + struct device_node *node; + const __be32 *val; +@@ -575,75 +649,80 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) + } + #else + static void +-pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert) ++pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) + { + *gpio_base = -1; + } + #endif + +-static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert) ++static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) + { + int ret; ++ u8 val[MAX_BANK]; + +- ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); ++ ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output); + if (ret) + goto out; + +- ret = pca953x_read_reg(chip, PCA953X_DIRECTION, +- &chip->reg_direction); ++ ret = pca953x_read_regs(chip, PCA953X_DIRECTION, ++ chip->reg_direction); + if (ret) + goto out; + + /* set platform specific polarity inversion */ +- ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); ++ if (invert) ++ memset(val, 0xFF, NBANK(chip)); ++ else ++ memset(val, 0, NBANK(chip)); ++ ++ ret = pca953x_write_regs(chip, PCA953X_INVERT, val); + out: + return ret; + } + +-static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert) ++static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) + { + int ret; +- uint16_t val = 0; +- +- /* Let every port in proper state, that could save power */ +- pca953x_write_reg(chip, PCA957X_PUPD, 0x0); +- pca953x_write_reg(chip, PCA957X_CFG, 0xffff); +- pca953x_write_reg(chip, PCA957X_OUT, 0x0); ++ u8 val[MAX_BANK]; + +- ret = pca953x_read_reg(chip, PCA957X_IN, &val); +- if (ret) +- goto out; +- ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output); ++ ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output); + if (ret) + goto out; +- ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction); ++ ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction); + if (ret) + goto out; + + /* set platform specific polarity inversion */ +- pca953x_write_reg(chip, PCA957X_INVRT, invert); ++ if (invert) ++ memset(val, 0xFF, NBANK(chip)); ++ else ++ memset(val, 0, NBANK(chip)); ++ pca953x_write_regs(chip, PCA957X_INVRT, val); + + /* To enable register 6, 7 to controll pull up and pull down */ +- pca953x_write_reg(chip, PCA957X_BKEN, 0x202); ++ memset(val, 0x02, NBANK(chip)); ++ pca953x_write_regs(chip, PCA957X_BKEN, val); + + return 0; + out: + return ret; + } + +-static int __devinit pca953x_probe(struct i2c_client *client, ++static int pca953x_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + struct pca953x_platform_data *pdata; + struct pca953x_chip *chip; +- int irq_base=0, invert=0; ++ int irq_base = 0; + int ret; ++ u32 invert = 0; + +- chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); ++ chip = devm_kzalloc(&client->dev, ++ sizeof(struct pca953x_chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + +- pdata = client->dev.platform_data; ++ pdata = dev_get_platdata(&client->dev); + if (pdata) { + irq_base = pdata->irq_base; + chip->gpio_start = pdata->gpio_base; +@@ -674,15 +753,15 @@ static int __devinit pca953x_probe(struct i2c_client *client, + else + ret = device_pca957x_init(chip, invert); + if (ret) +- goto out_failed; ++ return ret; + + ret = pca953x_irq_setup(chip, id, irq_base); + if (ret) +- goto out_failed; ++ return ret; + + ret = gpiochip_add(&chip->gpio_chip); + if (ret) +- goto out_failed_irq; ++ return ret; + + if (pdata && pdata->setup) { + ret = pdata->setup(client, chip->gpio_chip.base, +@@ -693,17 +772,11 @@ static int __devinit pca953x_probe(struct i2c_client *client, + + i2c_set_clientdata(client, chip); + return 0; +- +-out_failed_irq: +- pca953x_irq_teardown(chip); +-out_failed: +- kfree(chip); +- return ret; + } + + static int pca953x_remove(struct i2c_client *client) + { +- struct pca953x_platform_data *pdata = client->dev.platform_data; ++ struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); + struct pca953x_chip *chip = i2c_get_clientdata(client); + int ret = 0; + +@@ -724,14 +797,44 @@ static int pca953x_remove(struct i2c_client *client) + return ret; + } + +- pca953x_irq_teardown(chip); +- kfree(chip); + return 0; + } + ++static const struct of_device_id pca953x_dt_ids[] = { ++ { .compatible = "nxp,pca9505", }, ++ { .compatible = "nxp,pca9506", }, ++ { .compatible = "nxp,pca9534", }, ++ { .compatible = "nxp,pca9535", }, ++ { .compatible = "nxp,pca9536", }, ++ { .compatible = "nxp,pca9537", }, ++ { .compatible = "nxp,pca9538", }, ++ { .compatible = "nxp,pca9539", }, ++ { .compatible = "nxp,pca9554", }, ++ { .compatible = "nxp,pca9555", }, ++ { .compatible = "nxp,pca9556", }, ++ { .compatible = "nxp,pca9557", }, ++ { .compatible = "nxp,pca9574", }, ++ { .compatible = "nxp,pca9575", }, ++ { .compatible = "nxp,pca9698", }, ++ ++ { .compatible = "maxim,max7310", }, ++ { .compatible = "maxim,max7312", }, ++ { .compatible = "maxim,max7313", }, ++ { .compatible = "maxim,max7315", }, ++ ++ { .compatible = "ti,pca6107", }, ++ { .compatible = "ti,tca6408", }, ++ { .compatible = "ti,tca6416", }, ++ { .compatible = "ti,tca6424", }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, pca953x_dt_ids); ++ + static struct i2c_driver pca953x_driver = { + .driver = { + .name = "pca953x", ++ .of_match_table = pca953x_dt_ids, + }, + .probe = pca953x_probe, + .remove = pca953x_remove, +diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c +index 1635158..9610ae5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch new file mode 100644 index 00000000..28224943 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_gpio_gpio-sch.c.patch @@ -0,0 +1,195 @@ +--- a/drivers/gpio/gpio-sch.c ++++ b/drivers/gpio/gpio-sch.c +@@ -125,13 +125,17 @@ static int sch_gpio_resume_direction_in(struct gpio_chip *gc, + unsigned gpio_num) + { + u8 curr_dirs; ++ unsigned short offset, bit; + + spin_lock(&gpio_lock); + +- curr_dirs = inb(gpio_ba + RGIO); ++ offset = RGIO + gpio_num / 8; ++ bit = gpio_num % 8; ++ ++ curr_dirs = inb(gpio_ba + offset); + +- if (!(curr_dirs & (1 << gpio_num))) +- outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO); ++ if (!(curr_dirs & (1 << bit))) ++ outb(curr_dirs | (1 << bit), gpio_ba + offset); + + spin_unlock(&gpio_lock); + return 0; +@@ -139,22 +143,31 @@ static int sch_gpio_resume_direction_in(struct gpio_chip *gc, + + static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) + { +- return !!(inb(gpio_ba + RGLV) & (1 << gpio_num)); ++ unsigned short offset, bit; ++ ++ offset = RGLV + gpio_num / 8; ++ bit = gpio_num % 8; ++ ++ return !!(inb(gpio_ba + offset) & (1 << bit)); + } + + static void sch_gpio_resume_set(struct gpio_chip *gc, + unsigned gpio_num, int val) + { + u8 curr_vals; ++ unsigned short offset, bit; + + spin_lock(&gpio_lock); + +- curr_vals = inb(gpio_ba + RGLV); ++ offset = RGLV + gpio_num / 8; ++ bit = gpio_num % 8; ++ ++ curr_vals = inb(gpio_ba + offset); + + if (val) +- outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV); ++ outb(curr_vals | (1 << bit), gpio_ba + offset); + else +- outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV); ++ outb((curr_vals & ~(1 << bit)), gpio_ba + offset); + + spin_unlock(&gpio_lock); + } +@@ -163,14 +176,18 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc, + unsigned gpio_num, int val) + { + u8 curr_dirs; ++ unsigned short offset, bit; + + sch_gpio_resume_set(gc, gpio_num, val); + ++ offset = RGIO + gpio_num / 8; ++ bit = gpio_num % 8; ++ + spin_lock(&gpio_lock); + +- curr_dirs = inb(gpio_ba + RGIO); +- if (curr_dirs & (1 << gpio_num)) +- outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO); ++ curr_dirs = inb(gpio_ba + offset); ++ if (curr_dirs & (1 << bit)) ++ outb(curr_dirs & ~(1 << bit), gpio_ba + offset); + + spin_unlock(&gpio_lock); + return 0; +@@ -185,7 +202,7 @@ static struct gpio_chip sch_gpio_resume = { + .set = sch_gpio_resume_set, + }; + +-static int __devinit sch_gpio_probe(struct platform_device *pdev) ++static int sch_gpio_probe(struct platform_device *pdev) + { + struct resource *res; + int err, id; +@@ -204,36 +221,41 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) + gpio_ba = res->start; + + switch (id) { +- case PCI_DEVICE_ID_INTEL_SCH_LPC: +- sch_gpio_core.base = 0; +- sch_gpio_core.ngpio = 10; +- +- sch_gpio_resume.base = 10; +- sch_gpio_resume.ngpio = 4; +- +- /* +- * GPIO[6:0] enabled by default +- * GPIO7 is configured by the CMC as SLPIOVR +- * Enable GPIO[9:8] core powered gpios explicitly +- */ +- outb(0x3, gpio_ba + CGEN + 1); +- /* +- * SUS_GPIO[2:0] enabled by default +- * Enable SUS_GPIO3 resume powered gpio explicitly +- */ +- outb(0x8, gpio_ba + RGEN); +- break; +- +- case PCI_DEVICE_ID_INTEL_ITC_LPC: +- sch_gpio_core.base = 0; +- sch_gpio_core.ngpio = 5; +- +- sch_gpio_resume.base = 5; +- sch_gpio_resume.ngpio = 9; +- break; +- +- default: +- return -ENODEV; ++ case PCI_DEVICE_ID_INTEL_SCH_LPC: ++ sch_gpio_core.base = 0; ++ sch_gpio_core.ngpio = 10; ++ sch_gpio_resume.base = 10; ++ sch_gpio_resume.ngpio = 4; ++ /* ++ * GPIO[6:0] enabled by default ++ * GPIO7 is configured by the CMC as SLPIOVR ++ * Enable GPIO[9:8] core powered gpios explicitly ++ */ ++ outb(0x3, gpio_ba + CGEN + 1); ++ /* ++ * SUS_GPIO[2:0] enabled by default ++ * Enable SUS_GPIO3 resume powered gpio explicitly ++ */ ++ outb(0x8, gpio_ba + RGEN); ++ break; ++ ++ case PCI_DEVICE_ID_INTEL_ITC_LPC: ++ sch_gpio_core.base = 0; ++ sch_gpio_core.ngpio = 5; ++ sch_gpio_resume.base = 5; ++ sch_gpio_resume.ngpio = 9; ++ break; ++ ++ case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: ++ sch_gpio_core.base = 0; ++ sch_gpio_core.ngpio = 21; ++ sch_gpio_resume.base = 21; ++ sch_gpio_resume.ngpio = 9; ++ break; ++ ++ default: ++ err = -ENODEV; ++ goto err_sch_gpio_core; + } + + sch_gpio_core.dev = &pdev->dev; +@@ -250,10 +272,8 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev) + return 0; + + err_sch_gpio_resume: +- err = gpiochip_remove(&sch_gpio_core); +- if (err) +- dev_err(&pdev->dev, "%s failed, %d\n", +- "gpiochip_remove()", err); ++ if (gpiochip_remove(&sch_gpio_core)) ++ dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); + + err_sch_gpio_core: + release_region(res->start, resource_size(res)); +@@ -262,7 +282,7 @@ err_sch_gpio_core: + return err; + } + +-static int __devexit sch_gpio_remove(struct platform_device *pdev) ++static int sch_gpio_remove(struct platform_device *pdev) + { + struct resource *res; + if (gpio_ba) { +@@ -294,7 +314,7 @@ static struct platform_driver sch_gpio_driver = { + .owner = THIS_MODULE, + }, + .probe = sch_gpio_probe, +- .remove = __devexit_p(sch_gpio_remove), ++ .remove = sch_gpio_remove, + }; + + static int __init sch_gpio_init(void) +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index 1368826..cc11488 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch new file mode 100644 index 00000000..c6d04ba8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Kconfig.patch @@ -0,0 +1,87 @@ +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -293,6 +293,26 @@ config SENSORS_ATXP1 + This driver can also be built as a module. If so, the module + will be called atxp1. + ++config SENSORS_CY8CXX ++ tristate "Cypress Semiconductor CY8Cxx" ++ depends on I2C ++ help ++ If you say yes here you get support for Cypress Semiconductor ++ CY8C series sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called cy8cxx. ++ ++config SENSORS_CY8C3245R1 ++ tristate "Cypress Semiconductor CY8C3245R1" ++ depends on I2C ++ help ++ If you say yes here you get support for Cypress Semiconductor ++ CY8C3245 first revision sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called cy8c3245r1. ++ + config SENSORS_DS620 + tristate "Dallas Semiconductor DS620" + depends on I2C +@@ -474,8 +494,8 @@ config SENSORS_IT87 + select HWMON_VID + help + If you say yes here you get support for ITE IT8705F, IT8712F, +- IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor +- chips, and the SiS960 clone. ++ IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E ++ sensor chips, and the SiS960 clone. + + This driver can also be built as a module. If so, the module + will be called it87. +@@ -812,6 +832,27 @@ config SENSORS_MAX6650 + This driver can also be built as a module. If so, the module + will be called max6650. + ++config SENSORS_MAX6620 ++ tristate "Maxim MAX6620 sensor chip" ++ depends on I2C && EXPERIMENTAL ++ help ++ If you say yes here you get support for the MAX6620 ++ sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called max6620. ++ ++config SENSORS_MAX6697 ++ tristate "Maxim MAX6697 and compatibles" ++ depends on I2C ++ help ++ If you say yes here you get support for MAX6581, MAX6602, MAX6622, ++ MAX6636, MAX6689, MAX6693, MAX6694, MAX6697, MAX6698, and MAX6699 ++ temperature sensor chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called max6697. ++ + config SENSORS_NTC_THERMISTOR + tristate "NTC thermistor support" + depends on EXPERIMENTAL +@@ -964,6 +1005,16 @@ config SENSORS_EMC2103 + This driver can also be built as a module. If so, the module + will be called emc2103. + ++config SENSORS_EMC2305 ++ tristate "SMSC EMC2305" ++ depends on I2C ++ help ++ If you say yes here you get support for the SMSC EMC2305/EMC2303 ++ fan controller chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called emc2305. ++ + config SENSORS_EMC6W201 + tristate "SMSC EMC6W201" + depends on I2C +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index 8251ce8..ff3a18e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch new file mode 100644 index 00000000..64dc1603 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_Makefile.patch @@ -0,0 +1,28 @@ +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -42,11 +42,14 @@ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o + obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o + obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o + obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o ++obj-$(CONFIG_SENSORS_CY8CXX) += cy8cxx.o ++obj-$(CONFIG_SENSORS_CY8C3245R1) += cy8c3245r1.o + obj-$(CONFIG_SENSORS_DME1737) += dme1737.o + obj-$(CONFIG_SENSORS_DS620) += ds620.o + obj-$(CONFIG_SENSORS_DS1621) += ds1621.o + obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o + obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o ++obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o + obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o + obj-$(CONFIG_SENSORS_EXYNOS4_TMU) += exynos4_tmu.o + obj-$(CONFIG_SENSORS_F71805F) += f71805f.o +@@ -94,6 +97,8 @@ obj-$(CONFIG_SENSORS_MAX1668) += max1668.o + obj-$(CONFIG_SENSORS_MAX6639) += max6639.o + obj-$(CONFIG_SENSORS_MAX6642) += max6642.o + obj-$(CONFIG_SENSORS_MAX6650) += max6650.o ++obj-$(CONFIG_SENSORS_MAX6620) += max6620.o ++obj-$(CONFIG_SENSORS_MAX6697) += max6697.o + obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o + obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o + obj-$(CONFIG_SENSORS_PC87360) += pc87360.o +diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c +index 3a15fd6..e84af9c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch new file mode 100644 index 00000000..d6b2b379 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7470.c.patch @@ -0,0 +1,35 @@ +--- a/drivers/hwmon/adt7470.c ++++ b/drivers/hwmon/adt7470.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + /* Addresses to scan */ + static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; +@@ -48,6 +49,7 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; + #define ADT7470_REG_PWM_MAX_MAX_ADDR 0x3B + #define ADT7470_REG_CFG 0x40 + #define ADT7470_FSPD_MASK 0x04 ++#define ADT7470_TODIS_MASK 0x08 + #define ADT7470_REG_ALARM1 0x41 + #define ADT7470_R1T_ALARM 0x01 + #define ADT7470_R2T_ALARM 0x02 +@@ -225,6 +227,14 @@ static void adt7470_init_client(struct i2c_client *client) + if (reg < 0) { + dev_err(&client->dev, "cannot read configuration register\n"); + } else { ++ struct property *pp; ++ pp = of_find_property(client->dev.of_node, ++ "disable-smbus-timeout", NULL); ++ if (pp) ++ reg |= ADT7470_TODIS_MASK; ++ else ++ reg &= ~ADT7470_TODIS_MASK; ++ + /* start monitoring (and do a self-test) */ + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3); + } +diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c +index b5fcd87..d460f4e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch new file mode 100644 index 00000000..35523d22 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_adt7475.c.patch @@ -0,0 +1,26 @@ +--- a/drivers/hwmon/adt7475.c ++++ b/drivers/hwmon/adt7475.c +@@ -671,6 +671,21 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + return count; + } + ++ /* Clear PWM invert bit, i.e. force normal sense of ++ * duty cycle. See ADT7473 data sheet for description ++ * of register 0x5C, bit 4: ++ * ++ * This bit inverts the PWM output. The default is ++ * 0, which corresponds to a logic high output for ++ * 100% duty cycle. Setting this bit to 1 inverts ++ * the PWM output, so 100% duty cycle corresponds to ++ * a logic low output. ++ * ++ */ ++ data->pwm[CONTROL][sattr->index] &= ~(1 << 4); ++ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(sattr->index), ++ data->pwm[CONTROL][sattr->index]); ++ + reg = PWM_REG(sattr->index); + break; + +diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c +index e6ec920..ce9d21f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch new file mode 100644 index 00000000..e24eea5c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_coretemp.c.patch @@ -0,0 +1,40 @@ +--- a/drivers/hwmon/coretemp.c ++++ b/drivers/hwmon/coretemp.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #define DRVNAME "coretemp" + +@@ -791,13 +792,23 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { + .notifier_call = coretemp_cpu_callback, + }; + ++static const struct x86_cpu_id coretemp_ids[] = { ++ { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); ++ + static int __init coretemp_init(void) + { + int i, err = -ENODEV; + +- /* quick check if we run Intel */ +- if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) +- goto exit; ++ /* ++ * CPUID.06H.EAX[0] indicates whether the CPU has thermal ++ * sensors. We check this bit only, all the early CPUs ++ * without thermal sensors will be filtered out. ++ */ ++ if (!x86_match_cpu(coretemp_ids)) ++ return -ENODEV; + + err = platform_driver_register(&coretemp_driver); + if (err) +diff --git a/drivers/hwmon/cy8c3245r1.c b/drivers/hwmon/cy8c3245r1.c +new file mode 100644 +index 0000000..3cf12d5 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch new file mode 100644 index 00000000..33486dc7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8c3245r1.c.patch @@ -0,0 +1,1087 @@ +--- /dev/null ++++ b/drivers/hwmon/cy8c3245r1.c +@@ -0,0 +1,1081 @@ ++/* ++ * A hwmon driver for the Cypress Semiconductor C3245 ++ * Copyright (C) 2014 Cumulus Networks ++ * ++ * Author: Shrijeet Mukherjee ++ * Author: Vidya Ravipati ++ * ++ * Based on the adt7470 driver ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* cy8c3245r1 registers */ ++#define CY8C3245R1_REG_BASE_ADDR 0x00 ++#define CY8C3245R1_REG_DEV_ID 0x09 ++#define CY8C3245R1_REG_COMPANY_ID 0x05 ++#define CY8C3245R1_REG_FW_REV_MAJ 0x06 ++#define CY8C3245R1_REG_FW_REV_MIN 0x07 ++#define CY8C3245R1_REG_RESET 0x08 ++ ++/* ++ * Fan PWM / RPM Profile control registers ++ * ++ * These registers consist of two-bytes each ++ */ ++#define CY8C3245R1_REG_FAN_PROFILE_BASE_ADDR 0x10 ++#define CY8C3245R1_REG_FAN_PROFILE(x) (CY8C3245R1_REG_FAN_PROFILE_BASE_ADDR + ((x) * 2)) ++enum { ++ CY8C3245R1_FAN_PROFILE_LOW_DUTY = 0, ++ CY8C3245R1_FAN_PROFILE_LOW_RPM, ++ CY8C3245R1_FAN_PROFILE_HIGH_DUTY, ++ CY8C3245R1_FAN_PROFILE_HIGH_RPM, ++ CY8C3245R1_FAN_PROFILE_SPEED_0_DUTY, ++ CY8C3245R1_FAN_PROFILE_SPEED_100_DUTY, ++ CY8C3245R1_FAN_PROFILE_MAX ++}; ++ ++/* skipping over regs to set */ ++ ++#define CY8C3245R1_REG_TEMP_BASE_ADDR 0x20 ++ ++#define CY8C3245R1_REG_FAN_BASE_ADDR 0x40 ++#define CY8C3245R1_REG_FAN_TARGET_BASE_ADDR 0x3E ++ ++#define CY8C3245R1_REG_PWM_BASE_ADDR 0x3C ++ ++#define CY8C3245R1_REG_TEMP_LIMITS_BASE_ADDR 0x20 ++#define CY8C3245R1_REG_TEMP_LIMITS_MAX_ADDR 0x28 ++ ++#define CY8C3245R1_REG_FAN_MAX_BASE_ADDR 0x16 ++ ++#define CY8C3245R1_REG_PWM_CFG_BASE_ADDR 0x33 ++ ++#define CY8C3245R1_TEMP_COUNT 8 ++#define CY8C3245R1_TEMP_REG(x) (CY8C3245R1_REG_TEMP_BASE_ADDR + (x)) ++#define CY8C3245R1_TEMP_MAX_REG(x) (CY8C3245R1_REG_TEMP_LIMITS_MAX_ADDR + (x)) ++ ++#define CY8C3245R1_FAN_COUNT 8 ++#define CY8C3245R1_REG_FAN(x) (CY8C3245R1_REG_FAN_BASE_ADDR + ((x) * 2)) ++ ++#define CY8C3245R1_REG_FAN_MIN(x) (CY8C3245R1_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) ++#define CY8C3245R1_REG_FAN_MAX(x) (CY8C3245R1_REG_FAN_MAX_BASE_ADDR) ++#define CY8C3245R1_REG_FAN_TARGET (CY8C3245R1_REG_FAN_TARGET_BASE_ADDR) ++ ++#define CY8C3245R1_PWM_COUNT 1 ++#define CY8C3245R1_REG_PWM (CY8C3245R1_REG_PWM_BASE_ADDR) ++ ++#define CY8C3245R1_COMPANY_ID 0xCC ++#define CY8C3245R1_DEV_ID 0x09 ++#define CY8C3245R1_FW_REV_MAJ 0x02 ++#define CY8C3245R1_FW_REV_MIN 0x03 ++ ++/* "all temps" according to hwmon sysfs interface spec */ ++#define CY8C3245R1_PWM_ALL_TEMPS 0x3FF ++ ++/* How often do we reread sensors values? (In jiffies) */ ++#define SENSOR_REFRESH_INTERVAL (5 * HZ) ++ ++/* How often do we reread sensor limit values? (In jiffies) */ ++#define LIMIT_REFRESH_INTERVAL (60 * HZ) ++ ++/* Wait at least 200ms per sensor for 10 sensors */ ++#define TEMP_COLLECTION_TIME 2000 ++ ++/* auto update thing won't fire more than every 2s */ ++#define AUTO_UPDATE_INTERVAL 2000 ++ ++/* datasheet says to divide this number by the fan reading to get fan rpm */ ++#define FAN_PERIOD_INVALID 65535 ++#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) ++ ++struct cy8c3245r1_data { ++ struct device *hwmon_dev; ++ struct attribute_group attrs; ++ struct mutex lock; ++ char sensors_valid; ++ char limits_valid; ++ unsigned long sensors_last_updated; /* In jiffies */ ++ unsigned long limits_last_updated; /* In jiffies */ ++ ++ int num_temp_sensors; /* -1 = probe */ ++ int temperatures_probed; ++ ++ s8 temp[CY8C3245R1_TEMP_COUNT]; ++ s8 temp_max[CY8C3245R1_TEMP_COUNT]; ++ u16 fan[CY8C3245R1_FAN_COUNT]; ++ u16 fan_max[CY8C3245R1_FAN_COUNT]; ++ u16 fan_min[CY8C3245R1_FAN_COUNT]; ++ u16 fan_tgt; ++ u16 fan_profile[CY8C3245R1_FAN_PROFILE_MAX]; ++ u8 fan_alarm; ++ u8 temp_alarm; ++ u8 force_pwm_max; ++ u8 pwm; ++ u8 pwm_automatic; ++ struct task_struct *auto_update; ++ struct completion auto_update_stop; ++ unsigned int auto_update_interval; ++}; ++ ++static int cy8c3245r1_probe(struct i2c_client *client, ++ const struct i2c_device_id *id); ++static int cy8c3245r1_remove(struct i2c_client *client); ++ ++static const struct i2c_device_id cy8c3245r1_id[] = { ++ { "CY8C3245R1", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, cy8c3245r1_id); ++ ++static struct i2c_driver cy8c3245r1_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "cy8c3245r1", ++ }, ++ .probe = cy8c3245r1_probe, ++ .remove = cy8c3245r1_remove, ++ .id_table = cy8c3245r1_id, ++}; ++ ++/* ++ * 16-bit registers on the CY8C3245R1 are high-byte first. ++ */ ++static inline int cy8c3245r1_read_word_data(struct i2c_client *client, u8 reg) ++{ ++ s32 rc; ++ u16 val; ++ ++ /* read high byte */ ++ rc = i2c_smbus_read_byte_data(client, reg); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg, -rc); ++ return rc; ++ } ++ val = ((u16)rc & 0xFF) << 8; ++ ++ /* read low byte */ ++ rc = i2c_smbus_read_byte_data(client, reg + 1); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg + 1, -rc); ++ return rc; ++ } ++ val |= (u16)rc & 0xFF; ++ ++ return val; ++} ++ ++static inline int cy8c3245r1_write_word_data(struct i2c_client *client, ++ u8 reg, ++ u16 value) ++{ ++ s32 rc; ++ ++ /* write high byte */ ++ rc = i2c_smbus_write_byte_data(client, reg, value >> 8); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg, value >> 8, -rc); ++ return rc; ++ } ++ ++ /* write low byte */ ++ rc = i2c_smbus_write_byte_data(client, reg + 1, value & 0xFF); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg + 1, value & 0xFF, -rc); ++ return rc; ++ } ++ ++ return rc; ++} ++ ++static void cy8c3245r1_init_client(struct i2c_client *client) ++{ ++ int reg = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_PWM_CFG_BASE_ADDR); ++ ++ if (reg < 0) { ++ dev_err(&client->dev, "cannot read configuration register\n"); ++ } else { ++ i2c_smbus_write_byte_data(client, CY8C3245R1_REG_PWM_CFG_BASE_ADDR, 0); ++ } ++} ++ ++/* Probe for temperature sensors. Assumes lock is held */ ++static int cy8c3245r1_read_temperatures(struct i2c_client *client, ++ struct cy8c3245r1_data *data) ++{ ++ int i; ++ ++ /* Only count fans if we have to */ ++ if (data->num_temp_sensors >= 0) ++ return 0; ++ ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) { ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_TEMP_REG(i)); ++ if (data->temp[i]) ++ data->num_temp_sensors = i + 1; ++ } ++ data->temperatures_probed = 1; ++ return 0; ++} ++ ++static int cy8c3245r1_update_thread(void *p) ++{ ++ struct i2c_client *client = p; ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ ++ while (!kthread_should_stop()) { ++ mutex_lock(&data->lock); ++ cy8c3245r1_read_temperatures(client, data); ++ mutex_unlock(&data->lock); ++ if (kthread_should_stop()) ++ break; ++ msleep_interruptible(data->auto_update_interval); ++ } ++ ++ complete_all(&data->auto_update_stop); ++ return 0; ++} ++ ++static struct cy8c3245r1_data *cy8c3245r1_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ unsigned long local_jiffies = jiffies; ++ int i; ++ int need_sensors = 1; ++ int need_limits = 1; ++ ++ /* ++ * Figure out if we need to update the shadow registers. ++ * Lockless means that we may occasionally report out of ++ * date data. ++ */ ++ if (time_before(local_jiffies, data->sensors_last_updated + ++ SENSOR_REFRESH_INTERVAL) && ++ data->sensors_valid) ++ need_sensors = 0; ++ ++ if (time_before(local_jiffies, data->limits_last_updated + ++ LIMIT_REFRESH_INTERVAL) && ++ data->limits_valid) ++ need_limits = 0; ++ ++ if (!need_sensors && !need_limits) ++ return data; ++ ++ mutex_lock(&data->lock); ++ if (!need_sensors) ++ goto no_sensor_update; ++ ++ if (!data->temperatures_probed) ++ cy8c3245r1_read_temperatures(client, data); ++ else ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_TEMP_REG(i)); ++ ++ for (i = 0; i < CY8C3245R1_FAN_COUNT; i++) { ++ data->fan[i] = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN(i)); ++ } ++ ++ data->pwm = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_REG_PWM); ++ ++ data->sensors_last_updated = local_jiffies; ++ data->sensors_valid = 1; ++ ++no_sensor_update: ++ if (!need_limits) ++ goto out; ++ ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) { ++ data->temp_max[i] = i2c_smbus_read_byte_data(client, ++ CY8C3245R1_TEMP_MAX_REG(i)); ++ } ++ ++ for (i = 0; i < CY8C3245R1_FAN_COUNT; i++) { ++ data->fan_max[i] = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN_MAX(i)); ++ } ++ data->fan_tgt = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN_TARGET); ++ ++ for (i = 0; i < CY8C3245R1_FAN_PROFILE_MAX; i++) { ++ data->fan_profile[i] = cy8c3245r1_read_word_data(client, ++ CY8C3245R1_REG_FAN_PROFILE(i)); ++ } ++ ++ data->limits_last_updated = local_jiffies; ++ data->limits_valid = 1; ++ ++out: ++ mutex_unlock(&data->lock); ++ return data; ++} ++ ++static ssize_t show_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", data->auto_update_interval); ++} ++ ++static ssize_t set_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 60000); ++ ++ mutex_lock(&data->lock); ++ data->auto_update_interval = temp; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", data->num_temp_sensors); ++} ++ ++static ssize_t set_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, -1, 10); ++ ++ mutex_lock(&data->lock); ++ data->num_temp_sensors = temp; ++ if (temp < 0) ++ data->temperatures_probed = 0; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]); ++} ++ ++static ssize_t set_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = DIV_ROUND_CLOSEST(temp, 1000); ++ temp = SENSORS_LIMIT(temp, -128, 127); ++ ++ mutex_lock(&data->lock); ++ data->temp_max[attr->index] = temp; ++ i2c_smbus_write_byte_data(client, CY8C3245R1_TEMP_MAX_REG(attr->index), ++ temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); ++} ++ ++static ssize_t show_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_max[attr->index])) ++ return sprintf(buf, "%d\n", ++ data->fan_max[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_max[attr->index] = rpm; ++ cy8c3245r1_write_word_data(client, CY8C3245R1_REG_FAN_MAX(attr->index), rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * fan_min is a pure software concept, not implemented by hardware. ++ * It is used to compute the alarm status. ++ */ ++static ssize_t show_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->fan_min[attr->index]); ++} ++ ++static ssize_t set_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_min[attr->index] = rpm; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_tgt)) ++ return sprintf(buf, "%d\n", ++ data->fan_tgt); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_tgt = rpm; ++ cy8c3245r1_write_word_data(client, CY8C3245R1_REG_FAN_TARGET, rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * Show Fan Profile Settings ++ */ ++static ssize_t show_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ return sprintf(buf, "%u\n", ++ data->fan_profile[attr->index]); ++} ++ ++/* ++ * Set Fan Profile Settings ++ */ ++static ssize_t set_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long parm; ++ ++ if (strict_strtoul(buf, 10, &parm)) ++ return -EINVAL; ++ ++ parm = SENSORS_LIMIT(parm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_profile[attr->index] = parm; ++ cy8c3245r1_write_word_data(client, CY8C3245R1_REG_FAN_PROFILE(attr->index), parm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan[attr->index])) ++ return sprintf(buf, "%d\n", data->fan[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ return sprintf(buf, "%d\n", data->pwm); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 255); ++ ++ mutex_lock(&data->lock); ++ data->pwm = temp; ++ i2c_smbus_write_byte_data(client, CY8C3245R1_REG_PWM, temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3245R1_FAN_COUNT; i++) ++ if ((data->fan[i] < data->fan_min[i]) || ++ (data->fan[i] >= data->fan_max[i])) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_temp_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3245R1_TEMP_COUNT; i++) ++ if (data->temp[i] >= data->temp_max[i]) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_fan_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if ((data->fan[attr->index] < data->fan_min[attr->index]) || ++ (data->fan[attr->index] >= data->fan_max[attr->index])) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_temp_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ if (data->temp[attr->index] >= data->temp_max[attr->index]) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ if (!(temp >= 0 && temp <= 3)) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static ssize_t show_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3245r1_data *data = cy8c3245r1_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->pwm_automatic); ++} ++ ++#define CY8C3245R1_REG_MIN 0x00 ++#define CY8C3245R1_REG_MAX 0xe0 ++ ++static ssize_t show_debug(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ int len = 0, i, j; ++ u8 val; ++ for (i = 0; i < (CY8C3245R1_REG_MAX - CY8C3245R1_REG_MIN) / 16; i++) { ++ len += sprintf(buf+len, "0x%02x: ", CY8C3245R1_REG_MIN + (i * 16)); ++ for (j = 0; j < 16; j++) { ++ val = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_MIN + (i * 16) + j); ++ len += sprintf(buf+len, "%02x ", val); ++ } ++ len += sprintf(buf+len, "\n"); ++ } ++ return len; ++} ++ ++static DEVICE_ATTR(fan_alarm_mask, S_IRUGO, show_fan_alarm_mask, NULL); ++static DEVICE_ATTR(temp_alarm_mask, S_IRUGO, show_temp_alarm_mask, NULL); ++static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, ++ set_num_temp_sensors); ++static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO, ++ show_auto_update_interval, set_auto_update_interval); ++ ++static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 0); ++static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 1); ++static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 2); ++static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 3); ++static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 4); ++static SENSOR_DEVICE_ATTR(temp6_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 5); ++static SENSOR_DEVICE_ATTR(temp7_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 6); ++static SENSOR_DEVICE_ATTR(temp8_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 7); ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5); ++static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6); ++static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++ ++static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 0); ++static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 1); ++static SENSOR_DEVICE_ATTR(fan3_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 2); ++static SENSOR_DEVICE_ATTR(fan4_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 3); ++static SENSOR_DEVICE_ATTR(fan5_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 4); ++static SENSOR_DEVICE_ATTR(fan6_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 5); ++static SENSOR_DEVICE_ATTR(fan7_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 6); ++static SENSOR_DEVICE_ATTR(fan8_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 0); ++static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 1); ++static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 2); ++static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 3); ++static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 4); ++static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 5); ++static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 6); ++static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 3); ++static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 4); ++static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 5); ++static SENSOR_DEVICE_ATTR(fan7_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 6); ++static SENSOR_DEVICE_ATTR(fan8_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 7); ++ ++#define FAN_PROFILE_ATTR(_name, _index) \ ++ SENSOR_DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ ++ show_fan_profile, set_fan_profile, _index) ++ ++static FAN_PROFILE_ATTR(fan_low_duty, CY8C3245R1_FAN_PROFILE_LOW_DUTY); ++static FAN_PROFILE_ATTR(fan_low_rpm, CY8C3245R1_FAN_PROFILE_LOW_RPM); ++static FAN_PROFILE_ATTR(fan_high_duty, CY8C3245R1_FAN_PROFILE_HIGH_DUTY); ++static FAN_PROFILE_ATTR(fan_high_rpm, CY8C3245R1_FAN_PROFILE_HIGH_RPM); ++static FAN_PROFILE_ATTR(fan_speed_0_duty, CY8C3245R1_FAN_PROFILE_SPEED_0_DUTY); ++static FAN_PROFILE_ATTR(fan_speed_100_duty,CY8C3245R1_FAN_PROFILE_SPEED_100_DUTY); ++ ++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); ++static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); ++static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); ++static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); ++static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); ++static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 5); ++static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 6); ++static SENSOR_DEVICE_ATTR(pwm8, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm7_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm8_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++ ++static SENSOR_DEVICE_ATTR(debug, S_IRUGO, show_debug, NULL, 0); ++ ++static struct attribute *cy8c3245r1_attr[] = ++{ ++ &dev_attr_fan_alarm_mask.attr, ++ &dev_attr_temp_alarm_mask.attr, ++ &dev_attr_num_temp_sensors.attr, ++ &dev_attr_auto_update_interval.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp4_max.dev_attr.attr, ++ &sensor_dev_attr_temp5_max.dev_attr.attr, ++ &sensor_dev_attr_temp6_max.dev_attr.attr, ++ &sensor_dev_attr_temp7_max.dev_attr.attr, ++ &sensor_dev_attr_temp8_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_temp6_input.dev_attr.attr, ++ &sensor_dev_attr_temp7_input.dev_attr.attr, ++ &sensor_dev_attr_temp8_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp6_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp7_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp8_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan1_max.dev_attr.attr, ++ &sensor_dev_attr_fan2_max.dev_attr.attr, ++ &sensor_dev_attr_fan3_max.dev_attr.attr, ++ &sensor_dev_attr_fan4_max.dev_attr.attr, ++ &sensor_dev_attr_fan5_max.dev_attr.attr, ++ &sensor_dev_attr_fan6_max.dev_attr.attr, ++ &sensor_dev_attr_fan7_max.dev_attr.attr, ++ &sensor_dev_attr_fan8_max.dev_attr.attr, ++ &sensor_dev_attr_fan1_min.dev_attr.attr, ++ &sensor_dev_attr_fan2_min.dev_attr.attr, ++ &sensor_dev_attr_fan3_min.dev_attr.attr, ++ &sensor_dev_attr_fan4_min.dev_attr.attr, ++ &sensor_dev_attr_fan5_min.dev_attr.attr, ++ &sensor_dev_attr_fan6_min.dev_attr.attr, ++ &sensor_dev_attr_fan7_min.dev_attr.attr, ++ &sensor_dev_attr_fan8_min.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan5_target.dev_attr.attr, ++ &sensor_dev_attr_fan6_target.dev_attr.attr, ++ &sensor_dev_attr_fan7_target.dev_attr.attr, ++ &sensor_dev_attr_fan8_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan5_input.dev_attr.attr, ++ &sensor_dev_attr_fan6_input.dev_attr.attr, ++ &sensor_dev_attr_fan7_input.dev_attr.attr, ++ &sensor_dev_attr_fan8_input.dev_attr.attr, ++ &sensor_dev_attr_fan1_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan2_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan3_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan4_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan5_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan6_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan7_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan8_alarm.dev_attr.attr, ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ &sensor_dev_attr_pwm5.dev_attr.attr, ++ &sensor_dev_attr_pwm6.dev_attr.attr, ++ &sensor_dev_attr_pwm7.dev_attr.attr, ++ &sensor_dev_attr_pwm8.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm5_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm6_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm7_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm8_enable.dev_attr.attr, ++ &sensor_dev_attr_fan_low_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_low_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_high_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_high_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_0_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_100_duty.dev_attr.attr, ++ &sensor_dev_attr_debug.dev_attr.attr, ++ NULL ++}; ++ ++static int cy8c3245r1_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct cy8c3245r1_data *data; ++ int err; ++ int minor_revision, major_revision; ++ ++ data = kzalloc(sizeof(struct cy8c3245r1_data), GFP_KERNEL); ++ if (!data) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ data->num_temp_sensors = -1; ++ data->auto_update_interval = AUTO_UPDATE_INTERVAL; ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->lock); ++ ++ dev_info(&client->dev, "%s chip found\n", client->name); ++ ++ /* Initialize the CY8C3245R1 chip */ ++ cy8c3245r1_init_client(client); ++ ++ minor_revision = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_FW_REV_MIN); ++ major_revision = i2c_smbus_read_byte_data(client, CY8C3245R1_REG_FW_REV_MAJ); ++ if ((minor_revision < CY8C3245R1_FW_REV_MIN) || ++ (major_revision != CY8C3245R1_FW_REV_MAJ)) { ++ dev_err(&client->dev, ++ "PSoC Supported Version >= %u.%u, Current version %u.%u\n", ++ CY8C3245R1_FW_REV_MAJ, CY8C3245R1_FW_REV_MIN, major_revision, ++ minor_revision); ++ err = -ENODEV; ++ goto exit_free; ++ } ++ ++ /* Register sysfs hooks */ ++ data->attrs.attrs = cy8c3245r1_attr; ++ if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) ++ goto exit_free; ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ init_completion(&data->auto_update_stop); ++ data->auto_update = kthread_run(cy8c3245r1_update_thread, client, ++ dev_name(data->hwmon_dev)); ++ if (IS_ERR(data->auto_update)) { ++ err = PTR_ERR(data->auto_update); ++ goto exit_unregister; ++ } ++ ++ return 0; ++ ++exit_unregister: ++ hwmon_device_unregister(data->hwmon_dev); ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int cy8c3245r1_remove(struct i2c_client *client) ++{ ++ struct cy8c3245r1_data *data = i2c_get_clientdata(client); ++ ++ kthread_stop(data->auto_update); ++ wait_for_completion(&data->auto_update_stop); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++ kfree(data); ++ return 0; ++} ++ ++static int __init cy8c3245r1_init(void) ++{ ++ return i2c_add_driver(&cy8c3245r1_driver); ++} ++ ++static void __exit cy8c3245r1_exit(void) ++{ ++ i2c_del_driver(&cy8c3245r1_driver); ++} ++ ++MODULE_AUTHOR("Shrijeet Mukherjee "); ++MODULE_AUTHOR("Vidya Ravipati "); ++MODULE_DESCRIPTION("CY8C3245R1 driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(cy8c3245r1_init); ++module_exit(cy8c3245r1_exit); +diff --git a/drivers/hwmon/cy8cxx.c b/drivers/hwmon/cy8cxx.c +new file mode 100644 +index 0000000..3edfbe7 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch new file mode 100644 index 00000000..a2de0980 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_cy8cxx.c.patch @@ -0,0 +1,1090 @@ +--- /dev/null ++++ b/drivers/hwmon/cy8cxx.c +@@ -0,0 +1,1084 @@ ++/* ++ * A hwmon driver for the Cypress Semiconductor C3245 ++ * Copyright (C) 2013 Cumulus Networks ++ * ++ * Author: Shrijeet Mukherjee ++ * ++ * Based on the adt7470 driver ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Addresses to scan */ ++static const unsigned short normal_i2c[] = { 0x2E, I2C_CLIENT_END }; ++ ++/* CY8C3XX registers */ ++#define CY8C3XX_REG_BASE_ADDR 0x00 ++#define CY8C3XX_REG_DEV_ID 0x04 ++#define CY8C3XX_REG_COMPANY_ID 0x05 ++#define CY8C3XX_REG_FW_REV_MAJ 0x06 ++#define CY8C3XX_REG_FW_REV_MIN 0x07 ++#define CY8C3XX_REG_RESET 0x08 ++ ++/* ++ * Fan PWM / RPM Profile control registers ++ * ++ * These registers consist of two-bytes each ++ */ ++#define CY8C3XX_REG_FAN_PROFILE_BASE_ADDR 0x10 ++#define CY8C3XX_REG_FAN_PROFILE(x) (CY8C3XX_REG_FAN_PROFILE_BASE_ADDR + ((x) * 2)) ++enum { ++ CY8C3XX_FAN_PROFILE_LOW_DUTY = 0, ++ CY8C3XX_FAN_PROFILE_LOW_RPM, ++ CY8C3XX_FAN_PROFILE_HIGH_DUTY, ++ CY8C3XX_FAN_PROFILE_HIGH_RPM, ++ CY8C3XX_FAN_PROFILE_SPEED_0_DUTY, ++ CY8C3XX_FAN_PROFILE_SPEED_100_DUTY, ++ CY8C3XX_FAN_PROFILE_MAX ++}; ++ ++/* skipping over regs to set */ ++ ++#define CY8C3XX_REG_TEMP_BASE_ADDR 0x30 ++ ++#define CY8C3XX_REG_FAN_BASE_ADDR 0x80 ++#define CY8C3XX_REG_FAN_TARGET_BASE_ADDR 0xA0 ++ ++#define CY8C3XX_REG_PWM_BASE_ADDR 0x60 ++ ++#define CY8C3XX_REG_PWM_MAX_BASE_ADDR 0x38 ++ ++#define CY8C3XX_REG_TEMP_LIMITS_BASE_ADDR 0x30 ++#define CY8C3XX_REG_TEMP_LIMITS_MAX_ADDR 0x40 ++ ++#define CY8C3XX_REG_FAN_MAX_BASE_ADDR 0x16 ++ ++#define CY8C3XX_REG_PWM_CFG_BASE_ADDR 0x55 ++ ++#define CY8C3XX_TEMP_COUNT 5 ++#define CY8C3XX_TEMP_REG(x) (CY8C3XX_REG_TEMP_BASE_ADDR + (x)) ++#define CY8C3XX_TEMP_MAX_REG(x) (CY8C3XX_REG_TEMP_LIMITS_MAX_ADDR + (x)) ++ ++#define CY8C3XX_FAN_COUNT 8 ++#define CY8C3XX_REG_FAN(x) (CY8C3XX_REG_FAN_BASE_ADDR + ((x) * 2)) ++ ++#define CY8C3XX_REG_FAN_MIN(x) (CY8C3XX_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) ++#define CY8C3XX_REG_FAN_MAX(x) (CY8C3XX_REG_FAN_MAX_BASE_ADDR) ++#define CY8C3XX_REG_FAN_TARGET(x) (CY8C3XX_REG_FAN_TARGET_BASE_ADDR + \ ++ ((x) * 2)) ++ ++#define CY8C3XX_PWM_COUNT 8 ++#define CY8C3XX_REG_PWM(x) (CY8C3XX_REG_PWM_BASE_ADDR + ((x) * 2)) ++ ++#define CY8C3XX_COMPANY_ID 0xCC ++#define CY8C3XX_DEV_ID 0x02 ++#define CY8C3XX_FW_REV_MAJ 0x01 ++ ++/* "all temps" according to hwmon sysfs interface spec */ ++#define CY8C3XX_PWM_ALL_TEMPS 0x3FF ++ ++/* How often do we reread sensors values? (In jiffies) */ ++#define SENSOR_REFRESH_INTERVAL (5 * HZ) ++ ++/* How often do we reread sensor limit values? (In jiffies) */ ++#define LIMIT_REFRESH_INTERVAL (60 * HZ) ++ ++/* Wait at least 200ms per sensor for 10 sensors */ ++#define TEMP_COLLECTION_TIME 2000 ++ ++/* auto update thing won't fire more than every 2s */ ++#define AUTO_UPDATE_INTERVAL 2000 ++ ++/* datasheet says to divide this number by the fan reading to get fan rpm */ ++#define FAN_PERIOD_INVALID 65535 ++#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) ++ ++struct cy8c3xx_data { ++ struct device *hwmon_dev; ++ struct attribute_group attrs; ++ struct mutex lock; ++ char sensors_valid; ++ char limits_valid; ++ unsigned long sensors_last_updated; /* In jiffies */ ++ unsigned long limits_last_updated; /* In jiffies */ ++ ++ int num_temp_sensors; /* -1 = probe */ ++ int temperatures_probed; ++ ++ s8 temp[CY8C3XX_TEMP_COUNT]; ++ s8 temp_max[CY8C3XX_TEMP_COUNT]; ++ u16 fan[CY8C3XX_FAN_COUNT]; ++ u16 fan_max[CY8C3XX_FAN_COUNT]; ++ u16 fan_min[CY8C3XX_FAN_COUNT]; ++ u16 fan_tgt[CY8C3XX_FAN_COUNT]; ++ u16 fan_profile[CY8C3XX_FAN_PROFILE_MAX]; ++ u8 fan_alarm; ++ u8 temp_alarm; ++ u8 force_pwm_max; ++ u8 pwm[CY8C3XX_PWM_COUNT]; ++ u8 pwm_automatic; ++ struct task_struct *auto_update; ++ struct completion auto_update_stop; ++ unsigned int auto_update_interval; ++}; ++ ++static int cy8c3xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *id); ++static int cy8c3xx_detect(struct i2c_client *client, ++ struct i2c_board_info *info); ++static int cy8c3xx_remove(struct i2c_client *client); ++ ++static const struct i2c_device_id cy8c3xx_id[] = { ++ { "CY8C3245", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, cy8c3xx_id); ++ ++static struct i2c_driver cy8c3xx_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "cy8c3xx", ++ }, ++ .probe = cy8c3xx_probe, ++ .remove = cy8c3xx_remove, ++ .id_table = cy8c3xx_id, ++ .detect = cy8c3xx_detect, ++ .address_list = normal_i2c, ++}; ++ ++/* ++ * 16-bit registers on the CY8C3XX are high-byte first. ++ */ ++static inline int cy8c3xx_read_word_data(struct i2c_client *client, u8 reg) ++{ ++ s32 rc; ++ u16 val; ++ ++ /* read high byte */ ++ rc = i2c_smbus_read_byte_data(client, reg); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg, -rc); ++ return rc; ++ } ++ val = ((u16)rc & 0xFF) << 8; ++ ++ /* read low byte */ ++ rc = i2c_smbus_read_byte_data(client, reg + 1); ++ if (rc < 0) { ++ dev_warn(&client->dev, "i2c read failed: 0x%02x, errno %d\n", ++ reg + 1, -rc); ++ return rc; ++ } ++ val |= (u16)rc & 0xFF; ++ ++ return val; ++} ++ ++static inline int cy8c3xx_write_word_data(struct i2c_client *client, ++ u8 reg, ++ u16 value) ++{ ++ s32 rc; ++ ++ /* write high byte */ ++ rc = i2c_smbus_write_byte_data(client, reg, value >> 8); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg, value >> 8, -rc); ++ return rc; ++ } ++ ++ /* write low byte */ ++ rc = i2c_smbus_write_byte_data(client, reg + 1, value & 0xFF); ++ if (rc < 0) { ++ dev_warn(&client->dev, ++ "i2c write failed: 0x%02x: 0x%02x, errno %d\n", ++ reg + 1, value & 0xFF, -rc); ++ return rc; ++ } ++ ++ return rc; ++} ++ ++/* Probe for temperature sensors. Assumes lock is held */ ++static int cy8c3xx_read_temperatures(struct i2c_client *client, ++ struct cy8c3xx_data *data) ++{ ++ int i; ++ ++ /* Only count fans if we have to */ ++ if (data->num_temp_sensors >= 0) ++ return 0; ++ ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) { ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_TEMP_REG(i)); ++ if (data->temp[i]) ++ data->num_temp_sensors = i + 1; ++ } ++ data->temperatures_probed = 1; ++ return 0; ++} ++ ++static int cy8c3xx_update_thread(void *p) ++{ ++ struct i2c_client *client = p; ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ ++ while (!kthread_should_stop()) { ++ mutex_lock(&data->lock); ++ cy8c3xx_read_temperatures(client, data); ++ mutex_unlock(&data->lock); ++ if (kthread_should_stop()) ++ break; ++ msleep_interruptible(data->auto_update_interval); ++ } ++ ++ complete_all(&data->auto_update_stop); ++ return 0; ++} ++ ++static struct cy8c3xx_data *cy8c3xx_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ unsigned long local_jiffies = jiffies; ++ int i; ++ int need_sensors = 1; ++ int need_limits = 1; ++ ++ /* ++ * Figure out if we need to update the shadow registers. ++ * Lockless means that we may occasionally report out of ++ * date data. ++ */ ++ if (time_before(local_jiffies, data->sensors_last_updated + ++ SENSOR_REFRESH_INTERVAL) && ++ data->sensors_valid) ++ need_sensors = 0; ++ ++ if (time_before(local_jiffies, data->limits_last_updated + ++ LIMIT_REFRESH_INTERVAL) && ++ data->limits_valid) ++ need_limits = 0; ++ ++ if (!need_sensors && !need_limits) ++ return data; ++ ++ mutex_lock(&data->lock); ++ if (!need_sensors) ++ goto no_sensor_update; ++ ++ if (!data->temperatures_probed) ++ cy8c3xx_read_temperatures(client, data); ++ else ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_TEMP_REG(i)); ++ ++ for (i = 0; i < CY8C3XX_FAN_COUNT; i++) { ++ data->fan[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN(i)); ++ } ++ ++ for (i = 0; i < CY8C3XX_PWM_COUNT; i++) { ++ data->pwm[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_REG_PWM(i)); ++ } ++ ++ data->sensors_last_updated = local_jiffies; ++ data->sensors_valid = 1; ++ ++no_sensor_update: ++ if (!need_limits) ++ goto out; ++ ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) { ++ data->temp_max[i] = i2c_smbus_read_byte_data(client, ++ CY8C3XX_TEMP_MAX_REG(i)); ++ } ++ ++ for (i = 0; i < CY8C3XX_FAN_COUNT; i++) { ++ data->fan_max[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN_MAX(i)); ++ data->fan_tgt[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN_TARGET(i)); ++ } ++ ++ for (i = 0; i < CY8C3XX_FAN_PROFILE_MAX; i++) { ++ data->fan_profile[i] = cy8c3xx_read_word_data(client, ++ CY8C3XX_REG_FAN_PROFILE(i)); ++ } ++ ++ data->limits_last_updated = local_jiffies; ++ data->limits_valid = 1; ++ ++out: ++ mutex_unlock(&data->lock); ++ return data; ++} ++ ++static ssize_t show_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", data->auto_update_interval); ++} ++ ++static ssize_t set_auto_update_interval(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 60000); ++ ++ mutex_lock(&data->lock); ++ data->auto_update_interval = temp; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", data->num_temp_sensors); ++} ++ ++static ssize_t set_num_temp_sensors(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, -1, 10); ++ ++ mutex_lock(&data->lock); ++ data->num_temp_sensors = temp; ++ if (temp < 0) ++ data->temperatures_probed = 0; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]); ++} ++ ++static ssize_t set_temp_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = DIV_ROUND_CLOSEST(temp, 1000); ++ temp = SENSORS_LIMIT(temp, -128, 127); ++ ++ mutex_lock(&data->lock); ++ data->temp_max[attr->index] = temp; ++ i2c_smbus_write_byte_data(client, CY8C3XX_TEMP_MAX_REG(attr->index), ++ temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); ++} ++ ++static ssize_t show_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_max[attr->index])) ++ return sprintf(buf, "%d\n", ++ data->fan_max[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_max(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_max[attr->index] = rpm; ++ cy8c3xx_write_word_data(client, CY8C3XX_REG_FAN_MAX(attr->index), rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * fan_min is a pure software concept, not implemented by hardware. ++ * It is used to compute the alarm status. ++ */ ++static ssize_t show_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->fan_min[attr->index]); ++} ++ ++static ssize_t set_fan_min(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_min[attr->index] = rpm; ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan_tgt[attr->index])) ++ return sprintf(buf, "%d\n", ++ data->fan_tgt[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_fan_target(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long rpm; ++ ++ if (strict_strtol(buf, 10, &rpm) || !rpm) ++ return -EINVAL; ++ ++ rpm = SENSORS_LIMIT(rpm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_tgt[attr->index] = rpm; ++ cy8c3xx_write_word_data(client, CY8C3XX_REG_FAN_TARGET(attr->index), rpm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++/* ++ * Show Fan Profile Settings ++ */ ++static ssize_t show_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ return sprintf(buf, "%u\n", ++ data->fan_profile[attr->index]); ++} ++ ++/* ++ * Set Fan Profile Settings ++ */ ++static ssize_t set_fan_profile(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long parm; ++ ++ if (strict_strtoul(buf, 10, &parm)) ++ return -EINVAL; ++ ++ parm = SENSORS_LIMIT(parm, 1, 65534); ++ ++ mutex_lock(&data->lock); ++ data->fan_profile[attr->index] = parm; ++ cy8c3xx_write_word_data(client, CY8C3XX_REG_FAN_PROFILE(attr->index), parm); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (FAN_DATA_VALID(data->fan[attr->index])) ++ return sprintf(buf, "%d\n", data->fan[attr->index]); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ return sprintf(buf, "%d\n", data->pwm[attr->index]); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ temp = SENSORS_LIMIT(temp, 0, 255); ++ ++ mutex_lock(&data->lock); ++ data->pwm[attr->index] = temp; ++ i2c_smbus_write_byte_data(client, CY8C3XX_REG_PWM(attr->index), temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_fan_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3XX_FAN_COUNT; i++) ++ if ((data->fan[i] < data->fan_min[i]) || ++ (data->fan[i] >= data->fan_max[i])) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_temp_alarm_mask(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ int i; ++ u32 alarm_mask = 0; ++ ++ for (i = 0; i < CY8C3XX_TEMP_COUNT; i++) ++ if (data->temp[i] >= data->temp_max[i]) ++ alarm_mask |= 0x1 << i; ++ ++ return sprintf(buf, "%x\n", alarm_mask); ++} ++ ++static ssize_t show_fan_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if ((data->fan[attr->index] < data->fan_min[attr->index]) || ++ (data->fan[attr->index] >= data->fan_max[attr->index])) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_temp_alarm(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ if (data->temp[attr->index] >= data->temp_max[attr->index]) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t set_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ long temp; ++ ++ if (strict_strtol(buf, 10, &temp)) ++ return -EINVAL; ++ ++ if (!(temp > 0 && temp < 3)) ++ return -EINVAL; ++ ++ mutex_lock(&data->lock); ++ data->pwm_automatic = temp; ++ i2c_smbus_write_byte_data(client, CY8C3XX_REG_PWM_CFG_BASE_ADDR, temp); ++ mutex_unlock(&data->lock); ++ ++ return count; ++} ++ ++static ssize_t show_pwm_auto(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct cy8c3xx_data *data = cy8c3xx_update_device(dev); ++ ++ return sprintf(buf, "%d\n", data->pwm_automatic); ++} ++ ++#define CY8C3XX_REG_MIN 0x00 ++#define CY8C3XX_REG_MAX 0xe0 ++ ++static ssize_t show_debug(struct device *dev, ++ struct device_attribute *devattr, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ int len = 0, i, j; ++ u8 val; ++ for (i = 0; i < (CY8C3XX_REG_MAX - CY8C3XX_REG_MIN) / 16; i++) { ++ len += sprintf(buf+len, "0x%02x: ", CY8C3XX_REG_MIN + (i * 16)); ++ for (j = 0; j < 16; j++) { ++ val = i2c_smbus_read_byte_data(client, CY8C3XX_REG_MIN + (i * 16) + j); ++ len += sprintf(buf+len, "%02x ", val); ++ } ++ len += sprintf(buf+len, "\n"); ++ } ++ return len; ++} ++ ++static DEVICE_ATTR(fan_alarm_mask, S_IRUGO, show_fan_alarm_mask, NULL); ++static DEVICE_ATTR(temp_alarm_mask, S_IRUGO, show_temp_alarm_mask, NULL); ++static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, ++ set_num_temp_sensors); ++static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO, ++ show_auto_update_interval, set_auto_update_interval); ++ ++static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 0); ++static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 1); ++static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 2); ++static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 3); ++static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_temp_max, ++ set_temp_max, 4); ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); ++ ++static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4); ++ ++static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 0); ++static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 1); ++static SENSOR_DEVICE_ATTR(fan3_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 2); ++static SENSOR_DEVICE_ATTR(fan4_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 3); ++static SENSOR_DEVICE_ATTR(fan5_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 4); ++static SENSOR_DEVICE_ATTR(fan6_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 5); ++static SENSOR_DEVICE_ATTR(fan7_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 6); ++static SENSOR_DEVICE_ATTR(fan8_max, S_IWUSR | S_IRUGO, show_fan_max, ++ set_fan_max, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 0); ++static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 1); ++static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 2); ++static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 3); ++static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 4); ++static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 5); ++static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 6); ++static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, ++ set_fan_min, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 3); ++static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 4); ++static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 5); ++static SENSOR_DEVICE_ATTR(fan7_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 6); ++static SENSOR_DEVICE_ATTR(fan8_target, S_IWUSR | S_IRUGO, show_fan_target, ++ set_fan_target, 7); ++ ++#define FAN_PROFILE_ATTR(_name, _index) \ ++ SENSOR_DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ ++ show_fan_profile, set_fan_profile, _index) ++ ++static FAN_PROFILE_ATTR(fan_low_duty, CY8C3XX_FAN_PROFILE_LOW_DUTY); ++static FAN_PROFILE_ATTR(fan_low_rpm, CY8C3XX_FAN_PROFILE_LOW_RPM); ++static FAN_PROFILE_ATTR(fan_high_duty, CY8C3XX_FAN_PROFILE_HIGH_DUTY); ++static FAN_PROFILE_ATTR(fan_high_rpm, CY8C3XX_FAN_PROFILE_HIGH_RPM); ++static FAN_PROFILE_ATTR(fan_speed_0_duty, CY8C3XX_FAN_PROFILE_SPEED_0_DUTY); ++static FAN_PROFILE_ATTR(fan_speed_100_duty,CY8C3XX_FAN_PROFILE_SPEED_100_DUTY); ++ ++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); ++static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); ++static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); ++static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); ++static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); ++static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 5); ++static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 6); ++static SENSOR_DEVICE_ATTR(pwm8, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 7); ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm7_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++static SENSOR_DEVICE_ATTR(pwm8_enable, S_IWUSR | S_IRUGO, show_pwm_auto, ++ set_pwm_auto, 0); ++ ++static SENSOR_DEVICE_ATTR(debug, S_IRUGO, show_debug, NULL, 0); ++ ++static struct attribute *cy8c3xx_attr[] = ++{ ++ &dev_attr_fan_alarm_mask.attr, ++ &dev_attr_temp_alarm_mask.attr, ++ &dev_attr_num_temp_sensors.attr, ++ &dev_attr_auto_update_interval.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp4_max.dev_attr.attr, ++ &sensor_dev_attr_temp5_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan1_max.dev_attr.attr, ++ &sensor_dev_attr_fan2_max.dev_attr.attr, ++ &sensor_dev_attr_fan3_max.dev_attr.attr, ++ &sensor_dev_attr_fan4_max.dev_attr.attr, ++ &sensor_dev_attr_fan5_max.dev_attr.attr, ++ &sensor_dev_attr_fan6_max.dev_attr.attr, ++ &sensor_dev_attr_fan7_max.dev_attr.attr, ++ &sensor_dev_attr_fan8_max.dev_attr.attr, ++ &sensor_dev_attr_fan1_min.dev_attr.attr, ++ &sensor_dev_attr_fan2_min.dev_attr.attr, ++ &sensor_dev_attr_fan3_min.dev_attr.attr, ++ &sensor_dev_attr_fan4_min.dev_attr.attr, ++ &sensor_dev_attr_fan5_min.dev_attr.attr, ++ &sensor_dev_attr_fan6_min.dev_attr.attr, ++ &sensor_dev_attr_fan7_min.dev_attr.attr, ++ &sensor_dev_attr_fan8_min.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan5_target.dev_attr.attr, ++ &sensor_dev_attr_fan6_target.dev_attr.attr, ++ &sensor_dev_attr_fan7_target.dev_attr.attr, ++ &sensor_dev_attr_fan8_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan5_input.dev_attr.attr, ++ &sensor_dev_attr_fan6_input.dev_attr.attr, ++ &sensor_dev_attr_fan7_input.dev_attr.attr, ++ &sensor_dev_attr_fan8_input.dev_attr.attr, ++ &sensor_dev_attr_fan1_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan2_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan3_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan4_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan5_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan6_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan7_alarm.dev_attr.attr, ++ &sensor_dev_attr_fan8_alarm.dev_attr.attr, ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ &sensor_dev_attr_pwm5.dev_attr.attr, ++ &sensor_dev_attr_pwm6.dev_attr.attr, ++ &sensor_dev_attr_pwm7.dev_attr.attr, ++ &sensor_dev_attr_pwm8.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm5_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm6_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm7_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm8_enable.dev_attr.attr, ++ &sensor_dev_attr_fan_low_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_low_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_high_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_high_rpm.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_0_duty.dev_attr.attr, ++ &sensor_dev_attr_fan_speed_100_duty.dev_attr.attr, ++ &sensor_dev_attr_debug.dev_attr.attr, ++ NULL ++}; ++ ++/* Return 0 if detection is successful, -ENODEV otherwise */ ++static int cy8c3xx_detect(struct i2c_client *client, ++ struct i2c_board_info *info) ++{ ++ struct i2c_adapter *adapter = client->adapter; ++ int vendor, device, revision; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -ENODEV; ++ ++ vendor = i2c_smbus_read_byte_data(client, CY8C3XX_REG_COMPANY_ID); ++ printk(KERN_INFO "vendor = %u\n", vendor); ++ if (vendor != CY8C3XX_COMPANY_ID) ++ return -ENODEV; ++ ++ device = i2c_smbus_read_byte_data(client, CY8C3XX_REG_DEV_ID); ++ printk(KERN_INFO "device = %u\n", device); ++ if (device != CY8C3XX_DEV_ID) ++ return -ENODEV; ++ ++ revision = i2c_smbus_read_byte_data(client, CY8C3XX_REG_FW_REV_MAJ); ++ printk(KERN_INFO "rev = %u\n", revision); ++ if (revision != CY8C3XX_FW_REV_MAJ) ++ return -ENODEV; ++ ++ strlcpy(info->type, "cy8c3xx", I2C_NAME_SIZE); ++ ++ printk(KERN_INFO "cy8c3xx detected\n"); ++ return 0; ++} ++ ++static int cy8c3xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct cy8c3xx_data *data; ++ int err; ++ ++ data = kzalloc(sizeof(struct cy8c3xx_data), GFP_KERNEL); ++ if (!data) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ data->num_temp_sensors = -1; ++ data->auto_update_interval = AUTO_UPDATE_INTERVAL; ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->lock); ++ ++ dev_info(&client->dev, "%s chip found\n", client->name); ++ ++ /* Register sysfs hooks */ ++ data->attrs.attrs = cy8c3xx_attr; ++ if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) ++ goto exit_free; ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ init_completion(&data->auto_update_stop); ++ data->auto_update = kthread_run(cy8c3xx_update_thread, client, ++ dev_name(data->hwmon_dev)); ++ if (IS_ERR(data->auto_update)) { ++ err = PTR_ERR(data->auto_update); ++ goto exit_unregister; ++ } ++ ++ return 0; ++ ++exit_unregister: ++ hwmon_device_unregister(data->hwmon_dev); ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int cy8c3xx_remove(struct i2c_client *client) ++{ ++ struct cy8c3xx_data *data = i2c_get_clientdata(client); ++ ++ kthread_stop(data->auto_update); ++ wait_for_completion(&data->auto_update_stop); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &data->attrs); ++ kfree(data); ++ return 0; ++} ++ ++static int __init cy8c3xx_init(void) ++{ ++ return i2c_add_driver(&cy8c3xx_driver); ++} ++ ++static void __exit cy8c3xx_exit(void) ++{ ++ i2c_del_driver(&cy8c3xx_driver); ++} ++ ++MODULE_AUTHOR("Shrijeet Mukherjee "); ++MODULE_DESCRIPTION("CY8C3XX driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(cy8c3xx_init); ++module_exit(cy8c3xx_exit); +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +new file mode 100644 +index 0000000..62f88e0 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch new file mode 100644 index 00000000..061d7fe7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_emc2305.c.patch @@ -0,0 +1,880 @@ +--- /dev/null ++++ b/drivers/hwmon/emc2305.c +@@ -0,0 +1,875 @@ ++/* ++ * emc2305.c - hwmon driver for SMSC EMC2305 fan controller ++ * (C) Copyright 2013 ++ * Reinhard Pfau, Guntermann & Drunck GmbH ++ * ++ * Based on emc2103 driver by SMSC. ++ * ++ * Datasheet available at: ++ * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf ++ * ++ * Also supports the EMC2303 fan controller which has the same functionality ++ * and register layout as EMC2305, but supports only up to 3 fans instead of 5. ++ * ++ * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++/* ++ * TODO / IDEAS: ++ * - expose more of the configuration and features ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Addresses scanned. ++ * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. ++ * ++ * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 ++ * chips. ++ * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). ++ * The EMC2301 supports only 0x2f. ++ */ ++static const unsigned short i2c_adresses[] = { ++ 0x2E, ++ 0x2F, ++ 0x2C, ++ 0x2D, ++ 0x4C, ++ 0x4D, ++ I2C_CLIENT_END ++}; ++ ++/* ++ * global registers ++ */ ++enum { ++ REG_CONFIGURATION = 0x20, ++ REG_FAN_STATUS = 0x24, ++ REG_FAN_STALL_STATUS = 0x25, ++ REG_FAN_SPIN_STATUS = 0x26, ++ REG_DRIVE_FAIL_STATUS = 0x27, ++ REG_FAN_INTERRUPT_ENABLE = 0x29, ++ REG_PWM_POLARITY_CONFIG = 0x2a, ++ REG_PWM_OUTPUT_CONFIG = 0x2b, ++ REG_PWM_BASE_FREQ_1 = 0x2c, ++ REG_PWM_BASE_FREQ_2 = 0x2d, ++ REG_SOFTWARE_LOCK = 0xef, ++ REG_PRODUCT_FEATURES = 0xfc, ++ REG_PRODUCT_ID = 0xfd, ++ REG_MANUFACTURER_ID = 0xfe, ++ REG_REVISION = 0xff ++}; ++ ++/* ++ * fan specific registers ++ */ ++enum { ++ REG_FAN_SETTING = 0x30, ++ REG_PWM_DIVIDE = 0x31, ++ REG_FAN_CONFIGURATION_1 = 0x32, ++ REG_FAN_CONFIGURATION_2 = 0x33, ++ REG_GAIN = 0x35, ++ REG_FAN_SPIN_UP_CONFIG = 0x36, ++ REG_FAN_MAX_STEP = 0x37, ++ REG_FAN_MINIMUM_DRIVE = 0x38, ++ REG_FAN_VALID_TACH_COUNT = 0x39, ++ REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, ++ REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, ++ REG_TACH_TARGET_LOW = 0x3c, ++ REG_TACH_TARGET_HIGH = 0x3d, ++ REG_TACH_READ_HIGH = 0x3e, ++ REG_TACH_READ_LOW = 0x3f, ++}; ++ ++#define SEL_FAN(fan, reg) (reg + fan * 0x10) ++ ++/* ++ * Factor by equations [2] and [3] from data sheet; valid for fans where the ++ * number of edges equals (poles * 2 + 1). ++ */ ++#define FAN_RPM_FACTOR 3932160 ++ ++ ++struct emc2305_fan_data { ++ bool enabled; ++ bool valid; ++ unsigned long last_updated; ++ bool rpm_control; ++ u8 multiplier; ++ u8 poles; ++ u16 target; ++ u16 tach; ++ u16 rpm_factor; ++ u8 pwm; ++}; ++ ++struct emc2305_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ int fans; ++ struct emc2305_fan_data fan[5]; ++}; ++ ++static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) ++{ ++ int status = i2c_smbus_read_byte_data(client, i2c_reg); ++ if (status < 0) { ++ dev_warn(&client->dev, "reg 0x%02x, err %d\n", ++ i2c_reg, status); ++ } else { ++ *output = status; ++ } ++ return status; ++} ++ ++static void read_fan_from_i2c(struct i2c_client *client, u16 *output, ++ u8 hi_addr, u8 lo_addr) ++{ ++ u8 high_byte, lo_byte; ++ ++ if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) ++ return; ++ ++ if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) ++ return; ++ ++ *output = ((u16)high_byte << 5) | (lo_byte >> 3); ++} ++ ++static void write_fan_target_to_i2c(struct i2c_client *client, int fan, ++ u16 new_target) ++{ ++ const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); ++ const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); ++ u8 high_byte = (new_target & 0x1fe0) >> 5; ++ u8 low_byte = (new_target & 0x001f) << 3; ++ i2c_smbus_write_byte_data(client, lo_reg, low_byte); ++ i2c_smbus_write_byte_data(client, hi_reg, high_byte); ++} ++ ++static void read_fan_config_from_i2c(struct i2c_client *client, int fan) ++ ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ u8 conf1; ++ ++ if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), ++ &conf1) < 0) ++ return; ++ ++ data->fan[fan].rpm_control = (conf1 & 0x80) != 0; ++ data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); ++ data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; ++} ++ ++static void read_fan_setting(struct i2c_client *client, int fan) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ u8 setting; ++ ++ if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), ++ &setting) < 0) ++ return; ++ ++ data->fan[fan].pwm = setting; ++} ++ ++static void read_fan_data(struct i2c_client *client, int fan_idx) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ ++ read_fan_from_i2c(client, &data->fan[fan_idx].target, ++ SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), ++ SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); ++ read_fan_from_i2c(client, &data->fan[fan_idx].tach, ++ SEL_FAN(fan_idx, REG_TACH_READ_HIGH), ++ SEL_FAN(fan_idx, REG_TACH_READ_LOW)); ++} ++ ++static struct emc2305_fan_data * ++emc2305_update_fan(struct i2c_client *client, int fan_idx) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) ++ || !fan_data->valid) { ++ read_fan_config_from_i2c(client, fan_idx); ++ read_fan_data(client, fan_idx); ++ read_fan_setting(client, fan_idx); ++ fan_data->valid = true; ++ fan_data->last_updated = jiffies; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return fan_data; ++} ++ ++static struct emc2305_fan_data * ++emc2305_update_device_fan(struct device *dev, struct device_attribute *da) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ ++ return emc2305_update_fan(client, fan_idx); ++} ++ ++/* ++ * set/ config functions ++ */ ++ ++/* ++ * Note: we also update the fan target here, because its value is ++ * determined in part by the fan clock divider. This follows the principle ++ * of least surprise; the user doesn't expect the fan target to change just ++ * because the divider changed. ++ */ ++static int ++emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); ++ int new_range_bits, old_div = 8 / fan->multiplier; ++ int status = 0; ++ ++ if (new_div == old_div) /* No change */ ++ return 0; ++ ++ switch (new_div) { ++ case 1: ++ new_range_bits = 3; ++ break; ++ case 2: ++ new_range_bits = 2; ++ break; ++ case 4: ++ new_range_bits = 1; ++ break; ++ case 8: ++ new_range_bits = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ mutex_lock(&data->update_lock); ++ ++ status = i2c_smbus_read_byte_data(client, reg_conf1); ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg 0x%02x, err %d\n", ++ reg_conf1, status); ++ status = -EIO; ++ goto exit_unlock; ++ } ++ status &= 0x9F; ++ status |= (new_range_bits << 5); ++ status = i2c_smbus_write_byte_data(client, reg_conf1, status); ++ if (status < 0) { ++ status = -EIO; ++ goto exit_invalidate; ++ } ++ ++ fan->multiplier = 8 / new_div; ++ ++ /* update fan target if high byte is not disabled */ ++ if ((fan->target & 0x1fe0) != 0x1fe0) { ++ u16 new_target = (fan->target * old_div) / new_div; ++ fan->target = min_t(u16, new_target, 0x1fff); ++ write_fan_target_to_i2c(client, fan_idx, fan->target); ++ } ++ ++exit_invalidate: ++ /* invalidate fan data to force re-read from hardware */ ++ fan->valid = false; ++exit_unlock: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++static int ++emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ ++ /* ++ * Datasheet states 16000 as maximum RPM target ++ * (table 2.2 and section 4.3) ++ */ ++ if ((rpm_target < 0) || (rpm_target > 16000)) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (rpm_target == 0) ++ fan->target = 0x1fff; ++ else ++ fan->target = clamp_val( ++ (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, ++ 0, 0x1fff); ++ ++ write_fan_target_to_i2c(client, fan_idx, fan->target); ++ ++ mutex_unlock(&data->update_lock); ++ return 0; ++} ++ ++static int ++emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); ++ int status = 0; ++ u8 conf_reg; ++ ++ mutex_lock(&data->update_lock); ++ switch (enable) { ++ case 0: ++ fan->rpm_control = false; ++ break; ++ case 3: ++ fan->rpm_control = true; ++ break; ++ default: ++ status = -EINVAL; ++ goto exit_unlock; ++ } ++ ++ status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); ++ if (status < 0) { ++ status = -EIO; ++ goto exit_unlock; ++ } ++ ++ if (fan->rpm_control) ++ conf_reg |= 0x80; ++ else ++ conf_reg &= ~0x80; ++ ++ status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); ++ if (status < 0) ++ status = -EIO; ++ ++exit_unlock: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++static int ++emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); ++ const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); ++ int status = 0; ++ ++ /* ++ * Datasheet states 255 as maximum PWM ++ * (section 5.7) ++ */ ++ if ((pwm < 0) || (pwm > 255)) ++ return -EINVAL; ++ ++ fan->pwm = pwm; ++ ++ mutex_lock(&data->update_lock); ++ ++ status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); ++ ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++/* ++ * sysfs callback functions ++ * ++ * Note: ++ * Naming of the funcs is modelled after the naming scheme described in ++ * Documentation/hwmon/sysfs-interface: ++ * ++ * For a sysfs file _ the functions are named like this: ++ * the show function: show__ ++ * the store function: set__ ++ * For read only (RO) attributes of course only the show func is required. ++ * ++ * This convention allows us to define the sysfs attributes by using macros. ++ */ ++ ++static ssize_t ++show_fan_input(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ int rpm = 0; ++ if (fan->tach != 0) ++ rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t ++show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); ++ return sprintf(buf, "%d\n", fault ? 1 : 0); ++} ++ ++static ssize_t ++show_fan_div(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ int fan_div = 8 / fan->multiplier; ++ return sprintf(buf, "%d\n", fan_div); ++} ++ ++static ssize_t ++set_fan_div(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ long new_div; ++ int status; ++ ++ status = kstrtol(buf, 10, &new_div); ++ if (status < 0) ++ return -EINVAL; ++ ++ status = emc2305_set_fan_div(client, fan_idx, new_div); ++ if (status < 0) ++ return status; ++ ++ return count; ++} ++ ++static ssize_t ++show_fan_target(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ int rpm = 0; ++ ++ /* high byte of 0xff indicates disabled so return 0 */ ++ if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) ++ rpm = (FAN_RPM_FACTOR * fan->multiplier) ++ / fan->target; ++ ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ long rpm_target; ++ int status; ++ ++ status = kstrtol(buf, 10, &rpm_target); ++ if (status < 0) ++ return -EINVAL; ++ ++ status = emc2305_set_fan_target(client, fan_idx, rpm_target); ++ if (status < 0) ++ return status; ++ ++ return count; ++} ++ ++static ssize_t ++show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); ++} ++ ++static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ long new_value; ++ int status; ++ ++ status = kstrtol(buf, 10, &new_value); ++ if (status < 0) ++ return -EINVAL; ++ status = emc2305_set_pwm_enable(client, fan_idx, new_value); ++ return count; ++} ++ ++static ssize_t show_pwm(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); ++ return sprintf(buf, "%d\n", fan->pwm); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ int fan_idx = to_sensor_dev_attr(da)->index; ++ unsigned long val; ++ int ret; ++ int status; ++ ++ ret = kstrtoul(buf, 10, &val); ++ if (ret) ++ return ret; ++ if (val > 255) ++ return -EINVAL; ++ ++ status = emc2305_set_pwm(client, fan_idx, val); ++ return count; ++} ++ ++/* define a read only attribute */ ++#define EMC2305_ATTR_RO(_type, _item, _num) \ ++ SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ ++ show_## _type ## _ ## _item, NULL, _num - 1) ++ ++/* define a read/write attribute */ ++#define EMC2305_ATTR_RW(_type, _item, _num) \ ++ SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ ++ show_## _type ##_ ## _item, \ ++ set_## _type ## _ ## _item, _num - 1) ++ ++/* ++ * TODO: Ugly hack, but temporary as this whole logic needs ++ * to be rewritten as per standard HWMON sysfs registration ++ */ ++ ++/* define a read/write attribute */ ++#define EMC2305_ATTR_RW2(_type, _num) \ ++ SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ ++ show_## _type, set_## _type, _num - 1) ++ ++/* defines the attributes for a single fan */ ++#define EMC2305_DEFINE_FAN_ATTRS(_num) \ ++ static const \ ++ struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ ++ EMC2305_ATTR_RO(fan, input, _num), \ ++ EMC2305_ATTR_RO(fan, fault, _num), \ ++ EMC2305_ATTR_RW(fan, div, _num), \ ++ EMC2305_ATTR_RW(fan, target, _num), \ ++ EMC2305_ATTR_RW(pwm, enable, _num), \ ++ EMC2305_ATTR_RW2(pwm, _num) \ ++ } ++ ++#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) ++ ++/* common attributes for EMC2303 and EMC2305 */ ++static const struct sensor_device_attribute emc2305_attr_common[] = { ++}; ++ ++/* fan attributes for the single fans */ ++EMC2305_DEFINE_FAN_ATTRS(1); ++EMC2305_DEFINE_FAN_ATTRS(2); ++EMC2305_DEFINE_FAN_ATTRS(3); ++EMC2305_DEFINE_FAN_ATTRS(4); ++EMC2305_DEFINE_FAN_ATTRS(5); ++EMC2305_DEFINE_FAN_ATTRS(6); ++ ++/* fan attributes */ ++static const struct sensor_device_attribute *emc2305_fan_attrs[] = { ++ emc2305_attr_fan1, ++ emc2305_attr_fan2, ++ emc2305_attr_fan3, ++ emc2305_attr_fan4, ++ emc2305_attr_fan5, ++}; ++ ++/* ++ * driver interface ++ */ ++ ++static int emc2305_remove(struct i2c_client *client) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ int fan_idx, i; ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) ++ device_remove_file( ++ &client->dev, ++ &emc2305_fan_attrs[fan_idx][i].dev_attr); ++ ++ for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) ++ device_remove_file(&client->dev, ++ &emc2305_attr_common[i].dev_attr); ++ ++ kfree(data); ++ return 0; ++} ++ ++ ++#ifdef CONFIG_OF ++/* ++ * device tree support ++ */ ++ ++struct of_fan_attribute { ++ const char *name; ++ int (*set)(struct i2c_client*, int, long); ++}; ++ ++struct of_fan_attribute of_fan_attributes[] = { ++ {"fan-div", emc2305_set_fan_div}, ++ {"fan-target", emc2305_set_fan_target}, ++ {"pwm-enable", emc2305_set_pwm_enable}, ++ {NULL, NULL} ++}; ++ ++static int emc2305_config_of(struct i2c_client *client) ++{ ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ struct device_node *node; ++ unsigned int fan_idx; ++ ++ if (!client->dev.of_node) ++ return -EINVAL; ++ if (!of_get_next_child(client->dev.of_node, NULL)) ++ return 0; ++ ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ data->fan[fan_idx].enabled = false; ++ ++ for_each_child_of_node(client->dev.of_node, node) { ++ const __be32 *property; ++ int len; ++ struct of_fan_attribute *attr; ++ ++ property = of_get_property(node, "reg", &len); ++ if (!property || len != sizeof(int)) { ++ dev_err(&client->dev, "invalid reg on %s\n", ++ node->full_name); ++ continue; ++ } ++ ++ fan_idx = be32_to_cpup(property); ++ if (fan_idx >= data->fans) { ++ dev_err(&client->dev, ++ "invalid fan index %d on %s\n", ++ fan_idx, node->full_name); ++ continue; ++ } ++ ++ data->fan[fan_idx].enabled = true; ++ ++ for (attr = of_fan_attributes; attr->name; ++attr) { ++ int status = 0; ++ long value; ++ property = of_get_property(node, attr->name, &len); ++ if (!property) ++ continue; ++ if (len != sizeof(int)) { ++ dev_err(&client->dev, "invalid %s on %s\n", ++ attr->name, node->full_name); ++ continue; ++ } ++ value = be32_to_cpup(property); ++ status = attr->set(client, fan_idx, value); ++ if (status == -EINVAL) { ++ dev_err(&client->dev, ++ "invalid value for %s on %s\n", ++ attr->name, node->full_name); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++#endif ++ ++static void emc2305_get_config(struct i2c_client *client) ++{ ++ int i; ++ struct emc2305_data *data = i2c_get_clientdata(client); ++ ++ for (i = 0; i < data->fans; ++i) { ++ data->fan[i].enabled = true; ++ emc2305_update_fan(client, i); ++ } ++ ++#ifdef CONFIG_OF ++ emc2305_config_of(client); ++#endif ++ ++} ++ ++static int ++emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ struct emc2305_data *data; ++ int status; ++ int i; ++ int fan_idx; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -EIO; ++ ++ data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); ++ switch (status) { ++ case 0x34: /* EMC2305 */ ++ data->fans = 5; ++ break; ++ case 0x35: /* EMC2303 */ ++ data->fans = 3; ++ break; ++ case 0x36: /* EMC2302 */ ++ data->fans = 2; ++ break; ++ case 0x37: /* EMC2301 */ ++ data->fans = 1; ++ break; ++ default: ++ if (status >= 0) ++ status = -EINVAL; ++ goto exit_free; ++ } ++ ++ emc2305_get_config(client); ++ ++ for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { ++ status = device_create_file(&client->dev, ++ &emc2305_attr_common[i].dev_attr); ++ if (status) ++ goto exit_remove; ++ } ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { ++ if (!data->fan[fan_idx].enabled) ++ continue; ++ status = device_create_file( ++ &client->dev, ++ &emc2305_fan_attrs[fan_idx][i].dev_attr); ++ if (status) ++ goto exit_remove_fans; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove_fans; ++ } ++ ++ dev_info(&client->dev, "%s: sensor '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove_fans: ++ for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) ++ for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) ++ device_remove_file( ++ &client->dev, ++ &emc2305_fan_attrs[fan_idx][i].dev_attr); ++ ++exit_remove: ++ for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) ++ device_remove_file(&client->dev, ++ &emc2305_attr_common[i].dev_attr); ++exit_free: ++ kfree(data); ++ return status; ++} ++ ++static const struct i2c_device_id emc2305_id[] = { ++ { "emc2305", 0 }, ++ { "emc2303", 0 }, ++ { "emc2302", 0 }, ++ { "emc2301", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, emc2305_id); ++ ++/* Return 0 if detection is successful, -ENODEV otherwise */ ++static int ++emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) ++{ ++ struct i2c_adapter *adapter = new_client->adapter; ++ int manufacturer, product; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -ENODEV; ++ ++ manufacturer = ++ i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); ++ if (manufacturer != 0x5D) ++ return -ENODEV; ++ ++ product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); ++ ++ switch (product) { ++ case 0x34: ++ strlcpy(info->type, "emc2305", I2C_NAME_SIZE); ++ break; ++ case 0x35: ++ strlcpy(info->type, "emc2303", I2C_NAME_SIZE); ++ break; ++ case 0x36: ++ strlcpy(info->type, "emc2302", I2C_NAME_SIZE); ++ break; ++ case 0x37: ++ strlcpy(info->type, "emc2301", I2C_NAME_SIZE); ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static struct i2c_driver emc2305_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "emc2305", ++ }, ++ .probe = emc2305_probe, ++ .remove = emc2305_remove, ++ .id_table = emc2305_id, ++ .detect = emc2305_detect, ++ .address_list = i2c_adresses, ++}; ++ ++module_i2c_driver(emc2305_driver); ++ ++MODULE_AUTHOR("Reinhard Pfau "); ++MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c +index 1ba7af2..3d7ee59 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch new file mode 100644 index 00000000..1febfc34 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_it87.c.patch @@ -0,0 +1,189 @@ +--- a/drivers/hwmon/it87.c ++++ b/drivers/hwmon/it87.c +@@ -17,6 +17,7 @@ + * IT8720F Super I/O chip w/LPC interface + * IT8721F Super I/O chip w/LPC interface + * IT8726F Super I/O chip w/LPC interface ++ * IT8728F Super I/O chip w/LPC interface + * IT8758E Super I/O chip w/LPC interface + * Sis950 A clone of the IT8705F + * +@@ -58,7 +59,7 @@ + + #define DRVNAME "it87" + +-enum chips { it87, it8712, it8716, it8718, it8720, it8721 }; ++enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 }; + + static unsigned short force_id; + module_param(force_id, ushort, 0); +@@ -135,6 +136,7 @@ static inline void superio_exit(void) + #define IT8720F_DEVID 0x8720 + #define IT8721F_DEVID 0x8721 + #define IT8726F_DEVID 0x8726 ++#define IT8728F_DEVID 0x8728 + #define IT87_ACT_REG 0x30 + #define IT87_BASE_REG 0x60 + +@@ -274,11 +276,31 @@ struct it87_data { + s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ + }; + ++static inline int has_12mv_adc(const struct it87_data *data) ++{ ++ /* ++ * IT8721F and later have a 12 mV ADC, also with internal scaling ++ * on selected inputs. ++ */ ++ return data->type == it8721 ++ || data->type == it8728; ++} ++ ++static inline int has_newer_autopwm(const struct it87_data *data) ++{ ++ /* ++ * IT8721F and later have separate registers for the temperature ++ * mapping and the manual duty cycle. ++ */ ++ return data->type == it8721 ++ || data->type == it8728; ++} ++ + static u8 in_to_reg(const struct it87_data *data, int nr, long val) + { + long lsb; + +- if (data->type == it8721) { ++ if (has_12mv_adc(data)) { + if (data->in_scaled & (1 << nr)) + lsb = 24; + else +@@ -292,7 +314,7 @@ static u8 in_to_reg(const struct it87_data *data, int nr, long val) + + static int in_from_reg(const struct it87_data *data, int nr, int val) + { +- if (data->type == it8721) { ++ if (has_12mv_adc(data)) { + if (data->in_scaled & (1 << nr)) + return val * 24; + else +@@ -329,7 +351,7 @@ static inline u16 FAN16_TO_REG(long rpm) + + static u8 pwm_to_reg(const struct it87_data *data, long val) + { +- if (data->type == it8721) ++ if (has_newer_autopwm(data)) + return val; + else + return val >> 1; +@@ -337,7 +359,7 @@ static u8 pwm_to_reg(const struct it87_data *data, long val) + + static int pwm_from_reg(const struct it87_data *data, u8 reg) + { +- if (data->type == it8721) ++ if (has_newer_autopwm(data)) + return reg; + else + return (reg & 0x7f) << 1; +@@ -374,7 +396,8 @@ static inline int has_16bit_fans(const struct it87_data *data) + || data->type == it8716 + || data->type == it8718 + || data->type == it8720 +- || data->type == it8721; ++ || data->type == it8721 ++ || data->type == it8728; + } + + static inline int has_old_autopwm(const struct it87_data *data) +@@ -842,7 +865,7 @@ static ssize_t set_pwm_enable(struct device *dev, + data->fan_main_ctrl); + } else { + if (val == 1) /* Manual mode */ +- data->pwm_ctrl[nr] = data->type == it8721 ? ++ data->pwm_ctrl[nr] = has_newer_autopwm(data) ? + data->pwm_temp_map[nr] : + data->pwm_duty[nr]; + else /* Automatic mode */ +@@ -870,7 +893,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + return -EINVAL; + + mutex_lock(&data->update_lock); +- if (data->type == it8721) { ++ if (has_newer_autopwm(data)) { + /* If we are in automatic mode, the PWM duty cycle register + * is read-only so we can't write the value */ + if (data->pwm_ctrl[nr] & 0x80) { +@@ -1311,8 +1334,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr, + struct it87_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + +- return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr] +- : labels[nr]); ++ return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr] ++ : labels[nr]); + } + static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); + static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); +@@ -1605,6 +1628,9 @@ static int __init it87_find(unsigned short *address, + case IT8721F_DEVID: + sio_data->type = it8721; + break; ++ case IT8728F_DEVID: ++ sio_data->type = it8728; ++ break; + case 0xffff: /* No device at all */ + goto exit; + default: +@@ -1646,8 +1672,11 @@ static int __init it87_find(unsigned short *address, + superio_select(GPIO); + + reg = superio_inb(IT87_SIO_GPIO3_REG); +- if (sio_data->type == it8721) { +- /* The IT8721F/IT8758E doesn't have VID pins at all */ ++ if (sio_data->type == it8721 || sio_data->type == it8728) { ++ /* ++ * The IT8721F/IT8758E doesn't have VID pins at all, ++ * not sure about the IT8728F. ++ */ + sio_data->skip_vid = 1; + } else { + /* We need at least 4 VID pins */ +@@ -1692,7 +1721,8 @@ static int __init it87_find(unsigned short *address, + } + if (reg & (1 << 0)) + sio_data->internal |= (1 << 0); +- if ((reg & (1 << 1)) || sio_data->type == it8721) ++ if ((reg & (1 << 1)) || sio_data->type == it8721 || ++ sio_data->type == it8728) + sio_data->internal |= (1 << 1); + + sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; +@@ -1770,6 +1800,7 @@ static int __devinit it87_probe(struct platform_device *pdev) + "it8718", + "it8720", + "it8721", ++ "it8728", + }; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); +@@ -1807,7 +1838,7 @@ static int __devinit it87_probe(struct platform_device *pdev) + enable_pwm_interface = it87_check_pwm(dev); + + /* Starting with IT8721F, we handle scaling of internal voltages */ +- if (data->type == it8721) { ++ if (has_12mv_adc(data)) { + if (sio_data->internal & (1 << 0)) + data->in_scaled |= (1 << 3); /* in3 is AVCC */ + if (sio_data->internal & (1 << 1)) +@@ -2093,7 +2124,7 @@ static void __devinit it87_init_device(struct platform_device *pdev) + static void it87_update_pwm_ctrl(struct it87_data *data, int nr) + { + data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); +- if (data->type == it8721) { ++ if (has_newer_autopwm(data)) { + data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; + data->pwm_duty[nr] = it87_read_value(data, + IT87_REG_PWM_DUTY(nr)); +diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c +new file mode 100644 +index 0000000..525d12f diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch new file mode 100644 index 00000000..d615fec6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6620.c.patch @@ -0,0 +1,666 @@ +--- /dev/null ++++ b/drivers/hwmon/max6620.c +@@ -0,0 +1,661 @@ ++/* ++ * max6620.c - Linux Kernel module for hardware monitoring. ++ * ++ * (C) 2012 by L. Grunenberg ++ * ++ * based on code written by : ++ * 2007 by Hans J. Koch ++ * John Morris ++ * Copyright (c) 2003 Spirent Communications ++ * and Claus Gindhart ++ * ++ * This module has only been tested with the MAX6620 chip. ++ * ++ * The datasheet was last seen at: ++ * ++ * http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Insmod parameters ++ */ ++ ++ ++/* clock: The clock frequency of the chip the driver should assume */ ++static int clock = 8192; ++static u32 sr = 2; ++static u32 np = 2; ++ ++module_param(clock, int, S_IRUGO); ++ ++static const unsigned short normal_i2c[] = {0x0a, 0x1a, 0x2a, I2C_CLIENT_END}; ++ ++/* ++ * MAX 6620 registers ++ */ ++ ++#define MAX6620_REG_CONFIG 0x00 ++#define MAX6620_REG_FAULT 0x01 ++#define MAX6620_REG_CONF_FAN0 0x02 ++#define MAX6620_REG_CONF_FAN1 0x03 ++#define MAX6620_REG_CONF_FAN2 0x04 ++#define MAX6620_REG_CONF_FAN3 0x05 ++#define MAX6620_REG_DYN_FAN0 0x06 ++#define MAX6620_REG_DYN_FAN1 0x07 ++#define MAX6620_REG_DYN_FAN2 0x08 ++#define MAX6620_REG_DYN_FAN3 0x09 ++#define MAX6620_REG_TACH0 0x10 ++#define MAX6620_REG_TACH1 0x12 ++#define MAX6620_REG_TACH2 0x14 ++#define MAX6620_REG_TACH3 0x16 ++#define MAX6620_REG_VOLT0 0x18 ++#define MAX6620_REG_VOLT1 0x1A ++#define MAX6620_REG_VOLT2 0x1C ++#define MAX6620_REG_VOLT3 0x1E ++#define MAX6620_REG_TAR0 0x20 ++#define MAX6620_REG_TAR1 0x22 ++#define MAX6620_REG_TAR2 0x24 ++#define MAX6620_REG_TAR3 0x26 ++#define MAX6620_REG_DAC0 0x28 ++#define MAX6620_REG_DAC1 0x2A ++#define MAX6620_REG_DAC2 0x2C ++#define MAX6620_REG_DAC3 0x2E ++ ++/* ++ * Config register bits ++ */ ++ ++#define MAX6620_CFG_RUN 0x80 ++#define MAX6620_CFG_POR 0x40 ++#define MAX6620_CFG_TIMEOUT 0x20 ++#define MAX6620_CFG_FULLFAN 0x10 ++#define MAX6620_CFG_OSC 0x08 ++#define MAX6620_CFG_WD_MASK 0x06 ++#define MAX6620_CFG_WD_2 0x02 ++#define MAX6620_CFG_WD_6 0x04 ++#define MAX6620_CFG_WD10 0x06 ++#define MAX6620_CFG_WD 0x01 ++ ++ ++/* ++ * Failure status register bits ++ */ ++ ++#define MAX6620_FAIL_TACH0 0x10 ++#define MAX6620_FAIL_TACH1 0x20 ++#define MAX6620_FAIL_TACH2 0x40 ++#define MAX6620_FAIL_TACH3 0x80 ++#define MAX6620_FAIL_MASK0 0x01 ++#define MAX6620_FAIL_MASK1 0x02 ++#define MAX6620_FAIL_MASK2 0x04 ++#define MAX6620_FAIL_MASK3 0x08 ++ ++ ++/* Minimum and maximum values of the FAN-RPM */ ++#define FAN_RPM_MIN 240 ++#define FAN_RPM_MAX 30000 ++ ++#define DIV_FROM_REG(reg) (1 << ((reg & 0xE0) >> 5)) ++ ++static int max6620_probe(struct i2c_client *client, const struct i2c_device_id *id); ++static int max6620_init_client(struct i2c_client *client); ++static int max6620_remove(struct i2c_client *client); ++static struct max6620_data *max6620_update_device(struct device *dev); ++ ++static const u8 config_reg[] = { ++ MAX6620_REG_CONF_FAN0, ++ MAX6620_REG_CONF_FAN1, ++ MAX6620_REG_CONF_FAN2, ++ MAX6620_REG_CONF_FAN3, ++}; ++ ++static const u8 dyn_reg[] = { ++ MAX6620_REG_DYN_FAN0, ++ MAX6620_REG_DYN_FAN1, ++ MAX6620_REG_DYN_FAN2, ++ MAX6620_REG_DYN_FAN3, ++}; ++ ++static const u8 tach_reg[] = { ++ MAX6620_REG_TACH0, ++ MAX6620_REG_TACH1, ++ MAX6620_REG_TACH2, ++ MAX6620_REG_TACH3, ++}; ++ ++static const u8 volt_reg[] = { ++ MAX6620_REG_VOLT0, ++ MAX6620_REG_VOLT1, ++ MAX6620_REG_VOLT2, ++ MAX6620_REG_VOLT3, ++}; ++ ++static const u8 target_reg[] = { ++ MAX6620_REG_TAR0, ++ MAX6620_REG_TAR1, ++ MAX6620_REG_TAR2, ++ MAX6620_REG_TAR3, ++}; ++ ++static const u8 dac_reg[] = { ++ MAX6620_REG_DAC0, ++ MAX6620_REG_DAC1, ++ MAX6620_REG_DAC2, ++ MAX6620_REG_DAC3, ++}; ++ ++/* ++ * Driver data (common to all clients) ++ */ ++ ++static const struct i2c_device_id max6620_id[] = { ++ { "max6620", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max6620_id); ++ ++static struct i2c_driver max6620_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "max6620", ++ }, ++ .probe = max6620_probe, ++ .remove = __devexit_p(max6620_remove), ++ .id_table = max6620_id, ++ .address_list = normal_i2c, ++}; ++ ++/* ++ * Client data (each client gets its own) ++ */ ++ ++struct max6620_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ int nr_fans; ++ char valid; /* zero until following fields are valid */ ++ unsigned long last_updated; /* in jiffies */ ++ ++ /* register values */ ++ u8 speed[4]; ++ u8 config; ++ u8 fancfg[4]; ++ u8 fandyn[4]; ++ u8 tach[4]; ++ u8 volt[4]; ++ u8 target[4]; ++ u8 dac[4]; ++ u8 fault; ++}; ++ ++static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ u32 rpm = 0; ++ u32 tach = 0; ++ u32 tach1 = 0; ++ u32 tach2 = 0; ++ ++ tach1 = i2c_smbus_read_byte_data(client, tach_reg[attr->index]); ++ tach1 = (tach1 << 3) & 0x7f8; ++ tach2 = i2c_smbus_read_byte_data(client, tach_reg[attr->index] + 1); ++ tach2 = (tach2 >> 5) & 0x7; ++ tach = tach1 | tach2; ++ if (tach == 0) { ++ rpm = 0; ++ } else { ++ rpm = (60 * sr * clock)/(tach * np); ++ } ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t get_target(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct i2c_client *client = to_i2c_client(dev); ++ u32 rpm; ++ u32 target; ++ u32 target1; ++ u32 target2; ++ ++ target1 = i2c_smbus_read_byte_data(client, target_reg[attr->index]); ++ target1 = (target1 << 3) & 0x7f8; ++ target2 = i2c_smbus_read_byte_data(client, target_reg[attr->index] + 1); ++ target2 = (target2 >> 5) & 0x7; ++ target = target1 | target2; ++ if (target == 0) { ++ rpm = 0; ++ } else { ++ rpm = (60 * sr * clock)/(target * np); ++ } ++ return sprintf(buf, "%d\n", rpm); ++} ++ ++static ssize_t set_target(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ u32 rpm; ++ int err; ++ u32 target; ++ u32 target1; ++ u32 target2; ++ ++ err = kstrtouint(buf, 10, &rpm); ++ if (err) ++ return err; ++ ++ rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); ++ ++ mutex_lock(&data->update_lock); ++ ++ target = (60 * sr * 8192)/(rpm * np); ++ target1 = (target >> 3) & 0xff; ++ target2 = (target << 5) & 0xe0; ++ i2c_smbus_write_byte_data(client, target_reg[attr->index], target1); ++ i2c_smbus_write_byte_data(client, target_reg[attr->index] + 1, target2); ++ ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++/* ++ * Get/set the fan speed in open loop mode using pwm1 sysfs file. ++ * Speed is given as a relative value from 0 to 255, where 255 is maximum ++ * speed. Note that this is done by writing directly to the chip's DAC, ++ * it won't change the closed loop speed set by fan1_target. ++ * Also note that due to rounding errors it is possible that you don't read ++ * back exactly the value you have set. ++ */ ++ ++static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ int pwm; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct max6620_data *data = max6620_update_device(dev); ++ ++ /* ++ * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. ++ * Lower DAC values mean higher speeds. ++ */ ++ pwm = ((int)data->volt[attr->index]); ++ ++ if (pwm < 0) ++ pwm = 0; ++ ++ return sprintf(buf, "%d\n", pwm); ++} ++ ++static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ unsigned long pwm; ++ int err; ++ ++ err = kstrtoul(buf, 10, &pwm); ++ if (err) ++ return err; ++ ++ pwm = SENSORS_LIMIT(pwm, 0, 255); ++ ++ mutex_lock(&data->update_lock); ++ ++ data->dac[attr->index] = pwm; ++ ++ ++ i2c_smbus_write_byte_data(client, dac_reg[attr->index], data->dac[attr->index]); ++ i2c_smbus_write_byte_data(client, dac_reg[attr->index]+1, 0x00); ++ ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++/* ++ * Get/Set controller mode: ++ * Possible values: ++ * 0 = Fan always on ++ * 1 = Open loop, Voltage is set according to speed, not regulated. ++ * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer ++ */ ++ ++static ssize_t get_enable(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct max6620_data *data = max6620_update_device(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ int mode = (data->fancfg[attr->index] & 0x80 ) >> 7; ++ int sysfs_modes[2] = {1, 2}; ++ ++ return sprintf(buf, "%d\n", sysfs_modes[mode]); ++} ++ ++static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ int max6620_modes[3] = {0, 1, 0}; ++ unsigned long mode; ++ int err; ++ ++ err = kstrtoul(buf, 10, &mode); ++ if (err) ++ return err; ++ ++ if (mode > 2) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ data->fancfg[attr->index] = i2c_smbus_read_byte_data(client, config_reg[attr->index]); ++ data->fancfg[attr->index] = (data->fancfg[attr->index] & ~0x80) ++ | (max6620_modes[mode] << 7); ++ ++ i2c_smbus_write_byte_data(client, config_reg[attr->index], data->fancfg[attr->index]); ++ ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++/* ++ * Read/write functions for fan1_div sysfs file. The MAX6620 has no such ++ * divider. We handle this by converting between divider and counttime: ++ * ++ * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, 3, 4 or 5 ++ * ++ * Lower values of k allow to connect a faster fan without the risk of ++ * counter overflow. The price is lower resolution. You can also set counttime ++ * using the module parameter. Note that the module parameter "prescaler" also ++ * influences the behaviour. Unfortunately, there's no sysfs attribute ++ * defined for that. See the data sheet for details. ++ */ ++ ++static ssize_t get_div(struct device *dev, struct device_attribute *devattr, char *buf) { ++ ++ struct max6620_data *data = max6620_update_device(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ ++ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fandyn[attr->index])); ++} ++ ++static ssize_t set_div(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { ++ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ unsigned long div; ++ int err; ++ u8 div_bin; ++ ++ err = kstrtoul(buf, 10, &div); ++ if (err) ++ return err; ++ ++ mutex_lock(&data->update_lock); ++ switch (div) { ++ case 1: ++ div_bin = 0; ++ break; ++ case 2: ++ div_bin = 1; ++ break; ++ case 4: ++ div_bin = 2; ++ break; ++ case 8: ++ div_bin = 3; ++ break; ++ case 16: ++ div_bin = 4; ++ break; ++ case 32: ++ div_bin = 5; ++ break; ++ default: ++ mutex_unlock(&data->update_lock); ++ return -EINVAL; ++ } ++ data->fandyn[attr->index] &= 0x1F; ++ data->fandyn[attr->index] |= div_bin << 5; ++ i2c_smbus_write_byte_data(client, dyn_reg[attr->index], data->fandyn[attr->index]); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0); ++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1); ++static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2); ++static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3); ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target, 0); ++static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div, 0); ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 0); ++static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, get_target, set_target, 1); ++static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, get_div, set_div, 1); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 1); ++static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 1); ++static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO, get_target, set_target, 2); ++static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO, get_div, set_div, 2); ++static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 2); ++static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 2); ++static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO, get_target, set_target, 3); ++static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO, get_div, set_div, 3); ++static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, 3); ++static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 3); ++ ++static struct attribute *max6620_attrs[] = { ++ &sensor_dev_attr_fan1_input.dev_attr.attr, ++ &sensor_dev_attr_fan2_input.dev_attr.attr, ++ &sensor_dev_attr_fan3_input.dev_attr.attr, ++ &sensor_dev_attr_fan4_input.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_div.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm1.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_div.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2.dev_attr.attr, ++ &sensor_dev_attr_fan3_target.dev_attr.attr, ++ &sensor_dev_attr_fan3_div.dev_attr.attr, ++ &sensor_dev_attr_pwm3_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm3.dev_attr.attr, ++ &sensor_dev_attr_fan4_target.dev_attr.attr, ++ &sensor_dev_attr_fan4_div.dev_attr.attr, ++ &sensor_dev_attr_pwm4_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm4.dev_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group max6620_attr_grp = { ++ .attrs = max6620_attrs, ++}; ++ ++ ++/* ++ * Real code ++ */ ++ ++static int __devinit max6620_probe(struct i2c_client *client, const struct i2c_device_id *id) { ++ ++ struct max6620_data *data; ++ int err; ++ ++ data = devm_kzalloc(&client->dev, sizeof(struct max6620_data), GFP_KERNEL); ++ if (!data) { ++ dev_err(&client->dev, "out of memory.\n"); ++ return -ENOMEM; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ data->nr_fans = id->driver_data; ++ ++ /* ++ * Initialize the max6620 chip ++ */ ++ dev_info(&client->dev, "About to initialize module\n"); ++ ++ err = max6620_init_client(client); ++ if (err) ++ return err; ++ dev_info(&client->dev, "Module initialized\n"); ++ ++ err = sysfs_create_group(&client->dev.kobj, &max6620_attr_grp); ++ if (err) ++ return err; ++dev_info(&client->dev, "Sysfs entries created\n"); ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (!IS_ERR(data->hwmon_dev)) ++ return 0; ++ ++ err = PTR_ERR(data->hwmon_dev); ++ dev_err(&client->dev, "error registering hwmon device.\n"); ++ ++ sysfs_remove_group(&client->dev.kobj, &max6620_attr_grp); ++ return err; ++} ++ ++static int __devexit max6620_remove(struct i2c_client *client) { ++ ++ struct max6620_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ ++ sysfs_remove_group(&client->dev.kobj, &max6620_attr_grp); ++ return 0; ++} ++ ++static int max6620_init_client(struct i2c_client *client) { ++ ++ struct max6620_data *data = i2c_get_clientdata(client); ++ int config; ++ int err = -EIO; ++ int i; ++ ++ config = i2c_smbus_read_byte_data(client, MAX6620_REG_CONFIG); ++ ++ if (config < 0) { ++ dev_err(&client->dev, "Error reading config, aborting.\n"); ++ return err; ++ } ++ ++ ++ /* ++ * Set bit 4, disable other fans from going full speed on a fail ++ * failure. ++ */ ++ if (i2c_smbus_write_byte_data(client, MAX6620_REG_CONFIG, config | 0x10)) { ++ dev_err(&client->dev, "Config write error, aborting.\n"); ++ return err; ++ } ++ ++ data->config = config; ++ for (i = 0; i < 4; i++) { ++ data->fancfg[i] = i2c_smbus_read_byte_data(client, config_reg[i]); ++ data->fancfg[i] |= 0xa8; // enable TACH monitoring ++ i2c_smbus_write_byte_data(client, config_reg[i], data->fancfg[i]); ++ data->fandyn[i] = i2c_smbus_read_byte_data(client, dyn_reg[i]); ++ /* 2 counts (001) and Rate change 100 (0.125 secs) */ ++ data-> fandyn[i] = 0x30; ++ i2c_smbus_write_byte_data(client, dyn_reg[i], data->fandyn[i]); ++ data->tach[i] = i2c_smbus_read_byte_data(client, tach_reg[i]); ++ data->volt[i] = i2c_smbus_read_byte_data(client, volt_reg[i]); ++ data->target[i] = i2c_smbus_read_byte_data(client, target_reg[i]); ++ data->dac[i] = i2c_smbus_read_byte_data(client, dac_reg[i]); ++ ++ } ++ return 0; ++} ++ ++static struct max6620_data *max6620_update_device(struct device *dev) ++{ ++ int i; ++ u8 fault_reg; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6620_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { ++ ++ for (i = 0; i < 4; i++) { ++ data->fancfg[i] = i2c_smbus_read_byte_data(client, config_reg[i]); ++ data->fandyn[i] = i2c_smbus_read_byte_data(client, dyn_reg[i]); ++ data->tach[i] = i2c_smbus_read_byte_data(client, tach_reg[i]); ++ data->volt[i] = i2c_smbus_read_byte_data(client, volt_reg[i]); ++ data->target[i] = i2c_smbus_read_byte_data(client, target_reg[i]); ++ data->dac[i] = i2c_smbus_read_byte_data(client, dac_reg[i]); ++ } ++ ++ ++ /* ++ * Alarms are cleared on read in case the condition that ++ * caused the alarm is removed. Keep the value latched here ++ * for providing the register through different alarm files. ++ */ ++ fault_reg = i2c_smbus_read_byte_data(client, MAX6620_REG_FAULT); ++ data->fault |= (fault_reg >> 4) & (fault_reg & 0x0F); ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++// module_i2c_driver(max6620_driver); ++ ++static int __init max6620_init(void) ++{ ++ return i2c_add_driver(&max6620_driver); ++} ++module_init(max6620_init); ++ ++/** ++ * sht21_init() - clean up driver ++ * ++ * Called when module is removed. ++ */ ++static void __exit max6620_exit(void) ++{ ++ i2c_del_driver(&max6620_driver); ++} ++module_exit(max6620_exit); ++ ++MODULE_AUTHOR("Lucas Grunenberg"); ++MODULE_DESCRIPTION("MAX6620 sensor driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c +index 8c3df04..5e78a33 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch new file mode 100644 index 00000000..00480ae1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6639.c.patch @@ -0,0 +1,456 @@ +--- a/drivers/hwmon/max6639.c ++++ b/drivers/hwmon/max6639.c +@@ -66,9 +66,62 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; + #define MAX6639_GCONFIG_CH2_LOCAL 0x10 + #define MAX6639_GCONFIG_PWM_FREQ_HI 0x08 + +-#define MAX6639_FAN_CONFIG1_PWM 0x80 ++#define MAX6639_GCONFIG_STANDBY_OFFSET 7 ++#define MAX6639_GCONFIG_POR_OFFSET 6 ++#define MAX6639_GCONFIG_DISABLE_TIMEOUT_OFFSET 5 ++#define MAX6639_GCONFIG_CH2_LOCAL_OFFSET 4 ++#define MAX6639_GCONFIG_PWM_FREQ_HI_OFFSET 3 ++ ++#define MAX6639_OUTMASK_CH1_ALERT_DISABLE 7 ++#define MAX6639_OUTMASK_CH2_ALERT_DISABLE 6 ++#define MAX6639_OUTMASK_CH1_OT_DISABLE 5 ++#define MAX6639_OUTMASK_CH2_OT_DISABLE 4 ++#define MAX6639_OUTMASK_CH1_THERM_DISABLE 3 ++#define MAX6639_OUTMASK_CH2_THERM_DISABLE 2 ++#define MAX6639_OUTMASK_FAN1_FAULT_ENABLE 1 ++#define MAX6639_OUTMASK_FAN2_FAULT_ENABLE 0 ++ ++#define MAX6639_FAN_CONFIG1_PWM 0x80 ++#define MAX6639_FAN_CONFIG1_PWM_MODE 0x80 ++#define MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET 7 ++#define MAX6639_FAN_CONFIG1_DUTY 0x70 ++#define MAX6639_FAN_CONFIG1_DUTY_OFFSET 4 ++#define MAX6639_FAN_CONFIG1_TEMP_CH 0x0c ++#define MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET 2 ++#define MAX6639_FAN_CONFIG1_RPM_RANGE 0x03 ++#define MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET 0 ++ ++#define MAX6639_FAN_CONFIG2a_RPM_STEPA 0xf0 ++#define MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET 4 ++#define MAX6639_FAN_CONFIG2a_TEMP_STEPA 0x0f ++#define MAX6639_FAN_CONFIG2a_TEMP_STEPA_OFFSET 0 ++ ++#define MAX6639_FAN_CONFIG2b_RPM_STEPB 0xf0 ++#define MAX6639_FAN_CONFIG2b_RPM_STEPB_OFFSET 4 ++#define MAX6639_FAN_CONFIG2b_START_STEPB 0x0f ++#define MAX6639_FAN_CONFIG2b_START_STEPB_OFFSET 0 ++ ++ ++#define MAX6639_FAN_CONFIG3_SPINUP_DISABLE 0x80 ++#define MAX6639_FAN_CONFIG3_SPINUP_DISABLE_OFFSET 7 ++#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40 ++#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED_OFFSET 6 ++#define MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE 0x20 ++#define MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE_OFFSET 5 ++#define MAX6639_FAN_CONFIG3_PWM_FREQ 0x3 ++#define MAX6639_FAN_CONFIG3_PWM_FREQ_OFFSET 0 ++ ++#define MAX6639_FAN_PPR_COUNT 0xc0 ++#define MAX6639_FAN_PPR_COUNT_OFFSET 6 ++#define MAX6639_FAN_PPR_TACH_MIN 0x3f ++#define MAX6639_FAN_PPR_TACH_MIN_OFFSET 0 ++ ++#define MAX6639_FAN_TARGET_CNT 0xff ++#define MAX6639_FAN_TARGET_CNT_OFFSET 0 ++ ++#define MAX6639_FAN_CNT 0xff ++#define MAX6639_FAN_CNT_OFFSET 0 + +-#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40 + + static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 }; + +@@ -162,6 +215,299 @@ abort: + return ret; + } + ++ ++/* Puneet start */ ++static ssize_t show_fan_target(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ int conf, tach_count, range; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ tach_count = i2c_smbus_read_byte_data(client, MAX6639_REG_TARGET_CNT(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ if (tach_count < 0) ++ return tach_count; ++ ++ range = (conf & MAX6639_FAN_CONFIG1_RPM_RANGE) >> MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET; ++ return sprintf(buf, "%d\n", FAN_FROM_REG(tach_count, range)); ++} ++ ++static ssize_t set_fan_target(struct device *dev, ++ struct device_attribute *dev_attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int conf, range, tach_count, target_speed; ++ int res; ++ ++ res = strict_strtoul(buf, 10, &target_speed); ++ if (res < 0) ++ return res; ++ ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ ++ range = (conf & MAX6639_FAN_CONFIG1_RPM_RANGE) >> MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET; ++ tach_count = FAN_FROM_REG(target_speed, range); ++ ++ mutex_lock(&data->update_lock); ++ res= i2c_smbus_write_byte_data(client, ++ MAX6639_REG_TARGET_CNT(attr->index), tach_count); ++ mutex_unlock(&data->update_lock); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++static ssize_t show_pwm_enable(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int conf; ++ int pwm_mode; ++ int temp_ch; ++ int mode = 0; ++ /*Modes 0: Auto Control, 1: Manual PWM Control, 2: Manual RPM Control */ ++ ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ ++ pwm_mode = (conf & MAX6639_FAN_CONFIG1_PWM_MODE) >> MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET; ++ temp_ch = (conf & MAX6639_FAN_CONFIG1_TEMP_CH) >> MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET; ++ ++ if (pwm_mode == 1) ++ mode = 1; ++ else if (temp_ch == 0) ++ mode = 2; ++ return sprintf(buf, "%d\n",mode); ++} ++ ++static ssize_t set_pwm_enable(struct device *dev, ++ struct device_attribute *dev_attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int mode, pwm_mode, temp_ch; ++ int res; ++ int val = 0; ++ /*Modes 0: Auto Control, 1: Manual PWM Control, 2: Manual RPM Control */ ++ res = strict_strtoul(buf, 10, &mode); ++ if (res < 0) ++ return res; ++ ++ if (mode == 0) { ++ pwm_mode = 0; ++ temp_ch = 3; ++ } else if (mode == 1){ ++ pwm_mode = 1; ++ temp_ch = 3; ++ } else { ++ pwm_mode = 0; ++ temp_ch = 0; ++ } ++ val |= ((pwm_mode << MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET) & ++ MAX6639_FAN_CONFIG1_PWM_MODE); ++ val |= ((temp_ch << MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET) & ++ MAX6639_FAN_CONFIG1_TEMP_CH); ++ ++ mutex_lock(&data->update_lock); ++ res = i2c_smbus_write_byte_data(client, ++ MAX6639_REG_FAN_CONFIG1(attr->index), val); ++ mutex_unlock(&data->update_lock); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++static ssize_t show_value(struct device *dev, char *buf, ++ u8 reg, u8 mask, u8 offset) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ int reg_val; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ mutex_lock(&data->update_lock); ++ reg_val = i2c_smbus_read_byte_data(client, reg); ++ mutex_unlock(&data->update_lock); ++ if (reg_val < 0) ++ return reg_val; ++ ++ reg_val = (reg_val & mask) >> offset; ++ return sprintf(buf, "%d\n", reg_val); ++} ++ ++static ssize_t set_value(struct device *dev, const char *buf, size_t count, ++ u8 reg, u8 mask, u8 offset) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6639_data *data = i2c_get_clientdata(client); ++ unsigned long val; ++ int res; ++ int reg_val; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ res = strict_strtoul(buf, 10, &val); ++ if (res) ++ return res; ++ mutex_lock(&data->update_lock); ++ reg_val = i2c_smbus_read_byte_data(client, reg); ++ mutex_unlock(&data->update_lock); ++ if (reg_val < 0) ++ return reg_val; ++ ++ reg_val &= ~mask; ++ val = (val << offset) & mask; ++ reg_val |= val; ++ ++ mutex_lock(&data->update_lock); ++ res = i2c_smbus_write_byte_data(client, reg, val); ++ mutex_unlock(&data->update_lock); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++#define max6639_attr(type, reg, mask, off) \ ++static ssize_t show_##type(struct device *dev, \ ++ struct device_attribute *dev_attr, char *buf) \ ++{ \ ++ return show_value(dev, buf, reg, mask, off); \ ++} \ ++static ssize_t set_##type(struct device *dev, \ ++ struct device_attribute *dev_attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ return set_value(dev, buf, count, reg, mask, off); \ ++} \ ++static SENSOR_DEVICE_ATTR(type, S_IWUSR | S_IRUGO, show_##type, set_##type, 0); \ ++ ++static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, set_pwm_enable, 0); ++static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, set_pwm_enable, 1); ++static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, show_fan_target, set_fan_target, 0); ++static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO, show_fan_target, set_fan_target, 1); ++ ++max6639_attr(standby, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_STANDBY, ++ MAX6639_GCONFIG_STANDBY_OFFSET) ++max6639_attr(por, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_POR, ++ MAX6639_GCONFIG_POR_OFFSET) ++max6639_attr(disable_smbus_timeout, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_DISABLE_TIMEOUT, ++ MAX6639_GCONFIG_DISABLE_TIMEOUT_OFFSET) ++max6639_attr(ch2_local, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_CH2_LOCAL, ++ MAX6639_GCONFIG_CH2_LOCAL_OFFSET) ++max6639_attr(pwm_freq_hi, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_PWM_FREQ_HI, ++ MAX6639_GCONFIG_PWM_FREQ_HI_OFFSET) ++ ++max6639_attr(ch1_alert_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH1_ALERT_DISABLE, ++ MAX6639_OUTMASK_CH1_ALERT_DISABLE) ++max6639_attr(ch2_alert_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH2_ALERT_DISABLE, ++ MAX6639_OUTMASK_CH2_ALERT_DISABLE) ++max6639_attr(ch1_ot_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH1_OT_DISABLE, ++ MAX6639_OUTMASK_CH1_OT_DISABLE) ++max6639_attr(ch2_ot_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH2_OT_DISABLE, ++ MAX6639_OUTMASK_CH2_OT_DISABLE) ++max6639_attr(ch1_therm_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH1_THERM_DISABLE, ++ MAX6639_OUTMASK_CH1_THERM_DISABLE) ++max6639_attr(ch2_therm_disable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_CH2_THERM_DISABLE, ++ MAX6639_OUTMASK_CH2_THERM_DISABLE) ++max6639_attr(fan1_fault_enable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_FAN1_FAULT_ENABLE, ++ MAX6639_OUTMASK_FAN1_FAULT_ENABLE) ++max6639_attr(fan2_fault_enable, MAX6639_REG_OUTPUT_MASK, 1 << MAX6639_OUTMASK_FAN2_FAULT_ENABLE, ++ MAX6639_OUTMASK_FAN2_FAULT_ENABLE) ++ ++ ++max6639_attr(fan1_pwm_mode, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_PWM_MODE, ++ MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET) ++max6639_attr(fan2_pwm_mode, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_PWM_MODE, ++ MAX6639_FAN_CONFIG1_PWM_MODE_OFFSET) ++max6639_attr(fan1_duty, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_DUTY, ++ MAX6639_FAN_CONFIG1_DUTY_OFFSET) ++max6639_attr(fan2_duty, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_DUTY, ++ MAX6639_FAN_CONFIG1_DUTY_OFFSET) ++max6639_attr(fan1_temp_ch, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_TEMP_CH, ++ MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET) ++max6639_attr(fan2_temp_ch, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_TEMP_CH, ++ MAX6639_FAN_CONFIG1_TEMP_CH_OFFSET) ++max6639_attr(fan1_rpm_range, MAX6639_REG_FAN_CONFIG1(0), MAX6639_FAN_CONFIG1_RPM_RANGE, ++ MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET) ++max6639_attr(fan2_rpm_range, MAX6639_REG_FAN_CONFIG1(1), MAX6639_FAN_CONFIG1_RPM_RANGE, ++ MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET) ++ ++max6639_attr(fan1_rpm_step_size_a, MAX6639_REG_FAN_CONFIG2a(0), MAX6639_FAN_CONFIG2a_RPM_STEPA, ++ MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET) ++max6639_attr(fan2_rpm_step_size_a, MAX6639_REG_FAN_CONFIG2a(1), MAX6639_FAN_CONFIG2a_RPM_STEPA, ++ MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET) ++max6639_attr(fan1_temp_step_size, MAX6639_REG_FAN_CONFIG2a(0), MAX6639_FAN_CONFIG2a_TEMP_STEPA, ++ MAX6639_FAN_CONFIG2a_RPM_STEPA_OFFSET) ++max6639_attr(fan2_temp_step_size, MAX6639_REG_FAN_CONFIG2a(1), MAX6639_FAN_CONFIG2a_TEMP_STEPA, ++ MAX6639_FAN_CONFIG2a_TEMP_STEPA_OFFSET) ++ ++max6639_attr(fan1_rpm_step_size_b, MAX6639_REG_FAN_CONFIG2b(0), MAX6639_FAN_CONFIG2b_RPM_STEPB, ++ MAX6639_FAN_CONFIG2b_RPM_STEPB_OFFSET) ++max6639_attr(fan2_rpm_step_size_b, MAX6639_REG_FAN_CONFIG2b(1), MAX6639_FAN_CONFIG2b_RPM_STEPB, ++ MAX6639_FAN_CONFIG2b_RPM_STEPB_OFFSET) ++max6639_attr(fan1_rpm_start_step_b, MAX6639_REG_FAN_CONFIG2b(0), MAX6639_FAN_CONFIG2b_START_STEPB, ++ MAX6639_FAN_CONFIG2b_START_STEPB_OFFSET) ++max6639_attr(fan2_rpm_start_step_b, MAX6639_REG_FAN_CONFIG2b(1), MAX6639_FAN_CONFIG2b_RPM_STEPB, ++ MAX6639_FAN_CONFIG2b_START_STEPB_OFFSET) ++ ++max6639_attr(fan1_spinup_disable, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_SPINUP_DISABLE, ++ MAX6639_FAN_CONFIG3_SPINUP_DISABLE_OFFSET) ++max6639_attr(fan2_spinup_disable, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_SPINUP_DISABLE, ++ MAX6639_FAN_CONFIG3_SPINUP_DISABLE_OFFSET) ++max6639_attr(fan1_therm_full_speed_enable, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_THERM_FULL_SPEED, ++ MAX6639_FAN_CONFIG3_THERM_FULL_SPEED_OFFSET) ++max6639_attr(fan2_therm_full_speed_enable, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_THERM_FULL_SPEED, ++ MAX6639_FAN_CONFIG3_THERM_FULL_SPEED_OFFSET) ++max6639_attr(fan1_pulse_stretch_disable, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE, ++ MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE_OFFSET) ++max6639_attr(fan2_pulse_stretch_disable, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE, ++ MAX6639_FAN_CONFIG3_PULSE_STR_DISABLE_OFFSET) ++max6639_attr(fan1_pwm_freq, MAX6639_REG_FAN_CONFIG3(0), MAX6639_FAN_CONFIG3_PWM_FREQ, ++ MAX6639_FAN_CONFIG3_PWM_FREQ_OFFSET) ++max6639_attr(fan2_pwm_freq, MAX6639_REG_FAN_CONFIG3(1), MAX6639_FAN_CONFIG3_PWM_FREQ, ++ MAX6639_FAN_CONFIG3_PWM_FREQ_OFFSET) ++ ++max6639_attr(fan1_ppr_count, MAX6639_REG_FAN_PPR(0), MAX6639_FAN_PPR_COUNT, ++ MAX6639_FAN_PPR_COUNT_OFFSET) ++max6639_attr(fan2_ppr_count, MAX6639_REG_FAN_PPR(1), MAX6639_FAN_PPR_COUNT, ++ MAX6639_FAN_PPR_COUNT_OFFSET) ++max6639_attr(fan1_tach_min, MAX6639_REG_FAN_PPR(0), MAX6639_FAN_PPR_TACH_MIN, ++ MAX6639_FAN_PPR_TACH_MIN_OFFSET) ++max6639_attr(fan2_tach_min, MAX6639_REG_FAN_PPR(1), MAX6639_FAN_PPR_TACH_MIN, ++ MAX6639_FAN_PPR_TACH_MIN_OFFSET) ++ ++max6639_attr(fan1_cnt_target, MAX6639_REG_TARGET_CNT(0), MAX6639_FAN_TARGET_CNT, ++ MAX6639_FAN_TARGET_CNT_OFFSET) ++max6639_attr(fan2_cnt_target, MAX6639_REG_TARGET_CNT(1), MAX6639_FAN_TARGET_CNT, ++ MAX6639_FAN_TARGET_CNT_OFFSET) ++ ++max6639_attr(fan1_cnt, MAX6639_REG_FAN_CNT(0), MAX6639_FAN_CNT, ++ MAX6639_FAN_CNT_OFFSET) ++max6639_attr(fan2_cnt, MAX6639_REG_FAN_CNT(1), MAX6639_FAN_CNT, ++ MAX6639_FAN_CNT_OFFSET) ++ ++/*Puneet end */ + static ssize_t show_temp_input(struct device *dev, + struct device_attribute *dev_attr, char *buf) + { +@@ -326,14 +672,27 @@ static ssize_t set_pwm(struct device *dev, + static ssize_t show_fan_input(struct device *dev, + struct device_attribute *dev_attr, char *buf) + { ++ struct i2c_client *client = to_i2c_client(dev); + struct max6639_data *data = max6639_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); ++ int conf, range, input; + + if (IS_ERR(data)) + return PTR_ERR(data); ++ mutex_lock(&data->update_lock); ++ conf = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CONFIG1(attr->index)); ++ input = i2c_smbus_read_byte_data(client, MAX6639_REG_FAN_CNT(attr->index)); ++ mutex_unlock(&data->update_lock); ++ if (conf < 0) ++ return conf; ++ ++ if (input < 0) ++ return input; ++ ++ range = (conf & MAX6639_FAN_CONFIG1_RPM_RANGE) >> ++ MAX6639_FAN_CONFIG1_RPM_RANGE_OFFSET; + +- return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index], +- data->rpm_range)); ++ return sprintf(buf, "%d\n", FAN_FROM_REG(input, range)); + } + + static ssize_t show_alarm(struct device *dev, +@@ -401,6 +760,55 @@ static struct attribute *max6639_attributes[] = { + &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr, ++ &sensor_dev_attr_standby.dev_attr.attr, ++ &sensor_dev_attr_por.dev_attr.attr, ++ &sensor_dev_attr_disable_smbus_timeout.dev_attr.attr, ++ &sensor_dev_attr_ch2_local.dev_attr.attr, ++ &sensor_dev_attr_pwm_freq_hi.dev_attr.attr, ++ &sensor_dev_attr_ch1_alert_disable.dev_attr.attr, ++ &sensor_dev_attr_ch2_alert_disable.dev_attr.attr, ++ &sensor_dev_attr_ch1_ot_disable.dev_attr.attr, ++ &sensor_dev_attr_ch2_ot_disable.dev_attr.attr, ++ &sensor_dev_attr_ch1_therm_disable.dev_attr.attr, ++ &sensor_dev_attr_ch2_therm_disable.dev_attr.attr, ++ &sensor_dev_attr_fan1_fault_enable.dev_attr.attr, ++ &sensor_dev_attr_fan2_fault_enable.dev_attr.attr, ++ &sensor_dev_attr_fan1_pwm_mode.dev_attr.attr, ++ &sensor_dev_attr_fan2_pwm_mode.dev_attr.attr, ++ &sensor_dev_attr_fan1_duty.dev_attr.attr, ++ &sensor_dev_attr_fan2_duty.dev_attr.attr, ++ &sensor_dev_attr_fan1_temp_ch.dev_attr.attr, ++ &sensor_dev_attr_fan2_temp_ch.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_range.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_range.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_step_size_a.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_step_size_a.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_step_size_b.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_step_size_b.dev_attr.attr, ++ &sensor_dev_attr_fan1_temp_step_size.dev_attr.attr, ++ &sensor_dev_attr_fan2_temp_step_size.dev_attr.attr, ++ &sensor_dev_attr_fan1_rpm_start_step_b.dev_attr.attr, ++ &sensor_dev_attr_fan2_rpm_start_step_b.dev_attr.attr, ++ &sensor_dev_attr_fan1_spinup_disable.dev_attr.attr, ++ &sensor_dev_attr_fan2_spinup_disable.dev_attr.attr, ++ &sensor_dev_attr_fan1_therm_full_speed_enable.dev_attr.attr, ++ &sensor_dev_attr_fan2_therm_full_speed_enable.dev_attr.attr, ++ &sensor_dev_attr_fan1_pulse_stretch_disable.dev_attr.attr, ++ &sensor_dev_attr_fan2_pulse_stretch_disable.dev_attr.attr, ++ &sensor_dev_attr_fan1_pwm_freq.dev_attr.attr, ++ &sensor_dev_attr_fan2_pwm_freq.dev_attr.attr, ++ &sensor_dev_attr_fan1_ppr_count.dev_attr.attr, ++ &sensor_dev_attr_fan2_ppr_count.dev_attr.attr, ++ &sensor_dev_attr_fan1_tach_min.dev_attr.attr, ++ &sensor_dev_attr_fan2_tach_min.dev_attr.attr, ++ &sensor_dev_attr_fan1_cnt_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_cnt_target.dev_attr.attr, ++ &sensor_dev_attr_fan1_cnt.dev_attr.attr, ++ &sensor_dev_attr_fan2_cnt.dev_attr.attr, ++ &sensor_dev_attr_pwm1_enable.dev_attr.attr, ++ &sensor_dev_attr_pwm2_enable.dev_attr.attr, ++ &sensor_dev_attr_fan1_target.dev_attr.attr, ++ &sensor_dev_attr_fan2_target.dev_attr.attr, + NULL + }; + +diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c +new file mode 100644 +index 0000000..b567828 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch new file mode 100644 index 00000000..3460088b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_max6697.c.patch @@ -0,0 +1,707 @@ +--- /dev/null ++++ b/drivers/hwmon/max6697.c +@@ -0,0 +1,702 @@ ++/* ++ * Copyright (c) 2012 Guenter Roeck ++ * ++ * based on max1668.c ++ * Copyright (c) 2011 David George ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++enum chips { max6581, max6602, max6622, max6636, max6689, max6693, max6694, ++ max6697, max6698, max6699 }; ++ ++/* Report local sensor as temp1 */ ++ ++static const u8 MAX6697_REG_TEMP[] = { ++ 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08 }; ++static const u8 MAX6697_REG_TEMP_EXT[] = { ++ 0x57, 0x09, 0x52, 0x53, 0x54, 0x55, 0x56, 0 }; ++static const u8 MAX6697_REG_MAX[] = { ++ 0x17, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18 }; ++static const u8 MAX6697_REG_CRIT[] = { ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 }; ++ ++/* ++ * Map device tree / platform data register bit map to chip bit map. ++ * Applies to alert register and over-temperature register. ++ */ ++#define MAX6697_MAP_BITS(reg) ((((reg) & 0x7e) >> 1) | \ ++ (((reg) & 0x01) << 6) | ((reg) & 0x80)) ++ ++#define MAX6697_REG_STAT(n) (0x44 + (n)) ++ ++#define MAX6697_REG_CONFIG 0x41 ++#define MAX6581_CONF_EXTENDED (1 << 1) ++#define MAX6693_CONF_BETA (1 << 2) ++#define MAX6697_CONF_RESISTANCE (1 << 3) ++#define MAX6697_CONF_TIMEOUT (1 << 5) ++#define MAX6697_REG_ALERT_MASK 0x42 ++#define MAX6697_REG_OVERT_MASK 0x43 ++ ++#define MAX6581_REG_RESISTANCE 0x4a ++#define MAX6581_REG_IDEALITY 0x4b ++#define MAX6581_REG_IDEALITY_SELECT 0x4c ++#define MAX6581_REG_OFFSET 0x4d ++#define MAX6581_REG_OFFSET_SELECT 0x4e ++ ++#define MAX6697_CONV_TIME 156 /* ms per channel, worst case */ ++ ++struct max6697_chip_data { ++ int channels; ++ u32 have_ext; ++ u32 have_crit; ++ u32 have_fault; ++ u8 valid_conf; ++ const u8 *alarm_map; ++}; ++ ++struct max6697_data { ++ struct device *hwmon_dev; ++ ++ enum chips type; ++ const struct max6697_chip_data *chip; ++ ++ int update_interval; /* in milli-seconds */ ++ int temp_offset; /* in degrees C */ ++ ++ struct mutex update_lock; ++ unsigned long last_updated; /* In jiffies */ ++ bool valid; /* true if following fields are valid */ ++ ++ /* 1x local and up to 7x remote */ ++ u8 temp[8][4]; /* [nr][0]=temp [1]=ext [2]=max [3]=crit */ ++#define MAX6697_TEMP_INPUT 0 ++#define MAX6697_TEMP_EXT 1 ++#define MAX6697_TEMP_MAX 2 ++#define MAX6697_TEMP_CRIT 3 ++ u32 alarms; ++}; ++ ++/* Diode fault status bits on MAX6581 are right shifted by one bit */ ++static const u8 max6581_alarm_map[] = { ++ 0, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, ++ 16, 17, 18, 19, 20, 21, 22, 23 }; ++ ++static const struct max6697_chip_data max6697_chip_data[] = { ++ [max6581] = { ++ .channels = 8, ++ .have_crit = 0xff, ++ .have_ext = 0x7f, ++ .have_fault = 0xfe, ++ .valid_conf = MAX6581_CONF_EXTENDED | MAX6697_CONF_TIMEOUT, ++ .alarm_map = max6581_alarm_map, ++ }, ++ [max6602] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6622] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6636] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6689] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6693] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA | ++ MAX6697_CONF_TIMEOUT, ++ }, ++ [max6694] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA | ++ MAX6697_CONF_TIMEOUT, ++ }, ++ [max6697] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x7e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6698] = { ++ .channels = 7, ++ .have_crit = 0x72, ++ .have_ext = 0x02, ++ .have_fault = 0x0e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++ [max6699] = { ++ .channels = 5, ++ .have_crit = 0x12, ++ .have_ext = 0x02, ++ .have_fault = 0x1e, ++ .valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT, ++ }, ++}; ++ ++static struct max6697_data *max6697_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6697_data *data = i2c_get_clientdata(client); ++ struct max6697_data *ret = data; ++ int val; ++ int i; ++ u32 alarms; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (data->valid && ++ !time_after(jiffies, data->last_updated ++ + msecs_to_jiffies(data->update_interval))) ++ goto abort; ++ ++ for (i = 0; i < data->chip->channels; i++) { ++ if (data->chip->have_ext & (1 << i)) { ++ val = i2c_smbus_read_byte_data(client, ++ MAX6697_REG_TEMP_EXT[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_EXT] = val; ++ } ++ ++ val = i2c_smbus_read_byte_data(client, MAX6697_REG_TEMP[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_INPUT] = val; ++ ++ val = i2c_smbus_read_byte_data(client, MAX6697_REG_MAX[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_MAX] = val; ++ ++ if (data->chip->have_crit & (1 << i)) { ++ val = i2c_smbus_read_byte_data(client, ++ MAX6697_REG_CRIT[i]); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ data->temp[i][MAX6697_TEMP_CRIT] = val; ++ } ++ } ++ ++ alarms = 0; ++ for (i = 0; i < 3; i++) { ++ val = i2c_smbus_read_byte_data(client, MAX6697_REG_STAT(i)); ++ if (unlikely(val < 0)) { ++ ret = ERR_PTR(val); ++ goto abort; ++ } ++ alarms = (alarms << 8) | val; ++ } ++ data->alarms = alarms; ++ data->last_updated = jiffies; ++ data->valid = true; ++abort: ++ mutex_unlock(&data->update_lock); ++ ++ return ret; ++} ++ ++static ssize_t show_temp_input(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ int index = to_sensor_dev_attr(devattr)->index; ++ struct max6697_data *data = max6697_update_device(dev); ++ int temp; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ temp = (data->temp[index][MAX6697_TEMP_INPUT] - data->temp_offset) << 3; ++ temp |= data->temp[index][MAX6697_TEMP_EXT] >> 5; ++ ++ return sprintf(buf, "%d\n", temp * 125); ++} ++ ++static ssize_t show_temp(struct device *dev, ++ struct device_attribute *devattr, char *buf) ++{ ++ int nr = to_sensor_dev_attr_2(devattr)->nr; ++ int index = to_sensor_dev_attr_2(devattr)->index; ++ struct max6697_data *data = max6697_update_device(dev); ++ int temp; ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ temp = data->temp[nr][index]; ++ temp -= data->temp_offset; ++ ++ return sprintf(buf, "%d\n", temp * 1000); ++} ++ ++static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ int index = to_sensor_dev_attr(attr)->index; ++ struct max6697_data *data = max6697_update_device(dev); ++ ++ if (IS_ERR(data)) ++ return PTR_ERR(data); ++ ++ if (data->chip->alarm_map) ++ index = data->chip->alarm_map[index]; ++ ++ return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1); ++} ++ ++static ssize_t set_temp(struct device *dev, ++ struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ int nr = to_sensor_dev_attr_2(devattr)->nr; ++ int index = to_sensor_dev_attr_2(devattr)->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6697_data *data = i2c_get_clientdata(client); ++ long temp; ++ int ret; ++ ++ ret = kstrtol(buf, 10, &temp); ++ if (ret < 0) ++ return ret; ++ ++ mutex_lock(&data->update_lock); ++ temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset; ++ temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127); ++ data->temp[nr][index] = temp; ++ ret = i2c_smbus_write_byte_data(client, ++ index == 2 ? MAX6697_REG_MAX[nr] ++ : MAX6697_REG_CRIT[nr], ++ temp); ++ mutex_unlock(&data->update_lock); ++ ++ return ret < 0 ? ret : count; ++} ++ ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); ++static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 0, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 0, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); ++static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 1, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 1, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); ++static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 2, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 2, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); ++static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 3, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 3, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); ++static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 4, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 4, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); ++static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 5, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 5, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_input, NULL, 6); ++static SENSOR_DEVICE_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 6, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 6, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_input, NULL, 7); ++static SENSOR_DEVICE_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 7, MAX6697_TEMP_MAX); ++static SENSOR_DEVICE_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, ++ 7, MAX6697_TEMP_CRIT); ++ ++static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 22); ++static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 16); ++static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 17); ++static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 18); ++static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 19); ++static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, show_alarm, NULL, 20); ++static SENSOR_DEVICE_ATTR(temp7_max_alarm, S_IRUGO, show_alarm, NULL, 21); ++static SENSOR_DEVICE_ATTR(temp8_max_alarm, S_IRUGO, show_alarm, NULL, 23); ++ ++static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); ++static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); ++static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); ++static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 10); ++static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_alarm, NULL, 11); ++static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, show_alarm, NULL, 12); ++static SENSOR_DEVICE_ATTR(temp7_crit_alarm, S_IRUGO, show_alarm, NULL, 13); ++static SENSOR_DEVICE_ATTR(temp8_crit_alarm, S_IRUGO, show_alarm, NULL, 15); ++ ++static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 1); ++static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 3); ++static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5); ++static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6); ++static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7); ++ ++static DEVICE_ATTR(dummy, 0, NULL, NULL); ++ ++static mode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr, ++ int index) ++{ ++ struct device *dev = container_of(kobj, struct device, kobj); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max6697_data *data = i2c_get_clientdata(client); ++ const struct max6697_chip_data *chip = data->chip; ++ int channel = index / 6; /* channel number */ ++ int nr = index % 6; /* attribute index within channel */ ++ ++ if (channel >= chip->channels) ++ return 0; ++ ++ if ((nr == 3 || nr == 4) && !(chip->have_crit & (1 << channel))) ++ return 0; ++ if (nr == 5 && !(chip->have_fault & (1 << channel))) ++ return 0; ++ ++ return attr->mode; ++} ++ ++/* ++ * max6697_is_visible uses the index into the following array to determine ++ * if attributes should be created or not. Any change in order or content ++ * must be matched in max6697_is_visible. ++ */ ++static struct attribute *max6697_attributes[] = { ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp1_crit.dev_attr.attr, ++ &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, ++ &dev_attr_dummy.attr, ++ ++ &sensor_dev_attr_temp2_input.dev_attr.attr, ++ &sensor_dev_attr_temp2_max.dev_attr.attr, ++ &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_crit.dev_attr.attr, ++ &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp2_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp3_input.dev_attr.attr, ++ &sensor_dev_attr_temp3_max.dev_attr.attr, ++ &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_crit.dev_attr.attr, ++ &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp3_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp4_input.dev_attr.attr, ++ &sensor_dev_attr_temp4_max.dev_attr.attr, ++ &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_crit.dev_attr.attr, ++ &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp4_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp5_input.dev_attr.attr, ++ &sensor_dev_attr_temp5_max.dev_attr.attr, ++ &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_crit.dev_attr.attr, ++ &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp5_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp6_input.dev_attr.attr, ++ &sensor_dev_attr_temp6_max.dev_attr.attr, ++ &sensor_dev_attr_temp6_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp6_crit.dev_attr.attr, ++ &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp6_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp7_input.dev_attr.attr, ++ &sensor_dev_attr_temp7_max.dev_attr.attr, ++ &sensor_dev_attr_temp7_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp7_crit.dev_attr.attr, ++ &sensor_dev_attr_temp7_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp7_fault.dev_attr.attr, ++ ++ &sensor_dev_attr_temp8_input.dev_attr.attr, ++ &sensor_dev_attr_temp8_max.dev_attr.attr, ++ &sensor_dev_attr_temp8_max_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp8_crit.dev_attr.attr, ++ &sensor_dev_attr_temp8_crit_alarm.dev_attr.attr, ++ &sensor_dev_attr_temp8_fault.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group max6697_group = { ++ .attrs = max6697_attributes, .is_visible = max6697_is_visible, ++}; ++ ++static void max6697_get_config_of(struct device_node *node, ++ struct max6697_platform_data *pdata) ++{ ++ int len; ++ const __be32 *prop; ++ ++ prop = of_get_property(node, "smbus-timeout-disable", &len); ++ if (prop) ++ pdata->smbus_timeout_disable = true; ++ prop = of_get_property(node, "extended-range-enable", &len); ++ if (prop) ++ pdata->extended_range_enable = true; ++ prop = of_get_property(node, "beta-compensation-enable", &len); ++ if (prop) ++ pdata->beta_compensation = true; ++ prop = of_get_property(node, "alert-mask", &len); ++ if (prop && len == sizeof(u32)) ++ pdata->alert_mask = be32_to_cpu(prop[0]); ++ prop = of_get_property(node, "over-temperature-mask", &len); ++ if (prop && len == sizeof(u32)) ++ pdata->over_temperature_mask = be32_to_cpu(prop[0]); ++ prop = of_get_property(node, "resistance-cancellation", &len); ++ if (prop) { ++ if (len == sizeof(u32)) ++ pdata->resistance_cancellation = be32_to_cpu(prop[0]); ++ else ++ pdata->resistance_cancellation = 0xfe; ++ } ++ prop = of_get_property(node, "transistor-ideality", &len); ++ if (prop && len == 2 * sizeof(u32)) { ++ pdata->ideality_mask = be32_to_cpu(prop[0]); ++ pdata->ideality_value = be32_to_cpu(prop[1]); ++ } ++} ++ ++static int max6697_init_chip(struct i2c_client *client) ++{ ++ struct max6697_data *data = i2c_get_clientdata(client); ++ struct max6697_platform_data *pdata = dev_get_platdata(&client->dev); ++ struct max6697_platform_data p; ++ const struct max6697_chip_data *chip = data->chip; ++ int factor = chip->channels; ++ int ret, reg; ++ ++ /* ++ * Don't touch configuration if neither platform data nor OF ++ * configuration was specified. If that is the case, use the ++ * current chip configuration. ++ */ ++ if (!pdata && !client->dev.of_node) { ++ reg = i2c_smbus_read_byte_data(client, MAX6697_REG_CONFIG); ++ if (reg < 0) ++ return reg; ++ if (data->type == max6581) { ++ if (reg & MAX6581_CONF_EXTENDED) ++ data->temp_offset = 64; ++ reg = i2c_smbus_read_byte_data(client, ++ MAX6581_REG_RESISTANCE); ++ if (reg < 0) ++ return reg; ++ factor += hweight8(reg); ++ } else { ++ if (reg & MAX6697_CONF_RESISTANCE) ++ factor++; ++ } ++ goto done; ++ } ++ ++ if (client->dev.of_node) { ++ memset(&p, 0, sizeof(p)); ++ max6697_get_config_of(client->dev.of_node, &p); ++ pdata = &p; ++ } ++ ++ reg = 0; ++ if (pdata->smbus_timeout_disable && ++ (chip->valid_conf & MAX6697_CONF_TIMEOUT)) { ++ reg |= MAX6697_CONF_TIMEOUT; ++ } ++ if (pdata->extended_range_enable && ++ (chip->valid_conf & MAX6581_CONF_EXTENDED)) { ++ reg |= MAX6581_CONF_EXTENDED; ++ data->temp_offset = 64; ++ } ++ if (pdata->resistance_cancellation && ++ (chip->valid_conf & MAX6697_CONF_RESISTANCE)) { ++ reg |= MAX6697_CONF_RESISTANCE; ++ factor++; ++ } ++ if (pdata->beta_compensation && ++ (chip->valid_conf & MAX6693_CONF_BETA)) { ++ reg |= MAX6693_CONF_BETA; ++ } ++ ++ ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, reg); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK, ++ MAX6697_MAP_BITS(pdata->alert_mask)); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK, ++ MAX6697_MAP_BITS(pdata->over_temperature_mask)); ++ if (ret < 0) ++ return ret; ++ ++ if (data->type == max6581) { ++ factor += hweight8(pdata->resistance_cancellation >> 1); ++ ret = i2c_smbus_write_byte_data(client, MAX6581_REG_RESISTANCE, ++ pdata->resistance_cancellation >> 1); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY, ++ pdata->ideality_value); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_write_byte_data(client, ++ MAX6581_REG_IDEALITY_SELECT, ++ pdata->ideality_mask >> 1); ++ if (ret < 0) ++ return ret; ++ } ++done: ++ data->update_interval = factor * MAX6697_CONV_TIME; ++ return 0; ++} ++ ++static int max6697_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adapter = client->adapter; ++ struct device *dev = &client->dev; ++ struct max6697_data *data; ++ int err; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ return -ENODEV; ++ ++ data = devm_kzalloc(dev, sizeof(struct max6697_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->type = id->driver_data; ++ data->chip = &max6697_chip_data[data->type]; ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ err = max6697_init_chip(client); ++ if (err) ++ return err; ++ ++ err = sysfs_create_group(&client->dev.kobj, &max6697_group); ++ if (err) ++ return err; ++ ++ data->hwmon_dev = hwmon_device_register(dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto error; ++ } ++ ++ return 0; ++ ++error: ++ sysfs_remove_group(&client->dev.kobj, &max6697_group); ++ return err; ++} ++ ++static int max6697_remove(struct i2c_client *client) ++{ ++ struct max6697_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &max6697_group); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id max6697_id[] = { ++ { "max6581", max6581 }, ++ { "max6602", max6602 }, ++ { "max6622", max6622 }, ++ { "max6636", max6636 }, ++ { "max6689", max6689 }, ++ { "max6693", max6693 }, ++ { "max6694", max6694 }, ++ { "max6697", max6697 }, ++ { "max6698", max6698 }, ++ { "max6699", max6699 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max6697_id); ++ ++static struct i2c_driver max6697_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "max6697", ++ }, ++ .probe = max6697_probe, ++ .remove = max6697_remove, ++ .id_table = max6697_id, ++}; ++ ++module_i2c_driver(max6697_driver); ++ ++MODULE_AUTHOR("Guenter Roeck "); ++MODULE_DESCRIPTION("MAX6697 temperature sensor driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig +index 4b26f51..e549b09 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch new file mode 100644 index 00000000..1aef0cb1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Kconfig.patch @@ -0,0 +1,39 @@ +--- a/drivers/hwmon/pmbus/Kconfig ++++ b/drivers/hwmon/pmbus/Kconfig +@@ -119,4 +119,34 @@ config SENSORS_ZL6100 + This driver can also be built as a module. If so, the module will + be called zl6100. + ++config SENSORS_DPS460 ++ tristate "Delta DPS460" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for Delta ++ DPSXXX Power Supply. ++ ++ This driver can also be built as a module. If so, the module will ++ be called dps460. ++ ++config SENSORS_PS2471 ++ tristate "Lite-ON PS2471" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for Lite ++ -ON PS2471. ++ ++ This driver can also be built as a module. If so, the module will ++ be called ps2471. ++ ++config SENSORS_CPR4011 ++ tristate "Compuware CPR4011 4M11/21" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for Compuware ++ CPR4011 4M11/21 ++ ++ This driver can also be built as a module. If so, the module will ++ be called cpr4011. ++ + endif # PMBUS +diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile +index 789376c..85aeddf 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch new file mode 100644 index 00000000..0e18bea0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_Makefile.patch @@ -0,0 +1,12 @@ +--- a/drivers/hwmon/pmbus/Makefile ++++ b/drivers/hwmon/pmbus/Makefile +@@ -13,3 +13,6 @@ obj-$(CONFIG_SENSORS_MAX8688) += max8688.o + obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o + obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o + obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o ++obj-$(CONFIG_SENSORS_DPS460) += dps460.o ++obj-$(CONFIG_SENSORS_PS2471) += ps2471.o ++obj-$(CONFIG_SENSORS_CPR4011) += cpr4011.o +diff --git a/drivers/hwmon/pmbus/cpr4011.c b/drivers/hwmon/pmbus/cpr4011.c +new file mode 100644 +index 0000000..4cd976a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch new file mode 100644 index 00000000..4e5730fb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_cpr4011.c.patch @@ -0,0 +1,89 @@ +--- /dev/null ++++ b/drivers/hwmon/pmbus/cpr4011.c +@@ -0,0 +1,83 @@ ++/* ++ * Hardware monitoring driver for Compuware CPR-4011-4M11/21 ++ * ++ * Copyright (C) 2015 Cumulus Networks, LLC ++ * Author: Puneet Shenoy ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++enum chips { cpr4011 }; ++ ++static int cpr4011_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) { ++ pr_err("i2c check functionality failed\n"); ++ return -ENODEV; ++ } ++ info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->pages = 1; ++ info->func[0] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; ++ info->format[PSC_PWM] = linear; ++ ++ ret = pmbus_do_probe(client, id, info); ++ if (ret < 0) ++ kfree(info); ++ return ret; ++} ++ ++static int cpr4011_remove(struct i2c_client *client) ++{ ++ pmbus_do_remove(client); ++ return 0; ++} ++ ++static const struct i2c_device_id cpr4011_id[] = { ++ {"cpr4011", cpr4011}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, cpr4011_id); ++ ++static struct i2c_driver cpr4011_driver = { ++ .driver = { .name = "cpr4011",}, ++ .probe = cpr4011_probe, ++ .remove = cpr4011_remove, ++ .id_table = cpr4011_id, ++}; ++ ++module_i2c_driver(cpr4011_driver); ++ ++MODULE_AUTHOR("Puneet Shenoy"); ++MODULE_DESCRIPTION("PMBus driver for Compuware CPR4011 4M11/21 Power Supply"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/pmbus/dps460.c b/drivers/hwmon/pmbus/dps460.c +new file mode 100644 +index 0000000..47a8ee6 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch new file mode 100644 index 00000000..76cb56ca --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_dps460.c.patch @@ -0,0 +1,106 @@ +--- /dev/null ++++ b/drivers/hwmon/pmbus/dps460.c +@@ -0,0 +1,101 @@ ++/* ++ * Hardware monitoring driver for Delta DPSXXX Power Supplies ++ * ++ * Copyright (C) 2015 Cumulus Networks, LLC ++ * Author: Puneet Shenoy ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++enum chips { dps460, dps200 }; ++ ++static int dps460_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_PEC)) ++ return -ENODEV; ++ ++ info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ /* Use only 1 page with 1 Fan, 2 Temps. */ ++ info->pages = 1; ++ info->func[0] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; ++ info->format[PSC_PWM] = linear; ++ ++ if ((i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BLOCK_DATA))) ++ info->func[0] |= PMBUS_HAVE_MFR_INFO; ++ ++ if (id->driver_data == dps200) { ++ info->format[PSC_VOLTAGE_OUT] = direct; ++ info->format[PSC_FAN] = linear; ++ } else if (id->driver_data == dps460) { ++ /* Needs PEC(PACKET ERROR CODE) for writes */ ++ client->flags = I2C_CLIENT_PEC; ++ } ++ ++ ret = pmbus_do_probe(client, id, info); ++ if (ret < 0) ++ kfree(info); ++ return ret; ++} ++ ++static int dps460_remove(struct i2c_client *client) ++{ ++ pmbus_do_remove(client); ++ return 0; ++} ++ ++static const struct i2c_device_id dps460_id[] = { ++ {"dps460", dps460}, ++ {"dps200", dps200}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, dps460_id); ++ ++static struct i2c_driver dps460_driver = { ++ .driver = { ++ .name = "dps460", ++ }, ++ .probe = dps460_probe, ++ .remove = dps460_remove, ++ .id_table = dps460_id, ++}; ++ ++module_i2c_driver(dps460_driver); ++ ++MODULE_AUTHOR("Puneet Shenoy"); ++MODULE_DESCRIPTION("PMBus driver for Delta DPSXXX"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h +index 5d31d1c..48eb99c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch new file mode 100644 index 00000000..ac9da2ad --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus.h.patch @@ -0,0 +1,20 @@ +--- a/drivers/hwmon/pmbus/pmbus.h ++++ b/drivers/hwmon/pmbus/pmbus.h +@@ -288,6 +288,7 @@ enum pmbus_sensor_classes { + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, ++ PSC_PWM, + PSC_NUM_CLASSES /* Number of power sensor classes */ + }; + +@@ -312,6 +313,7 @@ enum pmbus_sensor_classes { + #define PMBUS_HAVE_STATUS_TEMP (1 << 15) + #define PMBUS_HAVE_STATUS_FAN12 (1 << 16) + #define PMBUS_HAVE_STATUS_FAN34 (1 << 17) ++#define PMBUS_HAVE_MFR_INFO (1 << 18) + + enum pmbus_data_format { linear = 0, direct, vid }; + +diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c +index d89b339..60c846c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch new file mode 100644 index 00000000..724ae420 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_pmbus_core.c.patch @@ -0,0 +1,267 @@ +--- a/drivers/hwmon/pmbus/pmbus_core.c ++++ b/drivers/hwmon/pmbus/pmbus_core.c +@@ -62,6 +62,8 @@ + + #define PMBUS_MAX_INPUT_LABELS 4 /* vin, vcap, iin, pin */ + ++#define PMBUS_MFR_INFO_COUNT 6 /* Manufacturer info fields */ ++ + /* + * status, status_vout, status_iout, status_fans, status_fan34, and status_temp + * are paged. status_input is unpaged. +@@ -103,6 +105,11 @@ struct pmbus_label { + char label[PMBUS_NAME_SIZE]; /* label */ + }; + ++struct pmbus_mfr { ++ char name[PMBUS_NAME_SIZE]; /* sysfs mfr name */ ++ struct sensor_device_attribute attribute; ++}; ++ + struct pmbus_data { + struct device *hwmon_dev; + +@@ -138,6 +145,13 @@ struct pmbus_data { + int num_labels; + struct pmbus_label *labels; + ++ /* ++ * Manufacturer Info ++ */ ++ int max_mfrs; ++ int num_mfrs; ++ struct pmbus_mfr *mfrs; ++ + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ +@@ -445,6 +459,10 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, + if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ + exponent = data->exponent; + mantissa = (u16) sensor->data; ++ } else if (sensor->class == PSC_PWM) { ++ /* PWM has a duty cycle value from 0 to 100 */ ++ mantissa = (u16) sensor->data; ++ exponent = 0; + } else { /* LINEAR11 */ + exponent = ((s16)sensor->data) >> 11; + mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; +@@ -452,6 +470,13 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, + + val = mantissa; + ++ /* Map duty cycle 0 -> 100 to PWM range 0 -> 255 */ ++ if (sensor->class == PSC_PWM) { ++ val = (val * 255)/100; ++ val = SENSORS_LIMIT(val, 0, 255); ++ return val; ++ } ++ + /* scale result to milli-units for all sensors except fans */ + if (sensor->class != PSC_FAN) + val = val * 1000L; +@@ -558,6 +583,13 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, + if (val == 0) + return 0; + ++ /* Map PWM range 0 -> 255 to duty cycle 0 -> 100 */ ++ if (class == PSC_PWM) { ++ val = (val * 100)/255; ++ SENSORS_LIMIT(val, 0, 100); ++ return val; ++ } ++ + if (class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) +@@ -769,6 +801,31 @@ static ssize_t pmbus_show_sensor(struct device *dev, + return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); + } + ++static ssize_t pmbus_show_mfr(struct device *dev, ++ struct device_attribute *da, ++ char *buf) { ++ struct i2c_client *client = to_i2c_client(dev); ++ int cmd = to_sensor_dev_attr(da)->index; ++ u8 b_buf[I2C_SMBUS_BLOCK_MAX + 1]; ++ int ret; ++ ++ if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_BLOCK_DATA)) ++ ret = i2c_smbus_read_block_data(client, cmd, b_buf); ++ else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) ++ ret = i2c_smbus_read_i2c_block_data(client, cmd, ++ I2C_SMBUS_BLOCK_MAX, b_buf); ++ else ++ ret = -EIO; ++ ++ if (ret < 0) ++ return ret; ++ ++ b_buf[ret] = '\0'; ++ return sprintf(buf, "%s\n", b_buf); ++}; ++ + static ssize_t pmbus_set_sensor(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +@@ -846,6 +903,20 @@ static void pmbus_add_boolean(struct pmbus_data *data, + data->num_booleans++; + } + ++static void pmbus_add_mfr(struct pmbus_data *data, const char *name, ++ int idx) ++{ ++ struct pmbus_mfr *mfr; ++ ++ BUG_ON(data->num_mfrs >= data->max_mfrs); ++ ++ mfr = &data->mfrs[data->num_mfrs]; ++ ++ snprintf(mfr->name, sizeof(mfr->name), "%s", name); ++ PMBUS_ADD_GET_ATTR(data, mfr->name, mfr, idx); ++ data->num_mfrs++; ++} ++ + static void pmbus_add_boolean_reg(struct pmbus_data *data, + const char *name, const char *type, + int seq, int reg, int bit) +@@ -871,8 +942,12 @@ static void pmbus_add_sensor(struct pmbus_data *data, + BUG_ON(data->num_sensors >= data->max_sensors); + + sensor = &data->sensors[data->num_sensors]; +- snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", +- name, seq, type); ++ if (!(strcmp("pwm", name))) ++ snprintf(sensor->name, sizeof(sensor->name), "%s%d", ++ name, seq); ++ else ++ snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", ++ name, seq, type); + sensor->page = page; + sensor->reg = reg; + sensor->class = class; +@@ -914,11 +989,12 @@ static void pmbus_find_max_attr(struct i2c_client *client, + struct pmbus_data *data) + { + const struct pmbus_driver_info *info = data->info; +- int page, max_sensors, max_booleans, max_labels; ++ int page, max_sensors, max_booleans, max_labels, max_mfrs; + + max_sensors = PMBUS_MAX_INPUT_SENSORS; + max_booleans = PMBUS_MAX_INPUT_BOOLEANS; + max_labels = PMBUS_MAX_INPUT_LABELS; ++ max_mfrs = 0; + + for (page = 0; page < info->pages; page++) { + if (info->func[page] & PMBUS_HAVE_VOUT) { +@@ -957,10 +1033,15 @@ static void pmbus_find_max_attr(struct i2c_client *client, + max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP; + } + } ++ if (info->func[0] & PMBUS_HAVE_MFR_INFO) ++ max_mfrs = PMBUS_MFR_INFO_COUNT; ++ + data->max_sensors = max_sensors; + data->max_booleans = max_booleans; + data->max_labels = max_labels; +- data->max_attributes = max_sensors + max_booleans + max_labels; ++ data->max_mfrs = max_mfrs; ++ data->max_attributes = max_sensors + max_booleans + \ ++ max_labels + max_mfrs; + } + + /* +@@ -1512,6 +1593,13 @@ static const int pmbus_fan_config_registers[] = { + PMBUS_FAN_CONFIG_34 + }; + ++static const int pmbus_fan_cmd_registers[] = { ++ PMBUS_FAN_COMMAND_1, ++ PMBUS_FAN_COMMAND_2, ++ PMBUS_FAN_COMMAND_3, ++ PMBUS_FAN_COMMAND_4, ++}; ++ + static const int pmbus_fan_status_registers[] = { + PMBUS_STATUS_FAN_12, + PMBUS_STATUS_FAN_12, +@@ -1568,6 +1656,9 @@ static void pmbus_add_fan_attributes(struct i2c_client *client, + pmbus_add_sensor(data, "fan", "input", index, page, + pmbus_fan_registers[f], PSC_FAN, true, + true); ++ pmbus_add_sensor(data, "pwm", "", index, page, ++ pmbus_fan_cmd_registers[f], PSC_PWM, ++ true, false); + + /* + * Each fan status register covers multiple fans, +@@ -1594,6 +1685,23 @@ static void pmbus_add_fan_attributes(struct i2c_client *client, + } + } + ++/* Manufacturer Info */ ++static void pmbus_add_mfr_attributes(struct i2c_client *client, ++ struct pmbus_data *data) ++{ ++ const struct pmbus_driver_info *info = data->info; ++ ++ /* Only Read Page 0 mfr info */ ++ if (info->func[0] & PMBUS_HAVE_MFR_INFO) { ++ pmbus_add_mfr(data, "mfr_id", PMBUS_MFR_ID); ++ pmbus_add_mfr(data, "mfr_model", PMBUS_MFR_MODEL); ++ pmbus_add_mfr(data, "mfr_revision", PMBUS_MFR_REVISION); ++ pmbus_add_mfr(data, "mfr_location", PMBUS_MFR_LOCATION); ++ pmbus_add_mfr(data, "mfr_date", PMBUS_MFR_DATE); ++ pmbus_add_mfr(data, "mfr_serial", PMBUS_MFR_SERIAL); ++ } ++} ++ + static void pmbus_find_attributes(struct i2c_client *client, + struct pmbus_data *data) + { +@@ -1615,6 +1723,9 @@ static void pmbus_find_attributes(struct i2c_client *client, + + /* Fans */ + pmbus_add_fan_attributes(client, data); ++ ++ /* Manufacturer Info */ ++ pmbus_add_mfr_attributes(client, data); + } + + /* +@@ -1741,6 +1852,13 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + goto out_booleans; + } + ++ data->mfrs = kzalloc(sizeof(struct pmbus_mfr) * data->max_mfrs, ++ GFP_KERNEL); ++ if (!data->mfrs) { ++ dev_err(&client->dev, "No memory to allocate mfr data\n"); ++ goto out_mfrs; ++ } ++ + data->attributes = kzalloc(sizeof(struct attribute *) + * data->max_attributes, GFP_KERNEL); + if (!data->attributes) { +@@ -1779,6 +1897,8 @@ out_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &data->group); + out_attributes: + kfree(data->attributes); ++out_mfrs: ++ kfree(data->mfrs); + out_labels: + kfree(data->labels); + out_booleans: +@@ -1797,6 +1917,7 @@ void pmbus_do_remove(struct i2c_client *client) + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->attributes); ++ kfree(data->mfrs); + kfree(data->labels); + kfree(data->booleans); + kfree(data->sensors); +diff --git a/drivers/hwmon/pmbus/ps2471.c b/drivers/hwmon/pmbus/ps2471.c +new file mode 100644 +index 0000000..a1ce238 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch new file mode 100644 index 00000000..9de4b98d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_pmbus_ps2471.c.patch @@ -0,0 +1,94 @@ +--- /dev/null ++++ b/drivers/hwmon/pmbus/ps2471.c +@@ -0,0 +1,89 @@ ++/* ++ * Hardware monitoring driver for Lite-ON PS2471 Power Supply ++ * ++ * Copyright (C) 2015 Cumulus Networks, LLC ++ * Author: Puneet Shenoy ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++enum chips { ps2471 }; ++ ++static int ps2471_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) { ++ pr_err("i2c check functionality failed\n"); ++ return -ENODEV; ++ } ++ info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->pages = 1; ++ info->func[0] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; ++ info->format[PSC_PWM] = linear; ++ ++ if ((i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_BLOCK_DATA))) ++ info->func[0] |= PMBUS_HAVE_MFR_INFO; ++ ++ ret = pmbus_do_probe(client, id, info); ++ if (ret < 0) ++ kfree(info); ++ return ret; ++} ++ ++static int ps2471_remove(struct i2c_client *client) ++{ ++ pmbus_do_remove(client); ++ return 0; ++} ++ ++static const struct i2c_device_id ps2471_id[] = { ++ {"ps2471", ps2471}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ps2471_id); ++ ++static struct i2c_driver ps2471_driver = { ++ .driver = { .name = "ps2471",}, ++ .probe = ps2471_probe, ++ .remove = ps2471_remove, ++ .id_table = ps2471_id, ++}; ++ ++module_i2c_driver(ps2471_driver); ++ ++MODULE_AUTHOR("Puneet Shenoy"); ++MODULE_DESCRIPTION("PMBus driver for Lite-ON PS2471 Power Supply"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c +index 8eac67d..8689664 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch new file mode 100644 index 00000000..4f887491 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_hwmon_via-cputemp.c.patch @@ -0,0 +1,38 @@ +--- a/drivers/hwmon/via-cputemp.c ++++ b/drivers/hwmon/via-cputemp.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #define DRVNAME "via_cputemp" + +@@ -308,15 +309,20 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = { + .notifier_call = via_cputemp_cpu_callback, + }; + ++static const struct x86_cpu_id cputemp_ids[] = { ++ { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */ ++ { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */ ++ { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */ ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, cputemp_ids); ++ + static int __init via_cputemp_init(void) + { + int i, err; + +- if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) { +- printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n"); +- err = -ENODEV; +- goto exit; +- } ++ if (!x86_match_cpu(cputemp_ids)) ++ return -ENODEV; + + err = platform_driver_register(&via_cputemp_driver); + if (err) +diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c +index 24f94f4..acba1c6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch new file mode 100644 index 00000000..ef889a76 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Kconfig.patch @@ -0,0 +1,39 @@ +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -120,6 +120,16 @@ config I2C_ISCH + This driver can also be built as a module. If so, the module + will be called i2c-isch. + ++config I2C_ISMT ++ tristate "Intel iSMT SMBus Controller" ++ depends on PCI && X86 ++ help ++ If you say yes to this option, support will be included for the Intel ++ iSMT SMBus host controller interface. ++ ++ This driver can also be built as a module. If so, the module will be ++ called i2c-ismt. ++ + config I2C_PIIX4 + tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)" + depends on PCI +@@ -330,6 +340,17 @@ config I2C_BLACKFIN_TWI_CLK_KHZ + help + The unit of the TWI clock is kHz. + ++config I2C_CEL_CPLD ++ tristate "Celestica CPLD I2C Driver" ++ depends on CEL_REDSTONE ++ help ++ If you say yes to this option, support will be included for ++ the Celestica CPLD I2C interface. This interface is for ++ interacting with SFP+ and QSFP modules. ++ ++ This driver can also be built as a module. If so, the module ++ will be called i2c-cel-cpld. ++ + config I2C_CPM + tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" + depends on (CPM1 || CPM2) && OF_I2C +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index d6b8779..b3f56c8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch new file mode 100644 index 00000000..121c39bf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_busses_Makefile.patch @@ -0,0 +1,21 @@ +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o + obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o + obj-$(CONFIG_I2C_I801) += i2c-i801.o + obj-$(CONFIG_I2C_ISCH) += i2c-isch.o ++obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o + obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o + obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o + obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o +@@ -31,6 +32,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o + obj-$(CONFIG_I2C_AT91) += i2c-at91.o + obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o + obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o ++obj-$(CONFIG_I2C_CEL_CPLD) += i2c-cel-cpld.o + obj-$(CONFIG_I2C_CPM) += i2c-cpm.o + obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o + obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o +diff --git a/drivers/i2c/busses/i2c-cel-cpld.c b/drivers/i2c/busses/i2c-cel-cpld.c +new file mode 100644 +index 0000000..c46bc21 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch new file mode 100644 index 00000000..d34d15cc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_i2c-mux.c.patch @@ -0,0 +1,112 @@ +--- a/drivers/i2c/i2c-mux.c ++++ b/drivers/i2c/i2c-mux.c +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + + /* multiplexer per channel data */ + struct i2c_mux_priv { +@@ -31,11 +33,11 @@ struct i2c_mux_priv { + struct i2c_algorithm algo; + + struct i2c_adapter *parent; +- void *mux_dev; /* the mux chip/device */ ++ void *mux_priv; /* the mux chip/device */ + u32 chan_id; /* the channel id */ + +- int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); +- int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); ++ int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id); ++ int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id); + }; + + static int i2c_mux_master_xfer(struct i2c_adapter *adap, +@@ -47,11 +49,11 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap, + + /* Switch to the right mux port and perform the transfer. */ + +- ret = priv->select(parent, priv->mux_dev, priv->chan_id); ++ ret = priv->select(parent, priv->mux_priv, priv->chan_id); + if (ret >= 0) + ret = parent->algo->master_xfer(parent, msgs, num); + if (priv->deselect) +- priv->deselect(parent, priv->mux_dev, priv->chan_id); ++ priv->deselect(parent, priv->mux_priv, priv->chan_id); + + return ret; + } +@@ -67,12 +69,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, + + /* Select the right mux port and perform the transfer. */ + +- ret = priv->select(parent, priv->mux_dev, priv->chan_id); ++ ret = priv->select(parent, priv->mux_priv, priv->chan_id); + if (ret >= 0) + ret = parent->algo->smbus_xfer(parent, addr, flags, + read_write, command, size, data); + if (priv->deselect) +- priv->deselect(parent, priv->mux_dev, priv->chan_id); ++ priv->deselect(parent, priv->mux_priv, priv->chan_id); + + return ret; + } +@@ -87,7 +89,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap) + } + + struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, +- void *mux_dev, u32 force_nr, u32 chan_id, ++ struct device *mux_dev, ++ void *mux_priv, u32 force_nr, u32 chan_id, + int (*select) (struct i2c_adapter *, + void *, u32), + int (*deselect) (struct i2c_adapter *, +@@ -102,7 +105,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, + + /* Set up private adapter data */ + priv->parent = parent; +- priv->mux_dev = mux_dev; ++ priv->mux_priv = mux_priv; + priv->chan_id = chan_id; + priv->select = select; + priv->deselect = deselect; +@@ -124,6 +127,26 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, + priv->adap.algo_data = priv; + priv->adap.dev.parent = &parent->dev; + ++ /* ++ * Try to get populate the mux adapter's of_node, expands to ++ * nothing if !CONFIG_OF. ++ */ ++ if (mux_dev->of_node) { ++ struct device_node *child; ++ u32 reg; ++ int ret; ++ ++ for_each_child_of_node(mux_dev->of_node, child) { ++ ret = of_property_read_u32(child, "reg", ®); ++ if (ret) ++ continue; ++ if (chan_id == reg) { ++ priv->adap.dev.of_node = child; ++ break; ++ } ++ } ++ } ++ + if (force_nr) { + priv->adap.nr = force_nr; + ret = i2c_add_numbered_adapter(&priv->adap); +@@ -141,6 +164,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, + dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", + i2c_adapter_id(&priv->adap)); + ++ of_i2c_register_devices(&priv->adap); ++ + return &priv->adap; + } + EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); +diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig +index 90b7a01..73ed997 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch new file mode 100644 index 00000000..e702e64f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Kconfig.patch @@ -0,0 +1,21 @@ +--- a/drivers/i2c/muxes/Kconfig ++++ b/drivers/i2c/muxes/Kconfig +@@ -37,4 +37,16 @@ config I2C_MUX_PCA954x + This driver can also be built as a module. If so, the module + will be called pca954x. + ++config I2C_MUX_DNI_6448 ++ tristate "Delta Networks 6448 I2C Mux" ++ depends on EXPERIMENTAL ++ help ++ If you say yes here you get support for the DNI 6448 I2C Mux devices ++ ++config I2C_MUX_QUANTA ++ tristate "CumulusNetworks QUANTA I2C Mux" ++ depends on EXPERIMENTAL ++ help ++ If you say yes here you get support for the QUANTA I2C Mux devices ++ + endmenu +diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile +index 4640436..7fbdd2f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch new file mode 100644 index 00000000..192ab21a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_Makefile.patch @@ -0,0 +1,13 @@ +--- a/drivers/i2c/muxes/Makefile ++++ b/drivers/i2c/muxes/Makefile +@@ -4,5 +4,7 @@ + obj-$(CONFIG_I2C_MUX_GPIO) += gpio-i2cmux.o + obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o + obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o ++obj-$(CONFIG_I2C_MUX_DNI_6448) += dni_6448_i2c_mux.o ++obj-$(CONFIG_I2C_MUX_QUANTA) += quanta-i2cmux.o + + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/muxes/dni_6448_i2c_mux.c b/drivers/i2c/muxes/dni_6448_i2c_mux.c +new file mode 100644 +index 0000000..ecbbd1d diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch new file mode 100644 index 00000000..c4eb589c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_gpio-i2cmux.c.patch @@ -0,0 +1,14 @@ +--- a/drivers/i2c/muxes/gpio-i2cmux.c ++++ b/drivers/i2c/muxes/gpio-i2cmux.c +@@ -105,7 +105,8 @@ static int __devinit gpiomux_probe(struct platform_device *pdev) + for (i = 0; i < pdata->n_values; i++) { + u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; + +- mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i, ++ mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, ++ nr, i, + gpiomux_select, deselect); + if (!mux->adap[i]) { + ret = -ENODEV; +diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c +index ed699c5..e9e07ba 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch new file mode 100644 index 00000000..ceeff4bf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca9541.c.patch @@ -0,0 +1,14 @@ +--- a/drivers/i2c/muxes/pca9541.c ++++ b/drivers/i2c/muxes/pca9541.c +@@ -353,7 +353,8 @@ static int pca9541_probe(struct i2c_client *client, + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; +- data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0, ++ data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client, ++ force, 0, + pca9541_select_chan, + pca9541_release_chan); + +diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c +index 6f89536..c9db544 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch new file mode 100644 index 00000000..c36a8f06 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_i2c_muxes_pca954x.c.patch @@ -0,0 +1,45 @@ +--- a/drivers/i2c/muxes/pca954x.c ++++ b/drivers/i2c/muxes/pca954x.c +@@ -188,6 +188,7 @@ static int pca954x_probe(struct i2c_client *client, + struct pca954x_platform_data *pdata = client->dev.platform_data; + int num, force; + struct pca954x *data; ++ int deselect_on_exit = 0; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) +@@ -210,6 +211,17 @@ static int pca954x_probe(struct i2c_client *client, + goto exit_free; + } + ++ /* ++ * Check whether we want to deselect the mux after the ++ * transaction. This can be specified in one of two ways: ++ * ++ * 1. using platform data: pdata->modes[num].deselect_on_exit ++ * 2. using the device tree property deselect_on_exit ++ */ ++ if (of_find_property(client->dev.of_node, "deselect-on-exit", NULL)) { ++ deselect_on_exit = 1; ++ } ++ + data->type = id->driver_data; + data->last_chan = 0; /* force the first selection */ + +@@ -226,10 +238,10 @@ static int pca954x_probe(struct i2c_client *client, + } + + data->virt_adaps[num] = +- i2c_add_mux_adapter(adap, client, ++ i2c_add_mux_adapter(adap, &client->dev, client, + force, num, pca954x_select_chan, +- (pdata && pdata->modes[num].deselect_on_exit) +- ? pca954x_deselect_mux : NULL); ++ (pdata && pdata->modes[num].deselect_on_exit) || deselect_on_exit ++ ? pca954x_deselect_mux : NULL); + + if (data->virt_adaps[num] == NULL) { + ret = -ENODEV; +diff --git a/drivers/i2c/muxes/quanta-i2cmux.c b/drivers/i2c/muxes/quanta-i2cmux.c +new file mode 100644 +index 0000000..498f6e7 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch new file mode 100644 index 00000000..ca38ba7a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Kconfig.patch @@ -0,0 +1,60 @@ +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -500,6 +500,55 @@ config USB_SWITCH_FSA9480 + stereo and mono audio, video, microphone and UART data to use + a common connector port. + ++config EARLY_DMA_ALLOC ++ bool "Early DMA Memory Allocator" ++ depends on HAS_DMA ++ ++ ---help--- ++ This driver locks down a region of DMA accessible memory ++ early in the boot process. This memory can be used by other ++ drivers that might rmmod/insmod, insuring the memory region ++ does not become fragmented. ++ ++config EDA_DEF_SIZE ++ hex "EDA Default Region Size" ++ depends on EARLY_DMA_ALLOC ++ default 0x04000000 ++ help ++ Default size of the reserved memory pool, if not altered by the ++ open firmware interface or kernel boot parameter. This memory ++ will not be accessable to the rest of the system. Default is ++ 64MB. ++ ++config EDA_DEF_ALIGN ++ hex "EDA Default Alignment" ++ depends on EARLY_DMA_ALLOC ++ default 0x00100000 ++ help ++ Default alignment of the memory region. Default is 1MB. ++ ++config RETIMER_CLASS ++ tristate "Retimer Class support" ++ depends on SYSFS ++ depends on OF ++ default y ++ help ++ Creates a hardware class in sysfs called "retimer_dev", ++ providing a common place to register RETIMER devices. ++ ++ This support can also be built as a module. If so, the module ++ will be called retimer_class. ++ ++config DS100DF410 ++ tristate "DS100DF410 Low Power 10GbE Quad Channel Retimer" ++ depends on I2C && SYSFS ++ help ++ If you say yes here you get support for the DS100DF410 ++ Low Power 10GbE Quad Channel Retimer. ++ ++ This driver can also be built as a module. If so, the module ++ will be called ds100df410. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index b26495a..ad70876 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch new file mode 100644 index 00000000..57927135 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_Makefile.patch @@ -0,0 +1,12 @@ +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -48,3 +48,6 @@ obj-y += lis3lv02d/ + obj-y += carma/ + obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o + obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ ++obj-$(CONFIG_EARLY_DMA_ALLOC) += early_dma_alloc.o ++obj-$(CONFIG_RETIMER_CLASS) += retimer_class.o ++obj-$(CONFIG_DS100DF410) += ds100df410.o +diff --git a/drivers/misc/ds100df410.c b/drivers/misc/ds100df410.c +new file mode 100644 +index 0000000..d46d107 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch new file mode 100644 index 00000000..3e00c18f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ds100df410.c.patch @@ -0,0 +1,332 @@ +--- /dev/null ++++ b/drivers/misc/ds100df410.c +@@ -0,0 +1,326 @@ ++/* ++ * ds100df410.c - I2c client driver to manage DS100DF410 ++ * DS100DF410 Low Power 10GbE Quad Channel Retimer ++ * ++ * Copyright (C) 2014 Cumulus Networks, Inc. ++ * Author: Puneet Shenoy ++ * ++ * Ideas and structure regarding introducing the class device graciously borrowed ++ * from the eeprom sysfs/class support by: ++ * Copyright (C) 2013 CumulusNetworks, Inc. ++ * Author: Curt Brune ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_RETIMER_CLASS ++#include ++#endif ++ ++#define DS100DF410_DRV_NAME "ds100df410" ++#define DRIVER_VERSION "1.0" ++ ++#define DS100DF410_RESET_REG 0x00 ++#define DS100DF410_OVERRIDE_REG 0x09 ++#define DS100DF410_CDR_RST_REG 0x0a ++#define DS100DF410_TAP_DEM_REG 0x15 ++#define DS100DF410_PFD_PRBS_DFE_REG 0x1e ++#define DS100DF410_DRV_SEL_VOD_REG 0x2d ++#define DS100DF410_ADAPT_EQ_SM_REG 0x31 ++#define DS100DF410_VEO_CLK_CDR_CAP_REG 0x36 ++#define DS100DF410_CHANNELS_REG 0xff ++ ++struct ds100df410_data { ++ struct i2c_client *client; ++ ++#ifdef CONFIG_RETIMER_CLASS ++ struct device *retimer_dev; ++#endif ++ struct mutex lock; ++}; ++ ++static u32 ds100df410_read(struct device *dev, u8 reg, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ u32 ret = i2c_smbus_read_byte_data(client, reg); ++ ++ return sprintf(buf, "%d\n", ret); ++} ++ ++static u32 ds100df410_write(struct device *dev, u8 reg, const char *buf, ++ size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ unsigned long val; ++ int ret; ++ ++ if (strict_strtoul(buf, 0, &val) < 0) ++ return -EINVAL; ++ ++ ret = i2c_smbus_write_byte_data(client, reg, (u8)val); ++ if (ret < 0) ++ return ret; ++ ++ return count; ++} ++ ++static ssize_t ds100df410_show_cdr_rst(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_CDR_RST_REG, buf); ++} ++ ++static ssize_t ds100df410_store_cdr_rst(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_CDR_RST_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_tap_dem(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_TAP_DEM_REG, buf); ++} ++ ++static ssize_t ds100df410_store_tap_dem(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_TAP_DEM_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_pfd_prbs_dfe(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_PFD_PRBS_DFE_REG, buf); ++} ++ ++static ssize_t ds100df410_store_pfd_prbs_dfe(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_PFD_PRBS_DFE_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_drv_sel_vod(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_DRV_SEL_VOD_REG, buf); ++} ++ ++static ssize_t ds100df410_store_drv_sel_vod(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_DRV_SEL_VOD_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_adapt_eq_sm(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_ADAPT_EQ_SM_REG, buf); ++} ++ ++static ssize_t ds100df410_store_adapt_eq_sm(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_ADAPT_EQ_SM_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_veo_clk_cdr_cap(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_VEO_CLK_CDR_CAP_REG, buf); ++} ++ ++static ssize_t ds100df410_store_veo_clk_cdr_cap(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_VEO_CLK_CDR_CAP_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_channels(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_CHANNELS_REG, buf); ++} ++ ++static ssize_t ds100df410_store_channels(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_CHANNELS_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_override(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_OVERRIDE_REG, buf); ++} ++ ++static ssize_t ds100df410_store_override(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_OVERRIDE_REG, buf, count); ++} ++ ++static ssize_t ds100df410_show_reset(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return ds100df410_read(dev, DS100DF410_RESET_REG, buf); ++} ++ ++static ssize_t ds100df410_store_reset(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ return ds100df410_write(dev, DS100DF410_RESET_REG, buf, count); ++} ++ ++static DEVICE_ATTR(cdr_rst, S_IWUSR | S_IRUGO, ++ ds100df410_show_cdr_rst, ds100df410_store_cdr_rst); ++static DEVICE_ATTR(tap_dem, S_IWUSR | S_IRUGO, ++ ds100df410_show_tap_dem, ds100df410_store_tap_dem); ++static DEVICE_ATTR(pfd_prbs_dfe, S_IWUSR | S_IRUGO, ++ ds100df410_show_pfd_prbs_dfe, ds100df410_store_pfd_prbs_dfe); ++static DEVICE_ATTR(drv_sel_vod, S_IWUSR | S_IRUGO, ++ ds100df410_show_drv_sel_vod, ds100df410_store_drv_sel_vod); ++static DEVICE_ATTR(adapt_eq_sm, S_IWUSR | S_IRUGO, ++ ds100df410_show_adapt_eq_sm, ds100df410_store_adapt_eq_sm); ++static DEVICE_ATTR(veo_clk_cdr_cap, S_IWUSR | S_IRUGO, ++ ds100df410_show_veo_clk_cdr_cap, ++ ds100df410_store_veo_clk_cdr_cap); ++static DEVICE_ATTR(channels, S_IWUSR | S_IRUGO, ++ ds100df410_show_channels, ds100df410_store_channels); ++static DEVICE_ATTR(override, S_IWUSR | S_IRUGO, ++ ds100df410_show_override, ds100df410_store_override); ++static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, ++ ds100df410_show_reset, ds100df410_store_reset); ++ ++static struct attribute *ds100df410_attributes[] = { ++ &dev_attr_cdr_rst.attr, ++ &dev_attr_tap_dem.attr, ++ &dev_attr_pfd_prbs_dfe.attr, ++ &dev_attr_drv_sel_vod.attr, ++ &dev_attr_adapt_eq_sm.attr, ++ &dev_attr_veo_clk_cdr_cap.attr, ++ &dev_attr_channels.attr, ++ &dev_attr_override.attr, ++ &dev_attr_reset.attr, ++ NULL ++}; ++ ++static const struct attribute_group ds100df410_attr_group = { ++ .attrs = ds100df410_attributes, ++}; ++ ++static int __devinit ds100df410_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); ++ struct ds100df410_data *data; ++ int err = 0; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { ++ return -EIO; ++ } ++ ++ data = kzalloc(sizeof(struct ds100df410_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ data->client = client; ++ mutex_init(&data->lock); ++ ++ /* register sysfs hooks */ ++ err = sysfs_create_group(&client->dev.kobj, &ds100df410_attr_group); ++ if (err) ++ goto exit_kfree; ++ ++ ++#ifdef CONFIG_RETIMER_CLASS ++ data->retimer_dev = retimer_device_register(&client->dev); ++ if (IS_ERR(data->retimer_dev)) { ++ dev_err(&client->dev, "error registering retimer device.\n"); ++ err = PTR_ERR(data->retimer_dev); ++ goto exit_kfree; ++ } ++#endif ++ ++ i2c_set_clientdata(client, data); ++ return 0; ++exit_kfree: ++ kfree(data); ++ return err; ++} ++ ++static int __devexit ds100df410_remove(struct i2c_client *client) ++{ ++ struct ds100df410_data *data; ++ ++ data = i2c_get_clientdata(client); ++ sysfs_remove_group(&client->dev.kobj, &ds100df410_attr_group); ++ ++#ifdef CONFIG_RETIMER_CLASS ++ retimer_device_unregister(data->retimer_dev); ++#endif ++ ++ kfree(data); ++ return 0; ++} ++ ++static const struct i2c_device_id ds100df410_id[] = { ++ { "ds100df410", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ds100df410_id); ++ ++static struct i2c_driver ds100df410_driver = { ++ .driver = { ++ .name = DS100DF410_DRV_NAME, ++ }, ++ .probe = ds100df410_probe, ++ .remove = __devexit_p(ds100df410_remove), ++ .id_table = ds100df410_id, ++}; ++ ++module_i2c_driver(ds100df410_driver); ++MODULE_AUTHOR("Puneet Shenoy "); ++MODULE_DESCRIPTION("I2C client for DS100DF410 10GE Quad Core Retimer"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION(DRIVER_VERSION); +diff --git a/drivers/misc/early_dma_alloc.c b/drivers/misc/early_dma_alloc.c +new file mode 100644 +index 0000000..609a858 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch new file mode 100644 index 00000000..570d67a3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_early_dma_alloc.c.patch @@ -0,0 +1,228 @@ +--- /dev/null ++++ b/drivers/misc/early_dma_alloc.c +@@ -0,0 +1,223 @@ ++/* ++ * Early DMA Memory Allocator ++ * ++ * Copyright © 2013,2014 Cumulus Networks, Inc. ++ * ++ * Author: Curt Brune ++ * Modified: Jonathan Toppins ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++/* ++ * This driver allocates a region of DMA accessible memory, making it ++ * available to one other device driver. ++ * ++ * The client device driver may be unloaded and reloaded over time. ++ * This driver keeps the DMA region from becoming fragmented across ++ * module reloads. ++ * ++ * Memory Region Restrictions ++ * -------------------------- ++ * The memory region allocated by EDA MUST exist below a 4GB limit. This ++ * is because EDA's primary (only at time of writing) user is the ++ * Broadcom BDE driver wich assumes a 32-bit physical address space and ++ * assumes paddr is no more than 32-bits wide. Furthermore, before porting ++ * the BDE driver to use EDA the BDE driver specifically checked if the ++ * memory region provided by highmem was less than 4GB. We assume Broadcom ++ * knew what they were doing and there is a specific reason why this 4GB ++ * limit is needed, so we enforce this limit by checking the physical address ++ * after allocation. ++ * ++ * Memory Region Size and Alignment ++ * -------------------------------- ++ * This driver allows three ways for the user to define the DMA memory ++ * that will be created, listed in order of preference. ++ * 1. The user may specify on the kernel command line in the boot loader ++ * the "eda_mem" option, this option has the format "size@alignment", ++ * example: eda_mem=0x04000000@0x00100000 ++ * 2. This driver looks for a device tree node compatible with ++ * "early-dma-alloc". The "region_size" property of the node contains ++ * the size, in bytes, of the desired DMA memory region. The ++ * "alignment" property contains the desired memory alignment of the ++ * region. ++ * 3. Finally if neither of the above are provided the Kbuild changable, ++ * compiled in default size and alignment will be used. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if (!defined CONFIG_EDA_DEF_SIZE) || \ ++ (!defined CONFIG_EDA_DEF_ALIGN) ++#error incorrect kernel config - fix it ++#endif ++ ++// #define DEBUG ++#if (defined DEBUG) ++#define eda_debug(fmt, ... ) \ ++ printk(KERN_ERR "eda-debug:%s(): " fmt "\n", __func__ , \ ++ ##__VA_ARGS__) ++#else ++#define eda_debug(fmt, ... ) ++#endif ++ ++#define eda_info(fmt, ... ) \ ++ printk(KERN_INFO "eda: " fmt "\n", ##__VA_ARGS__) ++ ++static uint32_t dma_size; ++static void *dma_vaddr; ++static u32 dma_align __initdata; ++static bool eda_cmdline __initdata; ++ ++static int __init setup_eda_mem(char *str) ++{ ++ char *endp; ++ ++ dma_size = memparse(str, &endp) & PAGE_MASK; ++ if (*endp == '@') ++ dma_align = memparse(endp + 1, NULL) & PAGE_MASK; ++ eda_cmdline = true; ++ return 0; ++} ++early_param("eda_mem", setup_eda_mem); ++ ++static int __init of_eda_init(uint32_t *size, u32 *align) ++#ifdef CONFIG_OF_FLATTREE ++{ ++ int rc = -ENODEV; ++ struct device_node *np = NULL; ++ const u32 *region_sz_p = NULL; ++ const u32 *align_p = NULL; ++ u32 prop_sz = 0; ++ ++ eda_debug("entry"); ++ ++ /* is a programming error make it really painful so it gets fixed */ ++ BUG_ON(NULL == size || NULL == align); ++ ++ np = of_find_compatible_node(NULL, NULL, "early-dma-alloc"); ++ if (!np) { ++ printk(KERN_WARNING "WARN: Can not find `early-dma-alloc'" ++ " device tree node.\n"); ++ goto cleanup; ++ } ++ ++ region_sz_p = of_get_property(np, "region_size", &prop_sz); ++ if (!region_sz_p || (prop_sz != sizeof(*region_sz_p))) { ++ printk(KERN_ERR "ERROR: Can not find `region_size' property" ++ " in early-dma-alloc device tree node.\n"); ++ goto cleanup; ++ } ++ *size = *region_sz_p; ++ ++ align_p = of_get_property(np, "alignment", &prop_sz); ++ if (!align_p || (prop_sz != sizeof(*align_p))) { ++ printk(KERN_ERR "ERROR: Can not find `alignment' property in" ++ "early-dma-alloc device tree node.\n"); ++ goto cleanup; ++ } ++ *align = *align_p; ++ rc = 0; ++ ++ eda_debug("cleanup"); ++ ++cleanup: ++ of_node_put(np); ++ return rc; ++ ++} ++#else ++{ ++ return -ENODEV; ++} ++#endif ++ ++int eda_dma_info_get(void **vaddr, uint32_t *paddr, uint32_t *size) ++{ ++ eda_debug("entry"); ++ ++ if (!dma_vaddr) ++ return -ENOMEM; ++ ++ if (!vaddr || !paddr || !size) ++ return -EINVAL; ++ ++ *vaddr = dma_vaddr; ++ *paddr = (uint32_t) virt_to_phys(dma_vaddr); ++ *size = dma_size; ++ ++ eda_debug("returning -- dma_vaddr: 0x%pK, dma_paddr: 0x%08x," ++ " size: 0x%08x", *vaddr, *paddr, *size); ++ ++ return 0; ++} ++EXPORT_SYMBOL(eda_dma_info_get); ++ ++int __init eda_init(void) ++{ ++ int rc = 0; ++ ++ if (eda_cmdline) { ++ if (!dma_align) ++ dma_align = CONFIG_EDA_DEF_ALIGN; ++ if (!dma_size) ++ dma_size = CONFIG_EDA_DEF_SIZE; ++ eda_debug("size & alignment came from: kernel cmdline"); ++ } else if (!of_eda_init(&dma_size, &dma_align)) { ++ eda_debug("size & alignment came from: open firmware entry"); ++ } else { ++ dma_align = CONFIG_EDA_DEF_ALIGN; ++ dma_size = CONFIG_EDA_DEF_SIZE; ++ eda_debug("size & alignment came from: compiled in defaults"); ++ } ++ ++ dma_vaddr = __alloc_bootmem_low(dma_size, dma_align, 0); ++ /* ++ * enforce EDA's requirement to allocate the memory region below a ++ * 32-bit limit. ++ */ ++ if (virt_to_phys(dma_vaddr) > 0xFFFFFFFFULL) { ++ rc = -ENOMEM; ++ printk(KERN_ERR "ERROR: DMA memory beyond 32-bit address" ++ " space not supported.\n"); ++ goto cleanup; ++ } ++ ++ eda_info("dma_vaddr: 0x%pK, dma_paddr: 0x%016llx, size: 0x%08x," ++ " alignment: 0x%08x", ++ dma_vaddr, (unsigned long long) virt_to_phys(dma_vaddr), ++ dma_size, dma_align); ++cleanup: ++ if (rc && dma_vaddr) { ++ free_bootmem((unsigned long) dma_vaddr, dma_size); ++ } ++ if (rc) { ++ dma_vaddr = NULL; ++ dma_size = 0; ++ } ++ return rc; ++} ++EXPORT_SYMBOL(eda_init); +diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig +index 701edf6..7c7b208 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch new file mode 100644 index 00000000..f740b763 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Kconfig.patch @@ -0,0 +1,38 @@ +--- a/drivers/misc/eeprom/Kconfig ++++ b/drivers/misc/eeprom/Kconfig +@@ -1,5 +1,16 @@ + menu "EEPROM support" + ++config EEPROM_CLASS ++ tristate "EEPROM Hardware Class support" ++ depends on SYSFS ++ default y ++ help ++ Creates a hardware class in sysfs called "eeprom_dev", ++ providing a common place to register EEPROM devices. ++ ++ This support can also be built as a module. If so, the module ++ will be called eeprom_class. ++ + config EEPROM_AT24 + tristate "I2C EEPROMs from most vendors" + depends on I2C && SYSFS +@@ -95,4 +106,16 @@ config EEPROM_DIGSY_MTC_CFG + + If unsure, say N. + ++config EEPROM_SFF_8436 ++ tristate "SFF-8436 QSFP EEPROMs support" ++ depends on I2C && SYSFS ++ help ++ If you say yes here you get read-only support for the EEPROM of ++ the QSFPs which are implemented as per SFF-8436. ++ ++ All other features of this chip should be accessed via i2c-dev. ++ ++ This driver can also be built as a module. If so, the module ++ will be called sff_8436. ++ + endmenu +diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile +index fc1e81d..9edd559 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch new file mode 100644 index 00000000..fbd3a616 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_Makefile.patch @@ -0,0 +1,14 @@ +--- a/drivers/misc/eeprom/Makefile ++++ b/drivers/misc/eeprom/Makefile +@@ -1,3 +1,4 @@ ++obj-$(CONFIG_EEPROM_CLASS) += eeprom_class.o + obj-$(CONFIG_EEPROM_AT24) += at24.o + obj-$(CONFIG_EEPROM_AT25) += at25.o + obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o +@@ -5,3 +6,4 @@ obj-$(CONFIG_EEPROM_MAX6875) += max6875.o + obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o + obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o + obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o ++obj-$(CONFIG_EEPROM_SFF_8436) += sff_8436_eeprom.o +diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c +index ab1ad41..67f4e6f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch new file mode 100644 index 00000000..4065e220 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_at24.c.patch @@ -0,0 +1,205 @@ +--- a/drivers/misc/eeprom/at24.c ++++ b/drivers/misc/eeprom/at24.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + /* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. +@@ -68,6 +69,8 @@ struct at24_data { + unsigned write_max; + unsigned num_addresses; + ++ struct eeprom_device *eeprom_dev; ++ + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. +@@ -192,7 +195,8 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: +- count = 2; ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; +@@ -237,12 +241,20 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; +- buf[1] = status >> 8; ++ if (count == 2) ++ buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: +- status = i2c_smbus_read_byte_data(client, offset); ++ if (at24->chip.flags & AT24_FLAG_ADDR16) { ++ status = i2c_smbus_write_byte_data(client, (offset >> 8) & 0xff, offset & 0xff); ++ if (status >= 0) { ++ status = i2c_smbus_read_byte(client); ++ } ++ } else { ++ status = i2c_smbus_read_byte_data(client, offset); ++ } + if (status >= 0) { + buf[0] = status; + status = count; +@@ -327,6 +339,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; ++ int i = 0; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); +@@ -340,10 +353,22 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + if (offset + count > next_page) + count = next_page - offset; + +- /* If we'll use I2C calls for I/O, set up the message */ +- if (!at24->use_smbus) { +- int i = 0; + ++ switch (at24->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /* Smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + +@@ -355,6 +380,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; ++ break; + } + + /* +@@ -365,15 +391,40 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; +- if (at24->use_smbus) { ++ switch (at24->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; +- } else { ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ if (count == 2) { ++ status = i2c_smbus_write_word_data( ++ client,offset,(u16)((buf[0]) | ++ (buf[1] << 8))); ++ } else { ++ /* count = 1 */ ++ status = i2c_smbus_write_byte_data( ++ client, offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ if (at24->chip.flags & AT24_FLAG_ADDR16) { ++ status = i2c_smbus_write_word_data(client, (offset >> 8) & 0xff, buf[0] << 8 | (offset & 0xff)); ++ } else { ++ status = i2c_smbus_write_byte_data(client, offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; ++ break; + } + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); +@@ -512,6 +563,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + + chip.setup = NULL; + chip.context = NULL; ++ chip.eeprom_data = NULL; + } + + if (!is_power_of_2(chip.byte_len)) +@@ -529,11 +581,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (chip.flags & AT24_FLAG_ADDR16) { +- err = -EPFNOSUPPORT; +- goto err_out; +- } +- if (i2c_check_functionality(client->adapter, +- I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { ++ use_smbus = I2C_SMBUS_BYTE_DATA; ++ } else if (!(chip.flags & AT24_FLAG_DISABLE_I2CBLOCK) && ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK))) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { +@@ -579,9 +630,14 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { +- if (!use_smbus || i2c_check_functionality(client->adapter, +- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { +- ++ if (!use_smbus || ++ (!(chip.flags & AT24_FLAG_DISABLE_I2CBLOCK) && ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_WORD_DATA) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + unsigned write_max = chip.page_size; + + at24->macc.write = at24_macc_write; +@@ -625,6 +681,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) + if (err) + goto err_clients; + ++ at24->eeprom_dev = eeprom_device_register(&client->dev, chip.eeprom_data); ++ if (IS_ERR(at24->eeprom_dev)) { ++ dev_err(&client->dev, "error registering eeprom device.\n"); ++ err = PTR_ERR(at24->eeprom_dev); ++ goto err_clients; ++ } ++ + i2c_set_clientdata(client, at24); + + dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n", +@@ -667,6 +730,8 @@ static int __devexit at24_remove(struct i2c_client *client) + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + ++ eeprom_device_unregister(at24->eeprom_dev); ++ + kfree(at24->writebuf); + kfree(at24); + return 0; +diff --git a/drivers/misc/eeprom/eeprom_class.c b/drivers/misc/eeprom/eeprom_class.c +new file mode 100644 +index 0000000..e01a81a diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch new file mode 100644 index 00000000..79e59f45 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_eeprom_class.c.patch @@ -0,0 +1,200 @@ +--- /dev/null ++++ b/drivers/misc/eeprom/eeprom_class.c +@@ -0,0 +1,194 @@ ++/* ++ * eeprom_class.c ++ * ++ * This file defines the sysfs class "eeprom", for use by EEPROM ++ * drivers. ++ * ++ * Copyright (C) 2013 Cumulus Networks, Inc. ++ * Author: Curt Brune ++ * ++ * Ideas and structure graciously borrowed from the hwmon class: ++ * Copyright (C) 2005 Mark M. Hoffman ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Root eeprom "class" object (corresponds to '//class/eeprom_dev/') */ ++static struct class *eeprom_class; ++ ++#define EEPROM_CLASS_NAME "eeprom_dev" ++#define EEPROM_ID_PREFIX "eeprom" ++#define EEPROM_ID_FORMAT EEPROM_ID_PREFIX "%d" ++ ++static DEFINE_IDA(eeprom_ida); ++ ++/** ++ * eeprom_device_register - register w/ eeprom class ++ * @dev: the device to register ++ * @data: platform data to use for the device ++ * ++ * eeprom_device_unregister() must be called when the device is no ++ * longer needed. ++ * ++ * Creates a new eeprom class device that is a child of @dev. Also ++ * creates a symlink in //class/eeprom_dev/eeprom[N] pointing ++ * to the new device. ++ * ++ * Returns the pointer to the new device. ++ */ ++struct eeprom_device *eeprom_device_register(struct device *dev, struct eeprom_platform_data *data) ++{ ++ struct eeprom_device *eeprom_dev; ++ int id; ++ int ret; ++ ++ id = ida_simple_get(&eeprom_ida, 0, 0, GFP_KERNEL); ++ if (id < 0) ++ return ERR_PTR(id); ++ ++ eeprom_dev = kzalloc(sizeof(struct eeprom_device), GFP_KERNEL); ++ if (!eeprom_dev) { ++ ret = -ENOMEM; ++ goto err_ida; ++ } ++ ++ eeprom_dev->dev = device_create(eeprom_class, dev, MKDEV(0, 0), ++ eeprom_dev, EEPROM_ID_FORMAT, id); ++ if (IS_ERR(eeprom_dev->dev)) { ++ ret = PTR_ERR(eeprom_dev->dev); ++ goto err_eeprom_dev_free; ++ } ++ ++ eeprom_dev->data = data; ++ ++ return eeprom_dev; ++ ++err_eeprom_dev_free: ++ kfree(eeprom_dev); ++ ++err_ida: ++ ida_simple_remove(&eeprom_ida, id); ++ return ERR_PTR(ret); ++} ++ ++/** ++ * eeprom_device_unregister - removes the previously registered class device ++ * ++ * @eeprom: the eeprom class device to destroy ++ */ ++void eeprom_device_unregister(struct eeprom_device *eeprom_dev) ++{ ++ int id; ++ ++ if (likely(sscanf(dev_name(eeprom_dev->dev), EEPROM_ID_FORMAT, &id) == 1)) { ++ device_unregister(eeprom_dev->dev); ++ kfree(eeprom_dev); ++ ida_simple_remove(&eeprom_ida, id); ++ } else ++ dev_dbg(eeprom_dev->dev->parent, ++ "eeprom_device_unregister() failed: bad class ID!\n"); ++} ++ ++/** ++ * Each member of the eeprom class exports a sysfs file called ++ * "label", containing the label property from the corresponding ++ * device tree node. ++ * ++ * Userspace can use the label to identify what the EEPROM is for. ++ */ ++static ssize_t label_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct eeprom_device *eeprom_dev = (struct eeprom_device *)dev_get_drvdata(dev); ++ const char* cp = NULL; ++ int len = 0; ++ ++ /* Check if the eeprom device has an explicit label: ++ * - explicitly passed in to eeprom_device_register() ++ * - explicitly passed via the device tree node ++ * ++ * Otherwise use "unknown". ++ */ ++ if (eeprom_dev->data && eeprom_dev->data->label) { ++ cp = eeprom_dev->data->label; ++ len = strlen(cp) + 1; ++ } else { ++ /* ++ * Check for a device tree property. ++ * ++ * The class device is a child of the original device, ++ * i.e. dev->parent points to the original device. ++ */ ++ if (dev->parent && dev->parent->of_node) ++ cp = of_get_property(dev->parent->of_node, "label", &len); ++ } ++ ++ if ((cp == NULL) || (len == 0)) { ++ cp = "unknown"; ++ len = strlen(cp) + 1; ++ } ++ ++ strncpy(buf, cp, len - 1); ++ buf[len - 1] = '\n'; ++ buf[len] = '\0'; ++ ++ return len; ++} ++ ++struct device_attribute eeprom_class_dev_attrs[] = { ++ __ATTR_RO(label), ++ __ATTR_NULL, ++}; ++ ++static int __init eeprom_init(void) ++{ ++ eeprom_class = class_create(THIS_MODULE, EEPROM_CLASS_NAME); ++ if (IS_ERR(eeprom_class)) { ++ pr_err("couldn't create sysfs class\n"); ++ return PTR_ERR(eeprom_class); ++ } ++ ++ eeprom_class->dev_attrs = eeprom_class_dev_attrs; ++ ++ return 0; ++} ++ ++static void __exit eeprom_exit(void) ++{ ++ class_destroy(eeprom_class); ++} ++ ++subsys_initcall(eeprom_init); ++module_exit(eeprom_exit); ++ ++EXPORT_SYMBOL_GPL(eeprom_device_register); ++EXPORT_SYMBOL_GPL(eeprom_device_unregister); ++ ++MODULE_AUTHOR("Curt Brune "); ++MODULE_DESCRIPTION("eeprom sysfs/class support"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/misc/eeprom/sff_8436_eeprom.c b/drivers/misc/eeprom/sff_8436_eeprom.c +new file mode 100644 +index 0000000..f6cc6e2 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch new file mode 100644 index 00000000..51e87f65 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_eeprom_sff_8436_eeprom.c.patch @@ -0,0 +1,1231 @@ +--- /dev/null ++++ b/drivers/misc/eeprom/sff_8436_eeprom.c +@@ -0,0 +1,1226 @@ ++/* ++ * sff_8436_eeprom.c - handle most SFF-8436 based QSFP EEPROMs ++ * ++ * Copyright (C) 2014 Cumulus networks Inc. ++ * ++ * 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 Freeoftware Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++/* ++ * Description: ++ * a) SFF 8436 based qsfp read/write transactions are just like the at24 eeproms ++ * b) The register/memory layout is up to 5 128 byte pages defined by a "pages valid" ++ * register and switched via a "page select" register as explained in below diagram. ++ * c) 256 bytes are mapped at a time. page 0 is always mapped to the first 128 bytes and ++ * the other 4 pages are selectively mapped to the second 128 bytes ++ * ++ * SFF 8436 based QSFP Memory Map ++ * ++ * 2-Wire Serial Address: 1010000x ++ * ++ * Lower Page 00h (128 bytes) ++ * ===================== ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * |Page Select Byte(127)| ++ * ===================== ++ * | ++ * | ++ * | ++ * | ++ * V ++ * ----------------------------------------------------------------- ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * V V V V ++ * ------------- ---------------- ----------------- -------------- ++ * | | | | | | | | ++ * | Upper | | Upper | | Upper | | Upper | ++ * | Page 00h | | Page 01h | | Page 02h | | Page 03h | ++ * | | | (Optional) | | (Optional) | | (Optional | ++ * | | | | | | | for Cable | ++ * | | | | | | | Assemblies) | ++ * | ID | | AST | | User | | | ++ * | Fields | | Table | | EEPROM Data | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * ------------- ---------------- ----------------- -------------- ++ * ++ * ++ **/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define SFF_8436_EEPROM_SIZE (5*128) ++#define SFF_8436_MAX_PAGE_COUNT 5 ++#define SFF_8436_MMAP_SIZE 256 ++#define SFF_8436_PAGE_SELECT_REG 0x7F ++ ++#define SFF_8436_OPTION_4_OFFSET 0xC3 ++#define SFF_8436_PAGE_02_PRESENT (1 << 7) /* Memory Page 02 present */ ++#define SFF_8436_PAGE_01_PRESENT (1 << 6) /* Memory Page 01 present */ ++#define SFF_8436_STATUS_2_OFFSET 0x02 ++#define SFF_8436_STATUS_PAGE_03_PRESENT_L (1 << 2) /* Flat Memory:0- Paging, 1- Page 0 only */ ++ ++#define SFF_ID_OFFSET 0x00 ++#define SFF_ID_LEN 1 ++#define SFF_ID_SFP 0x03 ++#define SFF_ID_QSFP_PLUS 0x0d ++#define SFF_ID_QSFP28 0x11 ++#define SFF_8472_EEPROM_SIZE (4*128) ++ ++struct sff_8436_data { ++ struct sff_8436_platform_data chip; ++ struct memory_accessor macc; ++ int use_smbus; ++ ++ /* ++ * Lock protects against activities from other Linux tasks, ++ * but not from changes by other I2C masters. ++ */ ++ struct mutex lock; ++ struct bin_attribute bin; ++ struct attribute_group attr_group; ++ ++ u8 *writebuf; ++ unsigned write_max; ++ ++ unsigned num_addresses; ++ ++ u8 data[SFF_8436_EEPROM_SIZE]; ++ struct eeprom_device *eeprom_dev; ++ ++ /* Config variable to support SFF-8472/SFP+ standard */ ++ int sfp_compat; ++ ++ struct i2c_client *client[]; ++}; ++ ++typedef enum qsfp_opcode { ++ QSFP_READ_OP = 0, ++ QSFP_WRITE_OP = 1 ++} qsfp_opcode_e; ++ ++/* ++ * This parameter is to help this driver avoid blocking other drivers out ++ * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C ++ * clock, one 256 byte read takes about 1/43 second which is excessive; ++ * but the 1/170 second it takes at 400 kHz may be quite reasonable; and ++ * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. ++ * ++ * This value is forced to be a power of two so that writes align on pages. ++ */ ++static unsigned io_limit = 128; ++ ++/* ++ *pecs often allow 5 msec for a page write, sometimes 20 msec; ++ * it's important to recover from write timeouts. ++ */ ++static unsigned write_timeout = 25; ++ ++#define SFF_8436_PAGE_SIZE 128 ++#define SFF_8436_SIZE_BYTELEN 5 ++#define SFF_8436_SIZE_FLAGS 8 ++ ++#define SFF_8436_BITMASK(x) (BIT(x) - 1) ++ ++ ++/* create non-zero magic value for given eeprom parameters */ ++#define SFF_8436_DEVICE_MAGIC(_len, _flags) \ ++ ((1 << SFF_8436_SIZE_FLAGS | (_flags)) \ ++ << SFF_8436_SIZE_BYTELEN | ilog2(_len)) ++ ++static const struct i2c_device_id sff8436_ids[] = { ++ { "sff8436",SFF_8436_DEVICE_MAGIC(2048 / 8, 0) }, ++ { /* END OF LIST */ } ++}; ++MODULE_DEVICE_TABLE(i2c, sff8436_ids); ++ ++/*-------------------------------------------------------------------------*/ ++/* ++ * This routine computes the addressing information to be used for a given r/w request. ++ * Assumes that sanity checks for offset happened at sysfs-layer. ++ * Offset within Lower Page 00h and Upper Page 00h are not recomputed ++ */ ++static uint8_t sff_8436_translate_offset(struct sff_8436_data *sff_8436, ++ loff_t *offset) ++{ ++ unsigned page = 0; ++ ++ if (*offset < SFF_8436_MMAP_SIZE) { ++ return 0; ++ } ++ ++ page = (*offset >> 7)-1; ++ ++ if (page > 0 ) { ++ *offset = 0x80 + (*offset & 0x7f); ++ } else { ++ *offset &= 0xff; ++ } ++ ++ return page; ++} ++ ++static int sff_8436_read_reg(struct sff_8436_data *sff_8436, ++ uint8_t reg, uint8_t *val) ++{ ++ int count = 1, i = 0; ++ struct i2c_client *client = sff_8436->client[0]; ++ struct i2c_msg msg[2]; ++ u8 msgbuf[2]; ++ ssize_t status; ++ unsigned long timeout, read_time; ++ ++ memset(msg, 0, sizeof(msg)); ++ ++ /* ++ * Writes fail if the previous one didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ read_time = jiffies; ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_read_i2c_block_data(client, ++ reg, count, val); ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ status = i2c_smbus_read_word_data(client, reg); ++ ++ if (status >= 0) { ++ *val = status & 0xff; ++ status = count; ++ } ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_read_byte_data(client, reg); ++ ++ if (status >= 0) { ++ *val = status; ++ status = count; ++ } ++ break; ++ ++ default: ++ i = 0; ++ msgbuf[i++] = reg; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = i; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = val; ++ msg[1].len = count; ++ ++ status = i2c_transfer(client->adapter, msg, 2); ++ if (status == 2) ++ status = count; ++ break; ++ } ++ dev_dbg(&client->dev, "read (using smbus %d) %d@%d --> %zd (%ld)\n", ++ sff_8436->use_smbus, count, reg, status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(read_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int sff_8436_write_reg(struct sff_8436_data *sff_8436, ++ uint8_t reg, uint8_t val) ++{ ++ uint8_t data[2] = { reg, val }; ++ int count = 1; ++ struct i2c_client *client = sff_8436->client[0]; ++ struct i2c_msg msg; ++ ssize_t status; ++ unsigned long timeout, write_time; ++ ++ /* ++ * Writes fail if the previous one didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ write_time = jiffies; ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_write_i2c_block_data(client, ++ reg, count, &val); ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_write_byte_data(client, reg, val); ++ ++ if (status == 0) ++ status = count; ++ break; ++ default: ++ msg.addr = client->addr; ++ msg.flags = 0; ++ msg.len = sizeof(data); ++ msg.buf = (char *) data; ++ ++ status = i2c_transfer(client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ break; ++ } ++ dev_dbg(&client->dev, "write (using smbus %d) %d@%d --> %zd (%ld)\n", ++ sff_8436->use_smbus, count, reg, status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(write_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int sff_8436_write_page_reg(struct sff_8436_data *sff_8436, ++ uint8_t val) ++{ ++ return sff_8436_write_reg(sff_8436, SFF_8436_PAGE_SELECT_REG, val); ++} ++ ++static ssize_t sff_8436_eeprom_read(struct sff_8436_data *sff_8436, ++ struct i2c_client *client, char *buf, ++ unsigned offset, size_t count) ++{ ++ struct i2c_msg msg[2]; ++ u8 msgbuf[2]; ++ unsigned long timeout, read_time; ++ int status, i; ++ ++ memset(msg, 0, sizeof(msg)); ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* ++ * When we have a better choice than SMBus calls, use a ++ * combined I2C message. Write address; then read up to ++ * io_limit data bytes. Note that read page rollover helps us ++ * here (unlike writes). msgbuf is u8 and will cast to our ++ * needs. ++ */ ++ i = 0; ++ msgbuf[i++] = offset; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = i; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = buf; ++ msg[1].len = count; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ read_time = jiffies; ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_read_i2c_block_data(client, offset, ++ count, buf); ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ status = i2c_smbus_read_word_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status & 0xff; ++ if (count == 2) ++ buf[1] = status >> 8; ++ status = count; ++ } ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_read_byte_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status; ++ status = count; ++ } ++ break; ++ default: ++ status = i2c_transfer(client->adapter, msg, 2); ++ if (status == 2) ++ status = count; ++ } ++ ++ dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", ++ count, offset, status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(read_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static ssize_t sff_8436_eeprom_write(struct sff_8436_data *sff_8436, ++ struct i2c_client *client, const char *buf, ++ unsigned offset, size_t count) ++{ ++ struct i2c_msg msg; ++ ssize_t status; ++ unsigned long timeout, write_time; ++ unsigned next_page; ++ int i = 0; ++ ++ /* write max is at most a page */ ++ if (count > sff_8436->write_max) ++ count = sff_8436->write_max; ++ ++ /* Never roll over backwards, to the start of this page */ ++ next_page = roundup(offset + 1, SFF_8436_PAGE_SIZE); ++ if (offset + count > next_page) ++ count = next_page - offset; ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* If we'll use I2C calls for I/O, set up the message */ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ ++ /* msg.buf is u8 and casts will mask the values */ ++ msg.buf = sff_8436->writebuf; ++ ++ msg.buf[i++] = offset; ++ memcpy(&msg.buf[i], buf, count); ++ msg.len = i + count; ++ break; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ write_time = jiffies; ++ ++ switch (sff_8436->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_write_i2c_block_data(client, ++ offset, count, buf); ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ if (count == 2) { ++ status = i2c_smbus_write_word_data( ++ client,offset,(u16)((buf[0]) | ++ (buf[1] << 8))); ++ } else { ++ /* count = 1 */ ++ status = i2c_smbus_write_byte_data( ++ client, offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_write_byte_data(client, offset, buf[0]); ++ if (status == 0) ++ status = count; ++ break; ++ default: ++ status = i2c_transfer(client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ break; ++ } ++ ++ dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", ++ count, offset, (long int) status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ msleep(1); ++ } while (time_before(write_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static ssize_t sff_8436_eeprom_update_client(struct sff_8436_data *sff_8436, ++ loff_t off, size_t count, qsfp_opcode_e opcode) ++{ ++ struct i2c_client *client = sff_8436->client[0]; ++ ssize_t retval = 0; ++ u8 page = 0; ++ loff_t phy_offset = off; ++ int ret = 0; ++ ++ page = sff_8436_translate_offset(sff_8436, &phy_offset); ++ ++ dev_dbg(&client->dev, ++ "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", ++ off, page, phy_offset, (long int) count, opcode); ++ if (page > 0) { ++ ret = sff_8436_write_page_reg(sff_8436, page); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "sff_8436_write_page_reg for page %d failed ret:%d!\n", ++ page, ret); ++ return ret; ++ } ++ } ++ ++ while (count) { ++ ssize_t status; ++ ++ if (opcode == QSFP_READ_OP) { ++ status = sff_8436_eeprom_read(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } else { ++ status = sff_8436_eeprom_write(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } ++ if (status <= 0) { ++ if (retval == 0) ++ retval = status; ++ break; ++ } ++ phy_offset += status; ++ off += status; ++ count -= status; ++ retval += status; ++ } ++ ++ ++ if (page > 0) { ++ ret = sff_8436_write_page_reg(sff_8436, 0); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "sff_8436_write_page_reg for page 0 failed ret:%d!\n", ret); ++ return ret; ++ } ++ } ++ return retval; ++} ++ ++/* ++ * API to return whether pluggable module is SFP+ or QSFP ++ */ ++int get_module_id (struct sff_8436_data *sff_8436) ++{ ++ struct i2c_client *client = sff_8436->client[0]; ++ int ret; ++ u8 mod_id = 0; ++ ++ mutex_lock(&sff_8436->lock); ++ ++ ret = sff_8436_read_reg(sff_8436, SFF_ID_OFFSET, &mod_id); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 00h status failed %d!\n", ret); ++ mod_id = -1; ++ } ++ ++ mutex_unlock(&sff_8436->lock); ++ ++ return mod_id; ++} ++ ++/* ++ * Mechanism to handle addresses greater than 256 by 8 bit addressing mode is ++ * by registering addresses 256-512 as another chip ++ * ++ * This routine supports chips which consume multiple I2C addresses. It ++ * computes the addressing information to be used for a given r/w request. ++ * Assumes that sanity checks for offset happened at sysfs-layer. ++ * ++ */ ++static struct i2c_client *sff_8472_translate_offset(struct sff_8436_data *sff_8436, ++ loff_t offset, loff_t *phy_offset) ++{ ++ unsigned i; ++ ++ i = offset >> 8; ++ *phy_offset = offset & 0xff; ++ ++ return sff_8436->client[i]; ++} ++ ++/* ++ * Assumption: ++ * Buffer provided and returned by this driver is ++ * of size 5x128 (QSFP eeprom size) even though ++ * SFP+ eeprom size is 4x128. ++ * ++ * Read operation: ++ * Last page -513 to 640 will be 0xff ++ * ++ * Write operation: ++ * Last page : 513 to 640 will be ignored ++ * ++ */ ++ ++static ssize_t sff_8472_read_write(struct sff_8436_data *sff_8436, ++ loff_t off, size_t count, qsfp_opcode_e opcode) ++{ ++ struct i2c_client *client; ++ ssize_t retval = 0; ++ ++ if (unlikely(!count)) ++ return count; ++ ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&sff_8436->lock); ++ ++ while (count) { ++ ssize_t status; ++ loff_t phy_offset = 0; ++ ++ client = sff_8472_translate_offset(sff_8436, off, &phy_offset); ++ dev_dbg(&client->dev, ++ "sff_8472_read_write off %lld offset:%lld, count:%ld, phy_offset:%lld\n", ++ off, off, (long int) count, phy_offset); ++ ++ if (opcode == QSFP_READ_OP) { ++ status = sff_8436_eeprom_read(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } else { ++ status = sff_8436_eeprom_write(sff_8436, client, ++ (char *)(&sff_8436->data[off]), phy_offset, count); ++ } ++ ++ if (status <= 0) { ++ if (retval == 0) ++ retval = status; ++ break; ++ } ++ off += status; ++ phy_offset += status; ++ count -= status; ++ retval += status; ++ } ++ ++ mutex_unlock(&sff_8436->lock); ++ ++ ++ return retval; ++} ++ ++static ssize_t sff_8436_read_write(struct sff_8436_data *sff_8436, ++ char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) ++{ ++ struct i2c_client *client = sff_8436->client[0]; ++ u8 page; ++ u8 refresh_page = 0; ++ int ret = 0; ++ u8 val = 0; ++ u8 mod_id = 0; ++ int err_timeout = 0; ++ size_t pending_len = 0, page_len = 0; ++ loff_t page_offset = 0, page_start_offset = 0; ++ size_t max_eeprom_size = SFF_8436_EEPROM_SIZE; ++ ++ if (unlikely(!len)) ++ return len; ++ ++ ++ if (sff_8436->sfp_compat) { ++ mod_id = get_module_id(sff_8436); ++ ++ if (mod_id == SFF_ID_SFP) { ++ max_eeprom_size = SFF_8472_EEPROM_SIZE; ++ } ++ } ++ ++ if (off > max_eeprom_size) ++ return 0; ++ ++ if (off + len > max_eeprom_size) ++ len = max_eeprom_size - off; ++ ++ memset(sff_8436->data, 0xff, SFF_8436_EEPROM_SIZE); ++ ++ if (opcode == QSFP_WRITE_OP) { ++ memcpy(&sff_8436->data[off], buf, len); ++ } ++ ++ if (sff_8436->sfp_compat) { ++ ++ dev_dbg(&client->dev, ++ "Module ID: %d, offset:%lld , len:%ld!\n", mod_id, off, len); ++ ++ if (mod_id == SFF_ID_SFP) { ++ ret = sff_8472_read_write(sff_8436, off, len, opcode); ++ ++ if (opcode == QSFP_READ_OP) { ++ memcpy(buf, &sff_8436->data[off], len); ++ } ++ return (ret); ++ } ++ } ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&sff_8436->lock); ++ ++ /* ++ * Refresh pages which covers the requested data ++ * from offset to off + len ++ * Only refresh pages which contain requested bytes ++ * ++ */ ++ ++ pending_len = len; ++ ++ for (page = off >> 7; page <= (off + len - 1) >> 7; page++) { ++ refresh_page = 0; ++ switch (page) { ++ case 0: ++ /* Lower page 00h */ ++ refresh_page = 1; ++ err_timeout = 1; ++ break; ++ case 1: ++ /* Upper page 00h */ ++ refresh_page = 1; ++ err_timeout = 1; ++ break; ++ case 2: ++ /* Upper page 01h */ ++ ret = sff_8436_read_reg(sff_8436, SFF_8436_OPTION_4_OFFSET, &val); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 01h status failed %d!\n", ret); ++ goto err; ++ } ++ if (val & SFF_8436_PAGE_01_PRESENT) { ++ refresh_page = 1; ++ } ++ break; ++ case 3: ++ /* Upper page 02h */ ++ ret = sff_8436_read_reg(sff_8436, SFF_8436_OPTION_4_OFFSET, &val); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 02h status failed %d!\n", ret); ++ goto err; ++ } ++ if (val & SFF_8436_PAGE_02_PRESENT) { ++ refresh_page = 1; ++ } ++ break; ++ case 4: ++ /* Upper page 03h */ ++ ret = sff_8436_read_reg(sff_8436, SFF_8436_STATUS_2_OFFSET, &val); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "sff_8436_read_reg for page 03h status failed %d!\n", ret); ++ goto err; ++ } ++ if (!(val & SFF_8436_STATUS_PAGE_03_PRESENT_L)) { ++ refresh_page = 1; ++ } ++ break; ++ default: ++ /* Invalid page index */ ++ dev_err(&client->dev, "Invalid page %d!\n", page); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ if (!refresh_page) { ++ /* if page is not valid or already refreshed */ ++ continue; ++ } ++ ++ /* ++ * Compute the offset and number of bytes to be read/write ++ * w.r.t requested page ++ * ++ * 1. start at offset 0 (within the page), and read/write the entire page ++ * 2. start at offset 0 (within the page) and read/write less than entire page ++ * 3. start at an offset not equal to 0 and read/write the rest of the page ++ * 4. start at an offset not equal to 0 and read/write less than (end of page - offset) ++ * ++ */ ++ page_start_offset = page * SFF_8436_PAGE_SIZE; ++ ++ if (page_start_offset < off) { ++ page_offset = off; ++ if (off + pending_len < page_start_offset + SFF_8436_PAGE_SIZE) { ++ page_len = pending_len; ++ } else { ++ page_len = SFF_8436_PAGE_SIZE - off; ++ } ++ } else { ++ page_offset = page_start_offset; ++ if (pending_len > SFF_8436_PAGE_SIZE) { ++ page_len = SFF_8436_PAGE_SIZE; ++ } else { ++ page_len = pending_len; ++ } ++ } ++ ++ pending_len = pending_len - page_len; ++ ++ dev_dbg(&client->dev, ++ "sff_read off %lld len %ld page_start_offset %lld page_offset %lld page_len %ld pending_len %ld\n", ++ off, (long int) len, page_start_offset, page_offset, (long int) page_len, (long int) pending_len); ++ ++ /* Refresh the data from offset for specified len */ ++ ret = sff_8436_eeprom_update_client(sff_8436, page_offset, page_len, opcode); ++ if (ret != page_len) { ++ if (err_timeout) { ++ dev_dbg(&client->dev, "sff_8436_update_client for %s page %d page_offset %lld page_len %ld failed %d!\n", ++ (page ? "Upper" : "Lower"), (page ? (page-1) : page), page_offset, (long int) page_len, ret); ++ goto err; ++ } else { ++ dev_err(&client->dev, "sff_8436_update_client for %s page %d page_offset %lld page_len %ld failed %d!\n", ++ (page ? "Upper" : "Lower"), (page ? (page-1) : page), page_offset, (long int) page_len, ret); ++ } ++ } ++ } ++ mutex_unlock(&sff_8436->lock); ++ ++ if (opcode == QSFP_READ_OP) { ++ memcpy(buf, &sff_8436->data[off], len); ++ } ++ return len; ++ ++err: ++ mutex_unlock(&sff_8436->lock); ++ ++ return ret; ++} ++ ++static ssize_t sff_8436_bin_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ ++ return sff_8436_read_write(sff_8436, buf, off, count, QSFP_READ_OP); ++} ++ ++ ++static ssize_t sff_8436_bin_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ ++ return sff_8436_read_write(sff_8436, buf, off, count, QSFP_WRITE_OP); ++} ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * This lets other kernel code access the eeprom data. For example, it ++ * might hold a board's Ethernet address, or board-specific calibration ++ * data generated on the manufacturing floor. ++ */ ++ ++static ssize_t sff_8436_macc_read(struct memory_accessor *macc, char *buf, ++ off_t offset, size_t count) ++{ ++ struct sff_8436_data *sff_8436 = container_of(macc, struct sff_8436_data, macc); ++ ++ return sff_8436_read_write(sff_8436, buf, offset, count, QSFP_READ_OP); ++} ++ ++static ssize_t sff_8436_macc_write(struct memory_accessor *macc, const char *buf, ++ off_t offset, size_t count) ++{ ++ struct sff_8436_data *sff_8436 = container_of(macc, struct sff_8436_data, macc); ++ ++ return sff_8436_read_write(sff_8436, (char *) buf, offset, count, QSFP_WRITE_OP); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int __devexit sff_8436_remove(struct i2c_client *client) ++{ ++ struct sff_8436_data *sff_8436; ++ int i; ++ ++ sff_8436 = i2c_get_clientdata(client); ++ sysfs_remove_group(&client->dev.kobj, &sff_8436->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &sff_8436->bin); ++ ++ for (i = 1; i < sff_8436->num_addresses; i++) ++ i2c_unregister_device(sff_8436->client[i]); ++ ++ eeprom_device_unregister(sff_8436->eeprom_dev); ++ ++ kfree(sff_8436->writebuf); ++ kfree(sff_8436); ++ return 0; ++} ++ ++static ssize_t show_sfp_compat(struct device *dev, ++ struct device_attribute *dattr, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ ssize_t count; ++ ++ mutex_lock(&sff_8436->lock); ++ count = sprintf(buf, "%d\n", sff_8436->sfp_compat); ++ mutex_unlock(&sff_8436->lock); ++ ++ return count; ++} ++ ++static ssize_t set_sfp_compat(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sff_8436_data *sff_8436 = i2c_get_clientdata(client); ++ int sfp_compat; ++ ++ if (sscanf(buf, "%d", &sfp_compat) != 1 || ++ sfp_compat < 0 || sfp_compat > 1) ++ return -EINVAL; ++ ++ mutex_lock(&sff_8436->lock); ++ sff_8436->sfp_compat = sfp_compat; ++ mutex_unlock(&sff_8436->lock); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(sfp_compatible, S_IRUGO | S_IWUSR, show_sfp_compat, set_sfp_compat); ++ ++static struct attribute *sff_8436_attrs[] = { ++ &dev_attr_sfp_compatible.attr, ++ NULL, ++}; ++ ++static struct attribute_group sff_8436_attr_group = { ++ .attrs = sff_8436_attrs, ++}; ++ ++static int sff_8436_eeprom_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int err; ++ int use_smbus = 0; ++ struct sff_8436_platform_data chip; ++ struct sff_8436_data *sff_8436; ++ kernel_ulong_t magic; ++ int num_addresses = 0; ++ int i = 0; ++ ++ if (client->dev.platform_data) { ++ chip = *(struct sff_8436_platform_data *)client->dev.platform_data; ++ } else { ++ /* ++ * SFF-8436 MMAP is 256 bytes long ++ */ ++ magic = SFF_8436_DEVICE_MAGIC(2048 / 8, 0); ++ chip.byte_len = BIT(magic & SFF_8436_BITMASK(SFF_8436_SIZE_BYTELEN)); ++ magic >>= SFF_8436_SIZE_BYTELEN; ++ chip.flags = magic & SFF_8436_BITMASK(SFF_8436_SIZE_FLAGS); ++ /* ++ * This is slow, but we can't know all eeproms, so we better ++ * play safe.pecifying custom eeprom-types via platform_data ++ * is recommended anyhow. ++ */ ++ chip.page_size = 1; ++ ++ chip.setup = NULL; ++ chip.context = NULL; ++ chip.eeprom_data = NULL; ++ } ++ ++ if (!is_power_of_2(chip.byte_len)) ++ dev_warn(&client->dev, ++ "byte_len looks suspicious (no power of 2)!\n"); ++ ++ if (!chip.page_size) { ++ dev_err(&client->dev, "page_size must not be 0!\n"); ++ err = -EINVAL; ++ goto exit; ++ } ++ if (!is_power_of_2(chip.page_size)) ++ dev_warn(&client->dev, ++ "page_size looks suspicious (no power of 2)!\n"); ++ ++ /* Use I2C operations unless we're stuck with SMBus extensions. */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { ++ use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ use_smbus = I2C_SMBUS_WORD_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_BYTE_DATA)) { ++ use_smbus = I2C_SMBUS_BYTE_DATA; ++ } else { ++ err = -EPFNOSUPPORT; ++ goto exit; ++ } ++ } ++ ++ /* Mechanism to handle addresses greater than 256 by 8 bit addressing mode is ++ * by registering addresses 256-512 as another chip ++ */ ++ num_addresses = 2; ++ ++ if (!(sff_8436 = kzalloc(sizeof(struct sff_8436_data) + ++ num_addresses * sizeof(struct i2c_client *), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ mutex_init(&sff_8436->lock); ++ sff_8436->use_smbus = use_smbus; ++ sff_8436->chip = chip; ++ sff_8436->num_addresses = num_addresses; ++ ++ /* ++ * Export the EEPROM bytes through sysfs, since that's convenient. ++ * By default, only root should see the data (maybe passwords etc) ++ */ ++ sysfs_bin_attr_init(&sff_8436->bin); ++ sff_8436->bin.attr.name = "eeprom"; ++ sff_8436->bin.attr.mode = SFF_8436_FLAG_IRUGO; ++ sff_8436->bin.read = sff_8436_bin_read; ++ sff_8436->bin.size = SFF_8436_EEPROM_SIZE; ++ ++ sff_8436->macc.read = sff_8436_macc_read; ++ ++ if (!use_smbus || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_WORD_DATA) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { ++ //unsigned write_max = chip.page_size; ++ /* ++ * NOTE: AN-2079 ++ * Finisar recommends that the host implement 1 byte writes only, ++ * since this module only supports 32 byte page boundaries. ++ * 2 byte writes are acceptable for PE and Vout changes per ++ * Application Note AN-2071. ++ */ ++ unsigned write_max = 1; ++ ++ sff_8436->macc.write = sff_8436_macc_write; ++ ++ sff_8436->bin.write = sff_8436_bin_write; ++ sff_8436->bin.attr.mode |= S_IWUSR; ++ ++ if (write_max > io_limit) ++ write_max = io_limit; ++ if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) ++ write_max = I2C_SMBUS_BLOCK_MAX; ++ sff_8436->write_max = write_max; ++ ++ /* buffer (data + address at the beginning) */ ++ sff_8436->writebuf = kmalloc(write_max + 2, GFP_KERNEL); ++ if (!sff_8436->writebuf) { ++ err = -ENOMEM; ++ goto exit_kfree; ++ } ++ } else { ++ dev_warn(&client->dev, ++ "cannot write due to controller restrictions."); ++ } ++ ++ memset(sff_8436->data, 0xff, SFF_8436_EEPROM_SIZE); ++ ++ sff_8436->client[0] = client; ++ ++ /* use dummy devices for multiple-address chips */ ++ for (i = 1; i < num_addresses; i++) { ++ sff_8436->client[i] = i2c_new_dummy(client->adapter, ++ client->addr + i); ++ if (!sff_8436->client[i]) { ++ dev_err(&client->dev, "address 0x%02x unavailable\n", ++ client->addr + i); ++ err = -EADDRINUSE; ++ goto err_struct; ++ } ++ } ++ ++ /* create the sysfs eeprom file */ ++ err = sysfs_create_bin_file(&client->dev.kobj, &sff_8436->bin); ++ if (err) ++ goto err_struct; ++ ++ sff_8436->attr_group = sff_8436_attr_group; ++ sff_8436->sfp_compat = 0; ++ ++ err = sysfs_create_group(&client->dev.kobj, &sff_8436->attr_group); ++ if (err) { ++ dev_err(&client->dev, "failed to create sysfs attribute group.\n"); ++ goto err_struct; ++ } ++ sff_8436->eeprom_dev = eeprom_device_register(&client->dev, chip.eeprom_data); ++ if (IS_ERR(sff_8436->eeprom_dev)) { ++ dev_err(&client->dev, "error registering eeprom device.\n"); ++ err = PTR_ERR(sff_8436->eeprom_dev); ++ goto err_sysfs_cleanup; ++ } ++ ++ i2c_set_clientdata(client, sff_8436); ++ ++ dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", ++ sff_8436->bin.size, client->name, ++ "read-only"); ++ ++ if (use_smbus == I2C_SMBUS_WORD_DATA || ++ use_smbus == I2C_SMBUS_BYTE_DATA) { ++ dev_notice(&client->dev, "Falling back to %s reads, " ++ "performance will suffer\n", use_smbus == ++ I2C_SMBUS_WORD_DATA ? "word" : "byte"); ++ } ++ ++ if (chip.setup) ++ chip.setup(&sff_8436->macc, chip.context); ++ ++ return 0; ++ ++err_sysfs_cleanup: ++ sysfs_remove_group(&client->dev.kobj, &sff_8436->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &sff_8436->bin); ++ ++err_struct: ++ for (i = 1; i < num_addresses; i++) { ++ if (sff_8436->client[i]) ++ i2c_unregister_device(sff_8436->client[i]); ++ } ++ ++ kfree(sff_8436->writebuf); ++exit_kfree: ++ kfree(sff_8436); ++exit: ++ dev_dbg(&client->dev, "probe error %d\n", err); ++ ++ return err; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct i2c_driver sff_8436_driver = { ++ .driver = { ++ .name = "sff8436", ++ .owner = THIS_MODULE, ++ }, ++ .probe = sff_8436_eeprom_probe, ++ .remove = __devexit_p(sff_8436_remove), ++ .id_table = sff8436_ids, ++}; ++ ++static int __init sff_8436_init(void) ++{ ++ if (!io_limit) { ++ pr_err("sff_8436: io_limit must not be 0!\n"); ++ return -EINVAL; ++ } ++ ++ io_limit = rounddown_pow_of_two(io_limit); ++ return i2c_add_driver(&sff_8436_driver); ++} ++module_init(sff_8436_init); ++ ++static void __exit sff_8436_exit(void) ++{ ++ i2c_del_driver(&sff_8436_driver); ++} ++module_exit(sff_8436_exit); ++ ++MODULE_DESCRIPTION("Driver for SFF-8436 based QSFP EEPROMs"); ++MODULE_AUTHOR("VIDYA RAVIPATI "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c +index e27afde..407c5ef 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch new file mode 100644 index 00000000..1efb818c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_iwmc3200top_fw-download.c.patch @@ -0,0 +1,18 @@ +--- a/drivers/misc/iwmc3200top/fw-download.c ++++ b/drivers/misc/iwmc3200top/fw-download.c +@@ -311,11 +311,8 @@ int iwmct_fw_load(struct iwmct_priv *priv) + + /* get the firmware */ + ret = request_firmware(&raw, fw_name, &priv->func->dev); +- if (ret < 0) { +- LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n", +- fw_name, ret); ++ if (ret) + goto exit; +- } + + if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) { + LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n", +diff --git a/drivers/misc/retimer_class.c b/drivers/misc/retimer_class.c +new file mode 100644 +index 0000000..0e59ccf diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch new file mode 100644 index 00000000..03046ecf --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_retimer_class.c.patch @@ -0,0 +1,165 @@ +--- /dev/null ++++ b/drivers/misc/retimer_class.c +@@ -0,0 +1,160 @@ ++/* ++ * retimer_class.c ++ * ++ * This file defines the sysfs class "retimer", for use by RETIMER ++ * drivers. ++ * ++ * Copyright (C) 2014 Cumulus Networks, Inc. ++ * Author: Puneet Shenoy ++ * ++ * Ideas and structure graciously borrowed from the eeprom_class class: ++ * Copyright (C) 2013 Curt Brune ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Root retimer "class" object (corresponds to '//class/retimer_dev/') */ ++static struct class *retimer_class; ++ ++#define RETIMER_CLASS_NAME "retimer_dev" ++#define RETIMER_ID_PREFIX "retimer" ++#define RETIMER_ID_FORMAT RETIMER_ID_PREFIX "%d" ++ ++static DEFINE_IDA(retimer_ida); ++ ++/** ++ * retimer_device_register - register w/ retimer class ++ * @dev: the device to register ++ * ++ * retimer_device_unregister() must be called when the device is no ++ * longer needed. ++ * ++ * Creates a new retimer class device that is a child of @dev. Also ++ * creates a symlink in //class/retimer_dev/retimer[N] pointing ++ * to the new device. ++ * ++ * Returns the pointer to the new device. ++ */ ++struct device *retimer_device_register(struct device *dev) ++{ ++ struct device *retimer_dev; ++ int id; ++ ++ id = ida_simple_get(&retimer_ida, 0, 0, GFP_KERNEL); ++ if (id < 0) ++ return ERR_PTR(id); ++ ++ retimer_dev = device_create(retimer_class, dev, MKDEV(0, 0), NULL, ++ RETIMER_ID_FORMAT, id); ++ ++ if (IS_ERR(retimer_dev)) ++ ida_simple_remove(&retimer_ida, id); ++ ++ return retimer_dev; ++} ++ ++/** ++ * retimer_device_unregister - removes the previously registered class device ++ * ++ * @dev: the class device to destroy ++ */ ++void retimer_device_unregister(struct device *dev) ++{ ++ int id; ++ ++ if (likely(sscanf(dev_name(dev), RETIMER_ID_FORMAT, &id) == 1)) { ++ device_unregister(dev); ++ ida_simple_remove(&retimer_ida, id); ++ } else ++ dev_dbg(dev->parent, ++ "retimer_device_unregister() failed: bad class ID!\n"); ++} ++ ++/** ++ * Each member of the retimer class exports a sysfs file called ++ * "label", containing the label property from the corresponding ++ * device tree node. ++ * ++ * Userspace can use the label to identify what the RETIMER is for. ++ */ ++static ssize_t label_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ const char* cp = NULL; ++ int len = 0; ++ ++ /* ++ * The class device is a child of the original device, ++ * i.e. dev->parent points to the original device. ++ */ ++ if (dev->parent && dev->parent->of_node) ++ cp = of_get_property(dev->parent->of_node, "label", &len); ++ ++ if ((cp == NULL) || (len == 0)) { ++ cp = "unknown"; ++ len = strlen(cp) + 1; ++ } ++ ++ strncpy(buf, cp, len - 1); ++ buf[len - 1] = '\n'; ++ buf[len] = '\0'; ++ ++ return len; ++} ++ ++struct device_attribute retimer_class_dev_attrs[] = { ++ __ATTR_RO(label), ++ __ATTR_NULL, ++}; ++ ++static int __init retimer_init(void) ++{ ++ retimer_class = class_create(THIS_MODULE, RETIMER_CLASS_NAME); ++ if (IS_ERR(retimer_class)) { ++ pr_err("couldn't create sysfs class\n"); ++ return PTR_ERR(retimer_class); ++ } ++ ++ retimer_class->dev_attrs = retimer_class_dev_attrs; ++ ++ return 0; ++} ++ ++static void __exit retimer_exit(void) ++{ ++ class_destroy(retimer_class); ++} ++ ++subsys_initcall(retimer_init); ++module_exit(retimer_exit); ++ ++EXPORT_SYMBOL_GPL(retimer_device_register); ++EXPORT_SYMBOL_GPL(retimer_device_unregister); ++ ++MODULE_AUTHOR("Puneet Shenoy "); ++MODULE_DESCRIPTION("retimer sysfs/class support"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c +index 43ef8d1..5e4fe09 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch new file mode 100644 index 00000000..4ddf4f33 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_misc_ti-st_st_kim.c.patch @@ -0,0 +1,17 @@ +--- a/drivers/misc/ti-st/st_kim.c ++++ b/drivers/misc/ti-st/st_kim.c +@@ -281,11 +281,8 @@ static long download_firmware(struct kim_data_s *kim_gdata) + request_firmware(&kim_gdata->fw_entry, bts_scr_name, + &kim_gdata->kim_pdev->dev); + if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) || +- (kim_gdata->fw_entry->size == 0))) { +- pr_err(" request_firmware failed(errno %ld) for %s", err, +- bts_scr_name); ++ (kim_gdata->fw_entry->size == 0))) + return -EINVAL; +- } + ptr = (void *)kim_gdata->fw_entry->data; + len = kim_gdata->fw_entry->size; + /* bts_header to remove out magic number and +diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile +index 12eef39..400756e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch new file mode 100644 index 00000000..ec4efbeb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_Kconfig.patch @@ -0,0 +1,25 @@ +--- a/drivers/mtd/chips/Kconfig ++++ b/drivers/mtd/chips/Kconfig +@@ -52,8 +52,8 @@ config MTD_CFI_NOSWAP + 'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't + enabled, means that the CPU will not do any swapping; the chips + are expected to be wired to the CPU in 'host-endian' form. +- Specific arrangements are possible with the BIG_ENDIAN_BYTE and +- LITTLE_ENDIAN_BYTE, if the bytes are reversed. ++ Specific arrangements are possible with the BIG_ENDIAN_BYTE, ++ LITTLE_ENDIAN_BYTE, and OF_BYTE_SWAP if the bytes are reversed. + + If you have a LART, on which the data (and address) lines were + connected in a fashion which ensured that the nets were as short +@@ -68,6 +68,9 @@ config MTD_CFI_BE_BYTE_SWAP + config MTD_CFI_LE_BYTE_SWAP + bool "LITTLE_ENDIAN_BYTE" + ++config MTD_CFI_OF_BYTE_SWAP ++ bool "OF_BYTESWAP_PROPERTY" ++ + endchoice + + config MTD_CFI_GEOMETRY +diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c +index 179814a..aa272a3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch new file mode 100644 index 00000000..965a594f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_chips_cfi_cmdset_0020.c.patch @@ -0,0 +1,15 @@ +--- a/drivers/mtd/chips/cfi_cmdset_0020.c ++++ b/drivers/mtd/chips/cfi_cmdset_0020.c +@@ -139,8 +139,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) + } + + /* Do some byteswapping if necessary */ +- extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); +- extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); ++ extp->FeatureSupport = cfi32_to_cpu(map, extp->FeatureSupport); ++ extp->BlkStatusRegMask = cfi32_to_cpu(map, extp->BlkStatusRegMask); + + #ifdef DEBUG_CFI_FEATURES + /* Tell the user about it in lots of lovely detail */ +diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig +index 283d887..95cc3ad 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch new file mode 100644 index 00000000..ebd911b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_Kconfig.patch @@ -0,0 +1,20 @@ +--- a/drivers/mtd/devices/Kconfig ++++ b/drivers/mtd/devices/Kconfig +@@ -102,6 +102,15 @@ config M25PXX_USE_FAST_READ + help + This option enables FAST_READ access supported by ST M25Pxx. + ++config M25PXX_STAY_IN_3BYTE_MODE ++ bool "Stay in 3-byte address mode when idle" ++ depends on MTD_M25P80 ++ default n ++ help ++ This option forces the flash to stay in 3-byte address mode when idle ++ (even for flashes that require 4-byte address). This is work around the ++ reset problem if the controller cannot issue 4-byte OPCODE when booting. ++ + config MTD_SST25L + tristate "Support SST25L (non JEDEC) SPI Flash chips" + depends on SPI_MASTER +diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c +index 3d6beb7..9145658 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch new file mode 100644 index 00000000..cfa4bbba --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_devices_m25p80.c.patch @@ -0,0 +1,143 @@ +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -47,6 +47,7 @@ + #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ + #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ + #define OPCODE_RDID 0x9f /* Read JEDEC ID */ ++#define OPCODE_RDFSR 0x70 /* Read Flag Status Register */ + + /* Used for SST flashes only. */ + #define OPCODE_BP 0x02 /* Byte program */ +@@ -69,6 +70,9 @@ + #define SR_BP2 0x10 /* Block protect 2 */ + #define SR_SRWD 0x80 /* SR write protect */ + ++/* Flag Status Register bits. */ ++#define FSR_RDY 0x80 /* Ready/Busy program erase controller */ ++ + /* Define max times to check status register before we give up. */ + #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ + #define MAX_CMD_SIZE 6 +@@ -91,6 +95,7 @@ struct m25p { + struct mtd_info mtd; + u16 page_size; + u16 addr_width; ++ bool check_fsr; + u8 erase_opcode; + u8 *command; + }; +@@ -107,6 +112,28 @@ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) + */ + + /* ++ * Read the Flag Status Register (required for some Micron chips). ++ * Return the Flag Status Register value. ++ * Returns negative if error occurred. ++ */ ++static int read_fsr(struct m25p *flash) ++{ ++ ssize_t retval; ++ u8 code = OPCODE_RDFSR; ++ u8 val; ++ ++ retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); ++ ++ if (retval < 0) { ++ dev_err(&flash->spi->dev, "error %d reading FSR\n", ++ (int) retval); ++ return retval; ++ } ++ ++ return val; ++} ++ ++/* + * Read the status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. +@@ -166,10 +193,18 @@ static inline int write_disable(struct m25p *flash) + */ + static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) + { ++ int status; ++ + switch (JEDEC_MFR(jedec_id)) { + case CFI_MFR_MACRONIX: + flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; + return spi_write(flash->spi, flash->command, 1); ++ case CFI_MFR_ST: ++ flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; ++ write_enable(flash); ++ status = spi_write(flash->spi, flash->command, 1); ++ write_disable(flash); ++ return status; + default: + /* Spansion style */ + flash->command[0] = OPCODE_BRWR; +@@ -185,15 +220,21 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) + static int wait_till_ready(struct m25p *flash) + { + unsigned long deadline; +- int sr; ++ int sr, fsr; + + deadline = jiffies + MAX_READY_WAIT_JIFFIES; + + do { + if ((sr = read_sr(flash)) < 0) + break; +- else if (!(sr & SR_WIP)) ++ else if (!(sr & SR_WIP)) { ++ if (flash->check_fsr) { ++ fsr = read_fsr(flash); ++ if (!(fsr & FSR_RDY)) ++ return 1; ++ } + return 0; ++ } + + cond_resched(); + +@@ -625,6 +666,7 @@ struct flash_info { + u16 flags; + #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ + #define M25P_NO_ERASE 0x02 /* No erase command needed */ ++#define E_FSR 0x08 /* Flag SR exists for flash */ + }; + + #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ +@@ -686,6 +728,10 @@ static const struct spi_device_id m25p_ids[] = { + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, + ++ /* Micron */ ++ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, ++ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, ++ + /* Spansion -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ +@@ -727,6 +773,11 @@ static const struct spi_device_id m25p_ids[] = { + { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, + { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, + ++ { "n25q64", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, ++ { "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, E_FSR) }, ++ { "n25q256", INFO(0x20ba19, 0, 64 * 1024, 512, E_FSR | SECT_4K) }, ++ { "n25q512", INFO(0x20ba20, 0, 64 * 1024, 1024, E_FSR | SECT_4K) }, ++ + { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, + { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, + { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, +@@ -928,6 +979,9 @@ static int __devinit m25p_probe(struct spi_device *spi) + if (info->flags & M25P_NO_ERASE) + flash->mtd.flags |= MTD_NO_ERASE; + ++ if (info->flags & E_FSR) ++ flash->check_fsr = 1; ++ + ppdata.of_node = spi->dev.of_node; + flash->mtd.dev.parent = &spi->dev; + flash->page_size = info->page_size; +diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c +index 7d65f9d..7f32f30 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch new file mode 100644 index 00000000..e8466966 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_maps_physmap_of.c.patch @@ -0,0 +1,31 @@ +--- a/drivers/mtd/maps/physmap_of.c ++++ b/drivers/mtd/maps/physmap_of.c +@@ -161,6 +161,9 @@ static int __devinit of_flash_probe(struct platform_device *dev) + struct of_flash *info; + const char *probe_type; + const __be32 *width; ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++ struct property * byteswap_prop; ++#endif + int err; + int i; + int count; +@@ -236,6 +239,16 @@ static int __devinit of_flash_probe(struct platform_device *dev) + info->list[i].map.size = res_size; + info->list[i].map.bankwidth = be32_to_cpup(width); + ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++ byteswap_prop = of_find_property(dp, "byteswap", NULL); ++ if (byteswap_prop == NULL) { ++ info->list[i].map.byteswap = 0; ++ } else { ++ info->list[i].map.byteswap = 1; ++ dev_info(&dev->dev, "byteswapping configured in OF\n"); ++ } ++#endif ++ + err = -ENOMEM; + info->list[i].map.virt = ioremap(info->list[i].map.phys, + info->list[i].map.size); +diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c +index f3cdce9..b7883e5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch new file mode 100644 index 00000000..650f9777 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_mtdoops.c.patch @@ -0,0 +1,14 @@ +--- a/drivers/mtd/mtdoops.c ++++ b/drivers/mtd/mtdoops.c +@@ -311,8 +311,7 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, + char *dst; + + if (reason != KMSG_DUMP_OOPS && +- reason != KMSG_DUMP_PANIC && +- reason != KMSG_DUMP_KEXEC) ++ reason != KMSG_DUMP_PANIC) + return; + + /* Only dump oopses if dump_oops is set */ +diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c +index 1f9c363..bc431fb 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch new file mode 100644 index 00000000..a32b7f2c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_mtd_ubi_build.c.patch @@ -0,0 +1,13 @@ +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -1286,7 +1286,7 @@ out: + ubi_err("UBI error: cannot initialize UBI, error %d", err); + return err; + } +-module_init(ubi_init); ++late_initcall(ubi_init); + + static void __exit ubi_exit(void) + { +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 61d3d1f..05ac9bc 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch new file mode 100644 index 00000000..6f4218e7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_Makefile.patch @@ -0,0 +1,27 @@ +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_RIONET) += rionet.o + obj-$(CONFIG_TUN) += tun.o + obj-$(CONFIG_VETH) += veth.o + obj-$(CONFIG_VIRTIO_NET) += virtio_net.o ++obj-$(CONFIG_VXLAN) += vxlan.o + + # + # Networking Drivers +@@ -57,6 +58,8 @@ obj-$(CONFIG_VMXNET3) += vmxnet3/ + obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o + obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/ + ++obj-$(if $(CONFIG_DPA),y) += dpa/ ++ + obj-$(CONFIG_USB_CATC) += usb/ + obj-$(CONFIG_USB_KAWETH) += usb/ + obj-$(CONFIG_USB_PEGASUS) += usb/ +@@ -66,3 +69,5 @@ obj-$(CONFIG_USB_USBNET) += usb/ + obj-$(CONFIG_USB_ZD1201) += usb/ + obj-$(CONFIG_USB_IPHETH) += usb/ + obj-$(CONFIG_USB_CDC_PHONET) += usb/ ++ ++obj-$(CONFIG_HYPERV_NET) += hyperv/ +diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig +index f5a8916..1dd0719 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch new file mode 100644 index 00000000..9cefb7ce --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_can_softing_softing_fw.c.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/can/softing/softing_fw.c ++++ b/drivers/net/can/softing/softing_fw.c +@@ -237,11 +237,8 @@ int softing_load_app_fw(const char *file, struct softing *card) + int8_t type_end = 0, type_entrypoint = 0; + + ret = request_firmware(&fw, file, &card->pdev->dev); +- if (ret) { +- dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n", +- file, ret); ++ if (ret) + return ret; +- } + dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n", + file, (unsigned long)fw->size); + /* parse the firmware */ +diff --git a/drivers/net/dpa/Makefile b/drivers/net/dpa/Makefile +new file mode 100644 +index 0000000..0e59076 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch new file mode 100644 index 00000000..e0a0f3a1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2.c.patch @@ -0,0 +1,65 @@ +--- a/drivers/net/ethernet/broadcom/bnx2.c ++++ b/drivers/net/ethernet/broadcom/bnx2.c +@@ -2823,6 +2823,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; + u16 hw_cons, sw_cons, sw_ring_cons; + int tx_pkt = 0, index; ++ unsigned int tx_bytes = 0; + struct netdev_queue *txq; + + index = (bnapi - bp->bnx2_napi); +@@ -2877,6 +2878,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + + sw_cons = NEXT_TX_BD(sw_cons); + ++ tx_bytes += skb->len; + dev_kfree_skb(skb); + tx_pkt++; + if (tx_pkt == budget) +@@ -2886,6 +2888,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + hw_cons = bnx2_get_hw_tx_cons(bnapi); + } + ++ netdev_tx_completed_queue(txq, tx_pkt, tx_bytes); + txr->hw_tx_cons = hw_cons; + txr->tx_cons = sw_cons; + +@@ -3678,16 +3681,13 @@ static int bnx2_request_uncached_firmware(struct bnx2 *bp) + } + + rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev); +- if (rc) { +- pr_err("Can't load firmware file \"%s\"\n", mips_fw_file); ++ if (rc) + goto out; +- } + + rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev); +- if (rc) { +- pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file); ++ if (rc) + goto err_release_mips_firmware; +- } ++ + mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data; + rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data; + if (bp->mips_firmware->size < sizeof(*mips_fw) || +@@ -5400,6 +5400,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) + } + dev_kfree_skb(skb); + } ++ netdev_tx_reset_queue(netdev_get_tx_queue(bp->dev, i)); + } + } + +@@ -6552,6 +6553,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) + } + txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; + ++ netdev_tx_sent_queue(txq, skb->len); ++ + prod = NEXT_TX_BD(prod); + txr->tx_prod_bseq += skb->len; + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index e367ab1..d1e7ee8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch new file mode 100644 index 00000000..38493852 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch @@ -0,0 +1,98 @@ +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -100,7 +100,8 @@ int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ + * return idx of last bd freed + */ + static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, +- u16 idx) ++ u16 idx, unsigned int *pkts_compl, ++ unsigned int *bytes_compl) + { + struct sw_tx_bd *tx_buf = &txdata->tx_buf_ring[idx]; + struct eth_tx_start_bd *tx_start_bd; +@@ -162,6 +163,10 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, + + /* release skb */ + WARN_ON(!skb); ++ if (skb) { ++ (*pkts_compl)++; ++ (*bytes_compl) += skb->len; ++ } + dev_kfree_skb_any(skb); + tx_buf->first_bd = 0; + tx_buf->skb = NULL; +@@ -173,6 +178,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) + { + struct netdev_queue *txq; + u16 hw_cons, sw_cons, bd_cons = txdata->tx_bd_cons; ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + #ifdef BNX2X_STOP_ON_ERROR + if (unlikely(bp->panic)) +@@ -192,10 +198,14 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) + " pkt_cons %u\n", + txdata->txq_index, hw_cons, sw_cons, pkt_cons); + +- bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons); ++ bd_cons = bnx2x_free_tx_pkt(bp, txdata, pkt_cons, ++ &pkts_compl, &bytes_compl); ++ + sw_cons++; + } + ++ netdev_tx_completed_queue(txq, pkts_compl, bytes_compl); ++ + txdata->tx_pkt_cons = sw_cons; + txdata->tx_bd_cons = bd_cons; + +@@ -1117,16 +1127,18 @@ static void bnx2x_free_tx_skbs(struct bnx2x *bp) + struct bnx2x_fastpath *fp = &bp->fp[i]; + for_each_cos_in_tx_queue(fp, cos) { + struct bnx2x_fp_txdata *txdata = &fp->txdata[cos]; ++ unsigned pkts_compl = 0, bytes_compl = 0; + +- u16 bd_cons = txdata->tx_bd_cons; + u16 sw_prod = txdata->tx_pkt_prod; + u16 sw_cons = txdata->tx_pkt_cons; + + while (sw_cons != sw_prod) { +- bd_cons = bnx2x_free_tx_pkt(bp, txdata, +- TX_BD(sw_cons)); ++ bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons), ++ &pkts_compl, &bytes_compl); + sw_cons++; + } ++ netdev_tx_reset_queue( ++ netdev_get_tx_queue(bp->dev, txdata->txq_index)); + } + } + } +@@ -2821,6 +2833,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + mapping = skb_frag_dma_map(&bp->pdev->dev, frag, 0, + skb_frag_size(frag), DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + DP(NETIF_MSG_TX_QUEUED, "Unable to map page - " + "dropping packet...\n"); +@@ -2832,7 +2845,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + */ + first_bd->nbd = cpu_to_le16(nbd); + bnx2x_free_tx_pkt(bp, txdata, +- TX_BD(txdata->tx_pkt_prod)); ++ TX_BD(txdata->tx_pkt_prod), ++ &pkts_compl, &bytes_compl); + return NETDEV_TX_OK; + } + +@@ -2893,6 +2907,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + pbd_e2->parsing_data); + DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); + ++ netdev_tx_sent_queue(txq, skb->len); ++ + txdata->tx_pkt_prod++; + /* + * Make sure that the BD data is updated before updating the producer +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +index f0ca8b2..8be81e3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch new file mode 100644 index 00000000..1be9c137 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +@@ -1740,6 +1740,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + struct sw_rx_bd *rx_buf; + u16 len; + int rc = -ENODEV; ++ struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txdata->txq_index); + + /* check the loopback mode */ + switch (loopback_mode) { +@@ -1784,6 +1785,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) + tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb); + rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb); + ++ netdev_tx_sent_queue(txq, skb->len); ++ + pkt_prod = txdata->tx_pkt_prod++; + tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)]; + tx_buf->first_bd = txdata->tx_bd_prod; +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index 1042935..f2119ea 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch new file mode 100644 index 00000000..1619909a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch @@ -0,0 +1,17 @@ +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -10573,11 +10573,8 @@ int bnx2x_init_firmware(struct bnx2x *bp) + + rc = request_firmware(&bp->firmware, fw_file_name, + &bp->pdev->dev); +- if (rc) { +- BNX2X_ERR("Can't load firmware file %s\n", +- fw_file_name); ++ if (rc) + goto request_firmware_exit; +- } + + rc = bnx2x_check_firmware(bp); + if (rc) { +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index d0ebf9c..32d4e7f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch new file mode 100644 index 00000000..042f01a3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_ethernet_broadcom_tg3.c.patch @@ -0,0 +1,50 @@ +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -5362,6 +5362,7 @@ static void tg3_tx(struct tg3_napi *tnapi) + u32 sw_idx = tnapi->tx_cons; + struct netdev_queue *txq; + int index = tnapi - tp->napi; ++ unsigned int pkts_compl = 0, bytes_compl = 0; + + if (tg3_flag(tp, ENABLE_TSS)) + index--; +@@ -5420,6 +5421,8 @@ static void tg3_tx(struct tg3_napi *tnapi) + } + } + ++ netdev_tx_completed_queue(txq, pkts_compl, bytes_compl); ++ + tnapi->tx_cons = sw_idx; + + /* Need to make the tx_cons update visible to tg3_start_xmit() +@@ -6863,6 +6866,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + } + + skb_tx_timestamp(skb); ++ netdev_tx_sent_queue(txq, skb->len); + + /* Packets are ready, update Tx producer idx local and on card. */ + tw32_tx_mbox(tnapi->prodmbox, entry); +@@ -7343,6 +7347,7 @@ static void tg3_free_rings(struct tg3 *tp) + + dev_kfree_skb_any(skb); + } ++ netdev_tx_reset_queue(netdev_get_tx_queue(tp->dev, j)); + } + } + +@@ -9595,11 +9600,8 @@ static int tg3_request_firmware(struct tg3 *tp) + { + const __be32 *fw_data; + +- if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { +- netdev_err(tp->dev, "Failed to load firmware \"%s\"\n", +- tp->fw_needed); ++ if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) + return -ENOENT; +- } + + fw_data = (void *)tp->fw->data; + +diff --git a/drivers/net/ethernet/brocade/bna/cna_fwimg.c b/drivers/net/ethernet/brocade/bna/cna_fwimg.c +index 725b9ff..0c072b3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch new file mode 100644 index 00000000..5fefddcb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_mdio_bus.c.patch @@ -0,0 +1,77 @@ +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -75,6 +75,38 @@ static struct class mdio_bus_class = { + .dev_release = mdiobus_release, + }; + ++#ifdef CONFIG_OF_MDIO ++/* Helper function for of_mdio_find_bus */ ++static int of_mdio_bus_match(struct device *dev, void *mdio_bus_np) ++{ ++ return dev->of_node == mdio_bus_np; ++} ++/** ++ * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. ++ * @mdio_np: Pointer to the mii_bus. ++ * ++ * Returns a pointer to the mii_bus, or NULL if none found. ++ * ++ * Because the association of a device_node and mii_bus is made via ++ * of_mdiobus_register(), the mii_bus cannot be found before it is ++ * registered with of_mdiobus_register(). ++ * ++ */ ++struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np) ++{ ++ struct device *d; ++ ++ if (!mdio_bus_np) ++ return NULL; ++ ++ d = class_find_device(&mdio_bus_class, NULL, mdio_bus_np, ++ of_mdio_bus_match); ++ ++ return d ? to_mii_bus(d) : NULL; ++} ++EXPORT_SYMBOL(of_mdio_find_bus); ++#endif ++ + /** + * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus + * @bus: target mii_bus +@@ -208,14 +240,14 @@ EXPORT_SYMBOL(mdiobus_scan); + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +-int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) ++int mdiobus_read(struct mii_bus *bus, int addr, int devad, u16 regnum) + { + int retval; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); +- retval = bus->read(bus, addr, regnum); ++ retval = bus->read(bus, addr, devad, regnum); + mutex_unlock(&bus->mdio_lock); + + return retval; +@@ -233,14 +265,14 @@ EXPORT_SYMBOL(mdiobus_read); + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +-int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) ++int mdiobus_write(struct mii_bus *bus, int addr, int devad, u16 regnum, u16 val) + { + int err; + + BUG_ON(in_interrupt()); + + mutex_lock(&bus->mdio_lock); +- err = bus->write(bus, addr, regnum, val); ++ err = bus->write(bus, addr, devad, regnum, val); + mutex_unlock(&bus->mdio_lock); + + return err; +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 3cbda08..0825a78 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch new file mode 100644 index 00000000..e24a668f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy.c.patch @@ -0,0 +1,51 @@ +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -6,7 +6,7 @@ + * + * Author: Andy Fleming + * +- * Copyright (c) 2004 Freescale Semiconductor, Inc. ++ * Copyright (c) 2004,2011 Freescale Semiconductor, Inc. + * Copyright (c) 2006, 2007 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or modify it +@@ -322,7 +322,7 @@ int phy_mii_ioctl(struct phy_device *phydev, + + case SIOCGMIIREG: + mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id, +- mii_data->reg_num); ++ 0, mii_data->reg_num); + break; + + case SIOCSMIIREG: +@@ -353,7 +353,7 @@ int phy_mii_ioctl(struct phy_device *phydev, + } + } + +- mdiobus_write(phydev->bus, mii_data->phy_id, ++ mdiobus_write(phydev->bus, mii_data->phy_id, 0, + mii_data->reg_num, val); + + if (mii_data->reg_num == MII_BMCR && +@@ -479,6 +479,10 @@ static void phy_force_reduction(struct phy_device *phydev) + + idx = phy_find_valid(idx, phydev->supported); + ++ /* Avoid reaching an invalid speed and duplex combination */ ++ if (!(settings[idx].setting & phydev->supported)) ++ return; ++ + phydev->speed = settings[idx].speed; + phydev->duplex = settings[idx].duplex; + +@@ -869,6 +873,8 @@ void phy_state_machine(struct work_struct *work) + if (0 == phydev->link_timeout--) { + phy_force_reduction(phydev); + needs_aneg = 1; ++ phydev->link_timeout = ++ PHY_FORCE_TIMEOUT; + } + } + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 83a5a5a..e88f49a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch new file mode 100644 index 00000000..01b0808b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_net_phy_phy_device.c.patch @@ -0,0 +1,342 @@ +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -6,7 +6,7 @@ + * + * Author: Andy Fleming + * +- * Copyright (c) 2004 Freescale Semiconductor, Inc. ++ * Copyright (c) 2004-2006, 2008-2011 Freescale Semiconductor, Inc. + * + * 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 +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -51,15 +52,13 @@ static void phy_device_release(struct device *dev) + } + + static struct phy_driver genphy_driver; ++static struct phy_driver gen10g_driver; + extern int mdio_bus_init(void); + extern void mdio_bus_exit(void); + + static LIST_HEAD(phy_fixup_list); + static DEFINE_MUTEX(phy_fixup_lock); + +-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, +- u32 flags, phy_interface_t interface); +- + /* + * Creates a new phy_fixup and adds it to the list + * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID) +@@ -210,23 +209,29 @@ static struct phy_device* phy_device_create(struct mii_bus *bus, + int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id) + { + int phy_reg; ++ int i; ++ ++ for (i = 1; i < 5; i++) { ++ /* Grab the bits from PHYIR1, and put them ++ * in the upper half */ ++ phy_reg = bus->read(bus, addr, i, MII_PHYSID1); + +- /* Grab the bits from PHYIR1, and put them +- * in the upper half */ +- phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); ++ if (phy_reg < 0) ++ return -EIO; + +- if (phy_reg < 0) +- return -EIO; ++ *phy_id = (phy_reg & 0xffff) << 16; + +- *phy_id = (phy_reg & 0xffff) << 16; ++ /* Grab the bits from PHYIR2, and put them in the lower half */ ++ phy_reg = bus->read(bus, addr, i, MII_PHYSID2); + +- /* Grab the bits from PHYIR2, and put them in the lower half */ +- phy_reg = mdiobus_read(bus, addr, MII_PHYSID2); ++ if (phy_reg < 0) ++ return -EIO; + +- if (phy_reg < 0) +- return -EIO; ++ *phy_id |= (phy_reg & 0xffff); + +- *phy_id |= (phy_reg & 0xffff); ++ if (*phy_id != 0xffffffff) ++ break; ++ } + + return 0; + } +@@ -433,12 +438,12 @@ int phy_init_hw(struct phy_device *phydev) + * + * Description: Called by drivers to attach to a particular PHY + * device. The phy_device is found, and properly hooked up +- * to the phy_driver. If no driver is attached, then the +- * genphy_driver is used. The phy_device is given a ptr to ++ * to the phy_driver. If no driver is attached, then a ++ * generic driver is used. The phy_device is given a ptr to + * the attaching device, and given a callback for link status + * change. The phy_device is returned to the attaching driver. + */ +-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ++int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + u32 flags, phy_interface_t interface) + { + struct device *d = &phydev->dev; +@@ -447,7 +452,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, + /* Assume that if there is no driver, that it doesn't + * exist, and we should use the genphy driver. */ + if (NULL == d->driver) { +- d->driver = &genphy_driver.driver; ++ int err; ++ if (interface == PHY_INTERFACE_MODE_XGMII) ++ d->driver = &gen10g_driver.driver; ++ else ++ d->driver = &genphy_driver.driver; + + err = d->driver->probe(d); + if (err >= 0) +@@ -531,6 +540,8 @@ void phy_detach(struct phy_device *phydev) + * real driver could be loaded */ + if (phydev->dev.driver == &genphy_driver.driver) + device_release_driver(&phydev->dev); ++ else if (phydev->dev.driver == &gen10g_driver.driver) ++ device_release_driver(&phydev->dev); + } + EXPORT_SYMBOL(phy_detach); + +@@ -612,6 +623,12 @@ static int genphy_config_advert(struct phy_device *phydev) + return changed; + } + ++int gen10g_config_advert(struct phy_device *dev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_config_advert); ++ + /** + * genphy_setup_forced - configures/forces speed/duplex from @phydev + * @phydev: target phy_device struct +@@ -620,7 +637,7 @@ static int genphy_config_advert(struct phy_device *phydev) + * to the values in phydev. Assumes that the values are valid. + * Please see phy_sanitize_settings(). + */ +-static int genphy_setup_forced(struct phy_device *phydev) ++int genphy_setup_forced(struct phy_device *phydev) + { + int err; + int ctl = 0; +@@ -639,7 +656,12 @@ static int genphy_setup_forced(struct phy_device *phydev) + + return err; + } ++EXPORT_SYMBOL(genphy_setup_forced); + ++int gen10g_setup_forced(struct phy_device *phydev) ++{ ++ return 0; ++} + + /** + * genphy_restart_aneg - Enable and Restart Autonegotiation +@@ -665,6 +687,12 @@ int genphy_restart_aneg(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_restart_aneg); + ++int gen10g_restart_aneg(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_restart_aneg); ++ + + /** + * genphy_config_aneg - restart auto-negotiation or write BMCR +@@ -707,6 +735,12 @@ int genphy_config_aneg(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_config_aneg); + ++int gen10g_config_aneg(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_config_aneg); ++ + /** + * genphy_update_link - update link status in @phydev + * @phydev: target phy_device struct +@@ -790,6 +824,16 @@ int genphy_read_status(struct phy_device *phydev) + + lpa &= adv; + ++ err = phy_read(phydev, MII_BMSR); ++ ++ if (err < 0) ++ return err; ++ ++ /* if the link changed while reading speed and duplex ++ * abort the speed and duplex update */ ++ if (((err & BMSR_LSTATUS) == 0) != (phydev->link == 0)) ++ return 0; ++ + phydev->speed = SPEED_10; + phydev->duplex = DUPLEX_HALF; + phydev->pause = phydev->asym_pause = 0; +@@ -836,6 +880,33 @@ int genphy_read_status(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_read_status); + ++int gen10g_read_status(struct phy_device *phydev) ++{ ++ int devad, reg; ++ u32 mmd_mask = phydev->mmds; ++ ++ phydev->link = 1; ++ ++ /* For now just lie and say it's 10G all the time */ ++ phydev->speed = 10000; ++ phydev->duplex = DUPLEX_FULL; ++ ++ for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) { ++ if (!mmd_mask & 1) ++ continue; ++ ++ /* Read twice because link state is latched and a ++ * read moves the current state into the register */ ++ phy45_read(phydev, devad, MDIO_STAT1); ++ reg = phy45_read(phydev, devad, MDIO_STAT1); ++ if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) ++ phydev->link = 0; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_read_status); ++ + static int genphy_config_init(struct phy_device *phydev) + { + int val; +@@ -882,6 +953,36 @@ static int genphy_config_init(struct phy_device *phydev) + + return 0; + } ++ ++/* Replicate mdio45_probe */ ++int gen10g_config_init(struct phy_device *phydev) ++{ ++ int mmd, stat2, devs1, devs2; ++ ++ phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full; ++ ++ /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY ++ * XS or DTE XS; give up if none is present. */ ++ for (mmd = 1; mmd <= 5; mmd++) { ++ /* Is this MMD present? */ ++ stat2 = phy45_read(phydev, mmd, MDIO_STAT2); ++ if (stat2 < 0 || ++ (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) ++ continue; ++ ++ /* It should tell us about all the other MMDs */ ++ devs1 = phy45_read(phydev, mmd, MDIO_DEVS1); ++ devs2 = phy45_read(phydev, mmd, MDIO_DEVS2); ++ if (devs1 < 0 || devs2 < 0) ++ continue; ++ ++ phydev->mmds = devs1 | (devs2 << 16); ++ return 0; ++ } ++ ++ return -ENODEV; ++} ++ + int genphy_suspend(struct phy_device *phydev) + { + int value; +@@ -897,6 +998,12 @@ int genphy_suspend(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_suspend); + ++int gen10g_suspend(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_suspend); ++ + int genphy_resume(struct phy_device *phydev) + { + int value; +@@ -912,6 +1019,13 @@ int genphy_resume(struct phy_device *phydev) + } + EXPORT_SYMBOL(genphy_resume); + ++int gen10g_resume(struct phy_device *phydev) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(gen10g_resume); ++ ++ + /** + * phy_probe - probe and init a PHY device + * @dev: device to probe and init +@@ -1022,7 +1136,20 @@ static struct phy_driver genphy_driver = { + .read_status = genphy_read_status, + .suspend = genphy_suspend, + .resume = genphy_resume, +- .driver = {.owner= THIS_MODULE, }, ++ .driver = {.owner = THIS_MODULE, }, ++}; ++ ++static struct phy_driver gen10g_driver = { ++ .phy_id = 0xffffffff, ++ .phy_id_mask = 0xffffffff, ++ .name = "Generic 10G PHY", ++ .config_init = gen10g_config_init, ++ .features = 0, ++ .config_aneg = gen10g_config_aneg, ++ .read_status = gen10g_read_status, ++ .suspend = gen10g_suspend, ++ .resume = gen10g_resume, ++ .driver = {.owner = THIS_MODULE, }, + }; + + static int __init phy_init(void) +@@ -1035,13 +1162,25 @@ static int __init phy_init(void) + + rc = phy_driver_register(&genphy_driver); + if (rc) +- mdio_bus_exit(); ++ goto genphy_register_failed; ++ ++ rc = phy_driver_register(&gen10g_driver); ++ if (rc) ++ goto gen10g_register_failed; ++ ++ return rc; ++ ++gen10g_register_failed: ++ phy_driver_unregister(&genphy_driver); ++genphy_register_failed: ++ mdio_bus_exit(); + + return rc; + } + + static void __exit phy_exit(void) + { ++ phy_driver_unregister(&gen10g_driver); + phy_driver_unregister(&genphy_driver); + mdio_bus_exit(); + } +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 2fbbca6..acb7e2c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch new file mode 100644 index 00000000..9be126bd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_of_of_mdio.c.patch @@ -0,0 +1,48 @@ +--- a/drivers/of/of_mdio.c ++++ b/drivers/of/of_mdio.c +@@ -45,6 +45,8 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) + for (i=0; iirq[i] = PHY_POLL; + ++ mdio->dev.of_node = np; ++ + /* Register the MDIO bus */ + rc = mdiobus_register(mdio); + if (rc) +@@ -77,12 +79,16 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) + mdio->irq[addr] = PHY_POLL; + } + ++ mdio->is_c45 = of_device_is_compatible(child, ++ "ethernet-phy-ieee802.3-c45"); ++ + phy = get_phy_device(mdio, addr); + if (!phy || IS_ERR(phy)) { + dev_err(&mdio->dev, "error probing PHY at address %i\n", + addr); + continue; + } ++ phy_scan_fixups(phy); + + /* Associate the OF node with the device structure so it + * can be looked up later */ +@@ -188,3 +194,17 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, + return IS_ERR(phy) ? NULL : phy; + } + EXPORT_SYMBOL(of_phy_connect_fixed_link); ++ ++/* XXX add comment */ ++struct phy_device *of_phy_attach(struct net_device *dev, ++ struct device_node *phy_np, u32 flags, ++ phy_interface_t iface) ++{ ++ struct phy_device *phy = of_phy_find_device(phy_np); ++ ++ if (!phy) ++ return NULL; ++ ++ return phy_attach_direct(dev, phy, flags, iface) ? NULL : phy; ++} ++EXPORT_SYMBOL(of_phy_attach); +diff --git a/drivers/of/platform.c b/drivers/of/platform.c +index 63b3ec4..fb3762c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch new file mode 100644 index 00000000..9ea2800d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_of_platform.c.patch @@ -0,0 +1,41 @@ +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -139,6 +139,18 @@ struct platform_device *of_device_alloc(struct device_node *np, + if (!dev) + return NULL; + ++ dev->dev.of_node = of_node_get(np); ++ if (bus_id) ++ dev_set_name(&dev->dev, "%s", bus_id); ++ else ++ of_device_make_bus_id(&dev->dev); ++ ++ if (kset_find_obj(dev->dev.kobj.kset, kobject_name(&dev->dev.kobj))) { ++ kfree(dev); ++ of_node_put(np); ++ return NULL; ++ } ++ + /* count the io and irq resources */ + while (of_address_to_resource(np, num_reg, &temp_res) == 0) + num_reg++; +@@ -161,17 +173,11 @@ struct platform_device *of_device_alloc(struct device_node *np, + WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); + } + +- dev->dev.of_node = of_node_get(np); + #if defined(CONFIG_MICROBLAZE) + dev->dev.dma_mask = &dev->archdata.dma_mask; + #endif + dev->dev.parent = parent; + +- if (bus_id) +- dev_set_name(&dev->dev, "%s", bus_id); +- else +- of_device_make_bus_id(&dev->dev); +- + return dev; + } + EXPORT_SYMBOL(of_device_alloc); +diff --git a/drivers/pci/access.c b/drivers/pci/access.c +index fdaa42a..bbde7d0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch new file mode 100644 index 00000000..690c2f55 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_access.c.patch @@ -0,0 +1,210 @@ +--- a/drivers/pci/access.c ++++ b/drivers/pci/access.c +@@ -445,3 +445,205 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev) + raw_spin_unlock_irqrestore(&pci_lock, flags); + } + EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); ++ ++static inline int pcie_cap_version(const struct pci_dev *dev) ++{ ++ return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS; ++} ++ ++static inline bool pcie_cap_has_devctl(const struct pci_dev *dev) ++{ ++ return true; ++} ++ ++static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) ++{ ++ int type = pci_pcie_type(dev); ++ ++ return pcie_cap_version(dev) > 1 || ++ type == PCI_EXP_TYPE_ROOT_PORT || ++ type == PCI_EXP_TYPE_ENDPOINT || ++ type == PCI_EXP_TYPE_LEG_END; ++} ++ ++static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) ++{ ++ int type = pci_pcie_type(dev); ++ ++ return pcie_cap_version(dev) > 1 || ++ type == PCI_EXP_TYPE_ROOT_PORT || ++ (type == PCI_EXP_TYPE_DOWNSTREAM && ++ dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT); ++} ++ ++static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) ++{ ++ int type = pci_pcie_type(dev); ++ ++ return pcie_cap_version(dev) > 1 || ++ type == PCI_EXP_TYPE_ROOT_PORT || ++ type == PCI_EXP_TYPE_RC_EC; ++} ++ ++static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) ++{ ++ if (!pci_is_pcie(dev)) ++ return false; ++ ++ switch (pos) { ++ case PCI_EXP_FLAGS_TYPE: ++ return true; ++ case PCI_EXP_DEVCAP: ++ case PCI_EXP_DEVCTL: ++ case PCI_EXP_DEVSTA: ++ return pcie_cap_has_devctl(dev); ++ case PCI_EXP_LNKCAP: ++ case PCI_EXP_LNKCTL: ++ case PCI_EXP_LNKSTA: ++ return pcie_cap_has_lnkctl(dev); ++ case PCI_EXP_SLTCAP: ++ case PCI_EXP_SLTCTL: ++ case PCI_EXP_SLTSTA: ++ return pcie_cap_has_sltctl(dev); ++ case PCI_EXP_RTCTL: ++ case PCI_EXP_RTCAP: ++ case PCI_EXP_RTSTA: ++ return pcie_cap_has_rtctl(dev); ++ case PCI_EXP_DEVCAP2: ++ case PCI_EXP_DEVCTL2: ++ case PCI_EXP_LNKCAP2: ++ case PCI_EXP_LNKCTL2: ++ case PCI_EXP_LNKSTA2: ++ return pcie_cap_version(dev) > 1; ++ default: ++ return false; ++ } ++} ++ ++/* ++ * Note that these accessor functions are only for the "PCI Express ++ * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the ++ * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.) ++ */ ++int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val) ++{ ++ int ret; ++ ++ *val = 0; ++ if (pos & 1) ++ return -EINVAL; ++ ++ if (pcie_capability_reg_implemented(dev, pos)) { ++ ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val); ++ /* ++ * Reset *val to 0 if pci_read_config_word() fails, it may ++ * have been written as 0xFFFF if hardware error happens ++ * during pci_read_config_word(). ++ */ ++ if (ret) ++ *val = 0; ++ return ret; ++ } ++ ++ /* ++ * For Functions that do not implement the Slot Capabilities, ++ * Slot Status, and Slot Control registers, these spaces must ++ * be hardwired to 0b, with the exception of the Presence Detect ++ * State bit in the Slot Status register of Downstream Ports, ++ * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8) ++ */ ++ if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA && ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { ++ *val = PCI_EXP_SLTSTA_PDS; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(pcie_capability_read_word); ++ ++int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val) ++{ ++ int ret; ++ ++ *val = 0; ++ if (pos & 3) ++ return -EINVAL; ++ ++ if (pcie_capability_reg_implemented(dev, pos)) { ++ ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val); ++ /* ++ * Reset *val to 0 if pci_read_config_dword() fails, it may ++ * have been written as 0xFFFFFFFF if hardware error happens ++ * during pci_read_config_dword(). ++ */ ++ if (ret) ++ *val = 0; ++ return ret; ++ } ++ ++ if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL && ++ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { ++ *val = PCI_EXP_SLTSTA_PDS; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(pcie_capability_read_dword); ++ ++int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) ++{ ++ if (pos & 1) ++ return -EINVAL; ++ ++ if (!pcie_capability_reg_implemented(dev, pos)) ++ return 0; ++ ++ return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); ++} ++EXPORT_SYMBOL(pcie_capability_write_word); ++ ++int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val) ++{ ++ if (pos & 3) ++ return -EINVAL; ++ ++ if (!pcie_capability_reg_implemented(dev, pos)) ++ return 0; ++ ++ return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val); ++} ++EXPORT_SYMBOL(pcie_capability_write_dword); ++ ++int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, ++ u16 clear, u16 set) ++{ ++ int ret; ++ u16 val; ++ ++ ret = pcie_capability_read_word(dev, pos, &val); ++ if (!ret) { ++ val &= ~clear; ++ val |= set; ++ ret = pcie_capability_write_word(dev, pos, val); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(pcie_capability_clear_and_set_word); ++ ++int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, ++ u32 clear, u32 set) ++{ ++ int ret; ++ u32 val; ++ ++ ret = pcie_capability_read_dword(dev, pos, &val); ++ if (!ret) { ++ val &= ~clear; ++ val |= set; ++ ret = pcie_capability_write_dword(dev, pos, val); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index e3efb43..b99d888 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch new file mode 100644 index 00000000..97701622 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_msi.c.patch @@ -0,0 +1,190 @@ +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -306,6 +306,9 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) + static void free_msi_irqs(struct pci_dev *dev) + { + struct msi_desc *entry, *tmp; ++ struct attribute **msi_attrs; ++ struct device_attribute *dev_attr; ++ int count = 0; + + list_for_each_entry(entry, &dev->msi_list, list) { + int i, nvec; +@@ -323,9 +326,25 @@ static void free_msi_irqs(struct pci_dev *dev) + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); + } ++ + list_del(&entry->list); + kfree(entry); + } ++ ++ if (dev->msi_irq_group) { ++ sysfs_remove_group(&dev->dev.kobj, dev->msi_irq_group); ++ msi_attrs = dev->msi_irq_group->attrs; ++ while (msi_attrs[count]) { ++ dev_attr = container_of(msi_attrs[count], ++ struct device_attribute, attr); ++ kfree(dev_attr->attr.name); ++ kfree(dev_attr); ++ ++count; ++ } ++ kfree(msi_attrs); ++ kfree(dev->msi_irq_group); ++ dev->msi_irq_group = NULL; ++ } + } + + static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) +@@ -403,6 +422,98 @@ void pci_restore_msi_state(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_restore_msi_state); + ++static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct msi_desc *entry; ++ unsigned long irq; ++ int retval; ++ ++ retval = kstrtoul(attr->attr.name, 10, &irq); ++ if (retval) ++ return retval; ++ ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ if (entry->irq == irq) { ++ return sprintf(buf, "%s\n", ++ entry->msi_attrib.is_msix ? "msix" : "msi"); ++ } ++ } ++ return -ENODEV; ++} ++ ++static int populate_msi_sysfs(struct pci_dev *pdev) ++{ ++ struct attribute **msi_attrs; ++ struct attribute *msi_attr; ++ struct device_attribute *msi_dev_attr; ++ struct attribute_group *msi_irq_group; ++ struct msi_desc *entry; ++ int ret = -ENOMEM; ++ int num_msi = 0; ++ int count = 0; ++ ++ /* Determine how many msi entries we have */ ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ ++num_msi; ++ } ++ if (!num_msi) ++ return 0; ++ ++ /* Dynamically create the MSI attributes for the PCI device */ ++ msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL); ++ if (!msi_attrs) ++ return -ENOMEM; ++ list_for_each_entry(entry, &pdev->msi_list, list) { ++ char *name = kmalloc(20, GFP_KERNEL); ++ if (!name) ++ goto error_attrs; ++ ++ msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); ++ if (!msi_dev_attr) { ++ kfree(name); ++ goto error_attrs; ++ } ++ ++ sprintf(name, "%d", entry->irq); ++ sysfs_attr_init(&msi_dev_attr->attr); ++ msi_dev_attr->attr.name = name; ++ msi_dev_attr->attr.mode = S_IRUGO; ++ msi_dev_attr->show = msi_mode_show; ++ msi_attrs[count] = &msi_dev_attr->attr; ++ ++count; ++ } ++ ++ msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL); ++ if (!msi_irq_group) ++ goto error_attrs; ++ msi_irq_group->name = "msi_irqs"; ++ msi_irq_group->attrs = msi_attrs; ++ ++ ret = sysfs_create_group(&pdev->dev.kobj, msi_irq_group); ++ if (ret) ++ goto error_irq_group; ++ pdev->msi_irq_group = msi_irq_group; ++ ++ return 0; ++ ++error_irq_group: ++ kfree(msi_irq_group); ++error_attrs: ++ count = 0; ++ msi_attr = msi_attrs[count]; ++ while (msi_attr) { ++ msi_dev_attr = container_of(msi_attr, struct device_attribute, attr); ++ kfree(msi_attr->name); ++ kfree(msi_dev_attr); ++ ++count; ++ msi_attr = msi_attrs[count]; ++ } ++ kfree(msi_attrs); ++ return ret; ++} ++ + /** + * msi_capability_init - configure device's MSI capability structure + * @dev: pointer to the pci_dev data structure of MSI device function +@@ -454,6 +565,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) + return ret; + } + ++ ret = populate_msi_sysfs(dev); ++ if (ret) { ++ msi_mask_irq(entry, mask, ~mask); ++ free_msi_irqs(dev); ++ return ret; ++ } ++ + /* Set MSI enabled bits */ + pci_intx_for_msi(dev, 0); + msi_set_enable(dev, pos, 1); +@@ -562,7 +680,7 @@ static int msix_capability_init(struct pci_dev *dev, + + ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); + if (ret) +- goto error; ++ goto out_avail; + + /* + * Some devices require MSI-X to be enabled before we can touch the +@@ -574,6 +692,10 @@ static int msix_capability_init(struct pci_dev *dev, + + msix_program_entries(dev, entries); + ++ ret = populate_msi_sysfs(dev); ++ if (ret) ++ goto out_free; ++ + /* Set MSI-X enabled bits and unmask the function */ + pci_intx_for_msi(dev, 0); + dev->msix_enabled = 1; +@@ -583,7 +705,7 @@ static int msix_capability_init(struct pci_dev *dev, + + return 0; + +-error: ++out_avail: + if (ret < 0) { + /* + * If we had some success, report the number of irqs +@@ -600,6 +722,7 @@ error: + ret = avail; + } + ++out_free: + free_msi_irqs(dev); + + return ret; +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 4c3a9e9..e4823bf 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch new file mode 100644 index 00000000..57b12feb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pci.c.patch @@ -0,0 +1,23 @@ +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -963,7 +963,7 @@ void pci_restore_state(struct pci_dev *dev) + for (i = 15; i >= 0; i--) { + pci_read_config_dword(dev, i * 4, &val); + if (val != dev->saved_config_space[i]) { +- dev_printk(KERN_DEBUG, &dev->dev, "restoring config " ++ dev_dbg(&dev->dev, "restoring config " + "space at offset %#x (was %#x, writing %#x)\n", + i, val, (int)dev->saved_config_space[i]); + pci_write_config_dword(dev,i * 4, +@@ -1545,8 +1545,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable) + } + + out: +- dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n", +- enable ? "enabled" : "disabled"); ++ dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled"); + } + + /** +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index c73ed00..31668af 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch new file mode 100644 index 00000000..3616dd54 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_pcie_aspm.c.patch @@ -0,0 +1,30 @@ +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -440,7 +440,7 @@ static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) + int pos = pci_pcie_cap(pdev); + + pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); +- reg16 &= ~0x3; ++ reg16 &= ~PCI_EXP_LNKCTL_ASPMC; + reg16 |= val; + pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); + } +@@ -457,12 +457,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) + return; + /* Convert ASPM state to upstream/downstream ASPM register state */ + if (state & ASPM_STATE_L0S_UP) +- dwstream |= PCIE_LINK_STATE_L0S; ++ dwstream |= PCI_EXP_LNKCTL_ASPM_L0S; + if (state & ASPM_STATE_L0S_DW) +- upstream |= PCIE_LINK_STATE_L0S; ++ upstream |= PCI_EXP_LNKCTL_ASPM_L0S; + if (state & ASPM_STATE_L1) { +- upstream |= PCIE_LINK_STATE_L1; +- dwstream |= PCIE_LINK_STATE_L1; ++ upstream |= PCI_EXP_LNKCTL_ASPM_L1; ++ dwstream |= PCI_EXP_LNKCTL_ASPM_L1; + } + /* + * Spec 2.0 suggests all functions should be configured the +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index bc92c47..757c9d2 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch new file mode 100644 index 00000000..f8b91a59 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_probe.c.patch @@ -0,0 +1,14 @@ +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -865,7 +865,8 @@ void set_pcie_port_type(struct pci_dev *pdev) + pdev->is_pcie = 1; + pdev->pcie_cap = pos; + pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); +- pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; ++ pdev->pcie_flags_reg = reg16; ++ pdev->pcie_type = pci_pcie_type(pdev); + pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); + pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; + } +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 481b184..1351477 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch new file mode 100644 index 00000000..b0534ef9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_quirks.c.patch @@ -0,0 +1,63 @@ +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -2256,6 +2256,58 @@ static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev) + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); + #endif /* CONFIG_TILE */ + ++/* Uncorrectable PCIe errors are generated when using the BCM56150 ++ * operating at Gen2 (5GT/s) link speed on the E1050 platform ++ * These errors are not observed when operating at Gen1 (2.5GT/s) ++ * link speed. There are two BCM56150 devices on the E1050 ++ * platform (bus 1 and 2), force both to Gen1 speed. This is ++ * done via the root complex since that is the only way to force ++ * the link to retrain. 0x50 is the Link Control PCIe capability ++ * register on the root complex, 0x70 is the Link Control2 PCIe ++ * PCIe capability register on the root complex. ++ * ++ * NOTE: This patch is a workaround and is not intended to be ++ * upstreamed. This specific issue is not seen with Linux kernel ++ * 3.16 and may be specific to backported (or lack of backported) ++ * Intel Bay Trail patches from 3.16 to 3.2 ++ */ ++static void __devinit quirk_bcm56150_gen1(struct pci_dev *dev) ++{ ++ u16 config; ++ struct pci_dev *pdev = NULL; ++ ++ /* Only interested in BCM56150 function 0 */ ++ if (PCI_FUNC(dev->devfn)) ++ return; ++ /* Find Intel PCIe root complex function 0 */ ++ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0f48, NULL); ++ if (!pdev) { ++ printk(KERN_INFO "E1050: Could not find Intel PCIe-RC fn 0\n"); ++ return; ++ } ++ if (dev->bus->number == 2) { ++ /* If this is the second BCM56150, then find Intel PCIe RC function 1 */ ++ pdev = pci_get_slot(pdev->bus, ++ PCI_DEVFN(PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)+1)); ++ if (!pdev) { ++ printk(KERN_INFO "E1050: Could not find Intel PCIe-RC fn 1\n"); ++ return; ++ } ++ } ++ /* Set link speed to 2.5GT/s */ ++ pci_read_config_word(pdev, 0x70, &config); ++ config &= ~0xf; ++ config |= 0x1; ++ pci_write_config_word(pdev, 0x70, config); ++ /* Initiate link re-training */ ++ pci_read_config_word(pdev, 0x50, &config); ++ config |= PCI_EXP_LNKCTL_RL; ++ pci_write_config_word(pdev, 0x50, config); ++ mdelay(50); ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, 0xb150, quirk_bcm56150_gen1); ++DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_BROADCOM, 0xb150, quirk_bcm56150_gen1); ++ + #ifdef CONFIG_PCI_MSI + /* Some chipsets do not support MSI. We cannot easily rely on setting + * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually +diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c +index 41f08e5..8d1ee41 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch new file mode 100644 index 00000000..5b3fa398 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_pci_setup-res.c.patch @@ -0,0 +1,17 @@ +--- a/drivers/pci/setup-res.c ++++ b/drivers/pci/setup-res.c +@@ -85,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno) + } + } + res->flags &= ~IORESOURCE_UNSET; +- dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", +- resno, res, (unsigned long long)region.start, +- (unsigned long long)region.end); ++ dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", ++ resno, res, (unsigned long long)region.start, ++ (unsigned long long)region.end); + } + + int pci_claim_resource(struct pci_dev *dev, int resource) +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 7f43cf8..cb2c255 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch new file mode 100644 index 00000000..893450ee --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_hctosys.c.patch @@ -0,0 +1,86 @@ +--- a/drivers/rtc/hctosys.c ++++ b/drivers/rtc/hctosys.c +@@ -24,6 +24,57 @@ + + int rtc_hctosys_ret = -ENODEV; + ++// Approximately the number of seconds in a 42 year span ++#define SECONDS_IN_42_YEARS (42 * 365 * 24 * 3600) ++ ++static int __init rtc_hc_fixup(struct rtc_device *rtc, struct rtc_time *p_tm) ++{ ++ int err = 0; ++ ++ /* ++ * rtc_time_to_tm() converts seconds since 1970-01-01 to a ++ * struct rtc_time. ++ * ++ * Some RTC drivers only store (year % 100) and assume 2000 on ++ * read back. For example when storing 1970, only 70 is ++ * stored in the hardware, but on read back it would be 2070. ++ * ++ * To work around this, pick a default date/time with the ++ * year > 2000. ++ * ++ * Adding 42 years worth of seconds puts the default date/time ++ * near 2012. ++ * ++ * As this code is being written in 2013, a default time ++ * around 2012 is safe to assume. ++ * ++ */ ++ rtc_time_to_tm(SECONDS_IN_42_YEARS, p_tm); ++ err = rtc_set_time(rtc, p_tm); ++ ++ if (err) { ++ dev_err(rtc->dev.parent, ++ "hc_fixup: unable to set hardware clock date/time\n"); ++ return err; ++ } ++ ++ err = rtc_read_time(rtc, p_tm); ++ if (err) { ++ dev_err(rtc->dev.parent, ++ "hc_fixup: unable to read the hardware clock\n"); ++ return err; ++ } ++ ++ err = rtc_valid_tm(p_tm); ++ if (err) { ++ dev_err(rtc->dev.parent, ++ "hc_fixup: unable to fix-up invalid date/time\n"); ++ return err; ++ } ++ ++ return err; ++} ++ + static int __init rtc_hctosys(void) + { + int err = -ENODEV; +@@ -43,15 +94,20 @@ static int __init rtc_hctosys(void) + if (err) { + dev_err(rtc->dev.parent, + "hctosys: unable to read the hardware clock\n"); +- goto err_read; +- ++ err = rtc_hc_fixup(rtc, &tm); ++ if (err) { ++ goto err_read; ++ } + } + + err = rtc_valid_tm(&tm); + if (err) { + dev_err(rtc->dev.parent, + "hctosys: invalid date/time\n"); +- goto err_invalid; ++ err = rtc_hc_fixup(rtc, &tm); ++ if (err) { ++ goto err_invalid; ++ } + } + + rtc_tm_to_time(&tm, &tv.tv_sec); +diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c +index 64aedd8..51a6298 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch new file mode 100644 index 00000000..711e6b90 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-m41t80.c.patch @@ -0,0 +1,170 @@ +--- a/drivers/rtc/rtc-m41t80.c ++++ b/drivers/rtc/rtc-m41t80.c +@@ -93,25 +93,32 @@ static int m41t80_get_datetime(struct i2c_client *client, + struct rtc_time *tm) + { + u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC }; +- struct i2c_msg msgs[] = { +- { +- .addr = client->addr, +- .flags = 0, +- .len = 1, +- .buf = dt_addr, +- }, +- { +- .addr = client->addr, +- .flags = I2C_M_RD, +- .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, +- .buf = buf + M41T80_REG_SEC, +- }, +- }; +- +- if (i2c_transfer(client->adapter, msgs, 2) < 0) { +- dev_err(&client->dev, "read error\n"); +- return -EIO; +- } ++ /* struct i2c_msg msgs[] = { */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = 0, */ ++ /* .len = 1, */ ++ /* .buf = dt_addr, */ ++ /* }, */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = I2C_M_RD, */ ++ /* .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, */ ++ /* .buf = buf + M41T80_REG_SEC, */ ++ /* }, */ ++ /* }; */ ++ ++ /* if (i2c_transfer(client->adapter, msgs, 2) < 0) { */ ++ /* dev_err(&client->dev, "read error\n"); */ ++ /* return -EIO; */ ++ /* } */ ++ buf[M41T80_REG_YEAR] = i2c_smbus_read_byte_data(client, M41T80_REG_YEAR); ++ buf[M41T80_REG_MON] = i2c_smbus_read_byte_data(client, M41T80_REG_MON); ++ buf[M41T80_REG_WDAY] = i2c_smbus_read_byte_data(client, M41T80_REG_WDAY); ++ buf[M41T80_REG_DAY] = i2c_smbus_read_byte_data(client, M41T80_REG_DAY); ++ buf[M41T80_REG_HOUR] = i2c_smbus_read_byte_data(client, M41T80_REG_HOUR); ++ buf[M41T80_REG_MIN] = i2c_smbus_read_byte_data(client, M41T80_REG_MIN); ++ buf[M41T80_REG_SEC] = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); + + tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f); + tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f); +@@ -129,36 +136,46 @@ static int m41t80_get_datetime(struct i2c_client *client, + static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) + { + u8 wbuf[1 + M41T80_DATETIME_REG_SIZE]; ++ int rc = 0; + u8 *buf = &wbuf[1]; + u8 dt_addr[1] = { M41T80_REG_SEC }; +- struct i2c_msg msgs_in[] = { +- { +- .addr = client->addr, +- .flags = 0, +- .len = 1, +- .buf = dt_addr, +- }, +- { +- .addr = client->addr, +- .flags = I2C_M_RD, +- .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, +- .buf = buf + M41T80_REG_SEC, +- }, +- }; +- struct i2c_msg msgs[] = { +- { +- .addr = client->addr, +- .flags = 0, +- .len = 1 + M41T80_DATETIME_REG_SIZE, +- .buf = wbuf, +- }, +- }; ++ /* struct i2c_msg msgs_in[] = { */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = 0, */ ++ /* .len = 1, */ ++ /* .buf = dt_addr, */ ++ /* }, */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = I2C_M_RD, */ ++ /* .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, */ ++ /* .buf = buf + M41T80_REG_SEC, */ ++ /* }, */ ++ /* }; */ ++ /* struct i2c_msg msgs[] = { */ ++ /* { */ ++ /* .addr = client->addr, */ ++ /* .flags = 0, */ ++ /* .len = 1 + M41T80_DATETIME_REG_SIZE, */ ++ /* .buf = wbuf, */ ++ /* }, */ ++ /* }; */ ++ ++ /* /\* Read current reg values into buf[1..7] *\/ */ ++ /* if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { */ ++ /* dev_err(&client->dev, "read error\n"); */ ++ /* return -EIO; */ ++ /* } */ ++ buf[M41T80_REG_YEAR] = i2c_smbus_read_byte_data(client, M41T80_REG_YEAR); ++ buf[M41T80_REG_MON] = i2c_smbus_read_byte_data(client, M41T80_REG_MON); ++ buf[M41T80_REG_WDAY] = i2c_smbus_read_byte_data(client, M41T80_REG_WDAY); ++ buf[M41T80_REG_DAY] = i2c_smbus_read_byte_data(client, M41T80_REG_DAY); ++ buf[M41T80_REG_HOUR] = i2c_smbus_read_byte_data(client, M41T80_REG_HOUR); ++ buf[M41T80_REG_MIN] = i2c_smbus_read_byte_data(client, M41T80_REG_MIN); ++ buf[M41T80_REG_SEC] = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); ++ + +- /* Read current reg values into buf[1..7] */ +- if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { +- dev_err(&client->dev, "read error\n"); +- return -EIO; +- } + + wbuf[0] = 0; /* offset into rtc's regs */ + /* Merge time-data and register flags into buf[0..7] */ +@@ -178,10 +195,25 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) + /* assume 20YY not 19YY */ + buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100); + +- if (i2c_transfer(client->adapter, msgs, 1) != 1) { +- dev_err(&client->dev, "write error\n"); ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_YEAR, buf[M41T80_REG_YEAR]) < 0) + return -EIO; +- } ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_MON, buf[M41T80_REG_MON]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_DAY, buf[M41T80_REG_DAY]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_WDAY, buf[M41T80_REG_WDAY]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_HOUR, buf[M41T80_REG_HOUR]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_MIN, buf[M41T80_REG_MIN]) < 0) ++ return -EIO; ++ if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC, buf[M41T80_REG_SEC]) < 0) ++ return -EIO; ++ ++ /* if (i2c_transfer(client->adapter, msgs, 1) != 1) { */ ++ /* dev_err(&client->dev, "write error\n"); */ ++ /* return -EIO; */ ++ /* } */ + return 0; + } + +@@ -777,8 +809,8 @@ static int m41t80_probe(struct i2c_client *client, + struct rtc_time tm; + struct m41t80_data *clientdata = NULL; + +- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C +- | I2C_FUNC_SMBUS_BYTE_DATA)) { ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ + rc = -ENODEV; + goto exit; + } +diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c +index 768e2ed..0dd8421 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch new file mode 100644 index 00000000..56c2829d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-mv.c.patch @@ -0,0 +1,32 @@ +--- a/drivers/rtc/rtc-mv.c ++++ b/drivers/rtc/rtc-mv.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -294,11 +295,19 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) + return 0; + } + ++#ifdef CONFIG_OF ++static struct of_device_id rtc_mv_of_match_table[] = { ++ { .compatible = "mrvl,orion-rtc", }, ++ {} ++}; ++#endif ++ + static struct platform_driver mv_rtc_driver = { + .remove = __exit_p(mv_rtc_remove), + .driver = { + .name = "rtc-mv", + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(rtc_mv_of_match_table), + }, + }; + +diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c +index f789e00..5208bec 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch new file mode 100644 index 00000000..a29872bd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_rtc_rtc-s35390a.c.patch @@ -0,0 +1,161 @@ +--- a/drivers/rtc/rtc-s35390a.c ++++ b/drivers/rtc/rtc-s35390a.c +@@ -19,6 +19,8 @@ + #define S35390A_CMD_STATUS1 0 + #define S35390A_CMD_STATUS2 1 + #define S35390A_CMD_TIME1 2 ++#define S35390A_CMD_TIME2 3 ++#define S35390A_CMD_INT2_REG1 5 + + #define S35390A_BYTE_YEAR 0 + #define S35390A_BYTE_MONTH 1 +@@ -28,12 +30,23 @@ + #define S35390A_BYTE_MINS 5 + #define S35390A_BYTE_SECS 6 + ++#define S35390A_ALRM_BYTE_WDAY 0 ++#define S35390A_ALRM_BYTE_HOURS 1 ++#define S35390A_ALRM_BYTE_MINS 2 ++ + #define S35390A_FLAG_POC 0x01 + #define S35390A_FLAG_BLD 0x02 + #define S35390A_FLAG_24H 0x40 + #define S35390A_FLAG_RESET 0x80 + #define S35390A_FLAG_TEST 0x01 + ++#define S35390A_INT2_MODE_MASK 0xF0 ++ ++#define S35390A_INT2_MODE_NOINTR 0x00 ++#define S35390A_INT2_MODE_FREQ 0x10 ++#define S35390A_INT2_MODE_ALARM 0x40 ++#define S35390A_INT2_MODE_PMIN_EDG 0x20 ++ + static const struct i2c_device_id s35390a_id[] = { + { "s35390a", 0 }, + { } +@@ -184,6 +197,104 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) + return rtc_valid_tm(tm); + } + ++static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) ++{ ++ struct s35390a *s35390a = i2c_get_clientdata(client); ++ char buf[3], sts = 0; ++ int err, i; ++ ++ dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ ++ "mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec, ++ alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, ++ alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); ++ ++ /* disable interrupt */ ++ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ /* clear pending interrupt, if any */ ++ err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ if (alm->enabled) ++ sts = S35390A_INT2_MODE_ALARM; ++ else ++ sts = S35390A_INT2_MODE_NOINTR; ++ ++ /* This chip expects the bits of each byte to be in reverse order */ ++ sts = bitrev8(sts); ++ ++ /* set interupt mode*/ ++ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ if (alm->time.tm_wday != -1) ++ buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; ++ ++ buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, ++ alm->time.tm_hour) | 0x80; ++ buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80; ++ ++ if (alm->time.tm_hour >= 12) ++ buf[S35390A_ALRM_BYTE_HOURS] |= 0x40; ++ ++ for (i = 0; i < 3; ++i) ++ buf[i] = bitrev8(buf[i]); ++ ++ err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf, ++ sizeof(buf)); ++ ++ return err; ++} ++ ++static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) ++{ ++ struct s35390a *s35390a = i2c_get_clientdata(client); ++ char buf[3], sts; ++ int i, err; ++ ++ err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); ++ if (err < 0) ++ return err; ++ ++ if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) ++ return -EINVAL; ++ ++ err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); ++ if (err < 0) ++ return err; ++ ++ /* This chip returns the bits of each byte in reverse order */ ++ for (i = 0; i < 3; ++i) { ++ buf[i] = bitrev8(buf[i]); ++ buf[i] &= ~0x80; ++ } ++ ++ alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); ++ alm->time.tm_hour = s35390a_reg2hr(s35390a, ++ buf[S35390A_ALRM_BYTE_HOURS]); ++ alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); ++ ++ dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", ++ __func__, alm->time.tm_min, alm->time.tm_hour, ++ alm->time.tm_wday); ++ ++ return 0; ++} ++ ++static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) ++{ ++ return s35390a_read_alarm(to_i2c_client(dev), alm); ++} ++ ++static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) ++{ ++ return s35390a_set_alarm(to_i2c_client(dev), alm); ++} ++ + static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) + { + return s35390a_get_datetime(to_i2c_client(dev), tm); +@@ -197,6 +308,9 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) + static const struct rtc_class_ops s35390a_rtc_ops = { + .read_time = s35390a_rtc_read_time, + .set_time = s35390a_rtc_set_time, ++ .set_alarm = s35390a_rtc_set_alarm, ++ .read_alarm = s35390a_rtc_read_alarm, ++ + }; + + static struct i2c_driver s35390a_driver; +@@ -261,6 +375,8 @@ static int s35390a_probe(struct i2c_client *client, + if (s35390a_get_datetime(client, &tm) < 0) + dev_warn(&client->dev, "clock needs to be set\n"); + ++ device_set_wakeup_capable(&client->dev, 1); ++ + s35390a->rtc = rtc_device_register(s35390a_driver.driver.name, + &client->dev, &s35390a_rtc_ops, THIS_MODULE); + +diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c +index 95b909a..3c03c10 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch new file mode 100644 index 00000000..6bdc0448 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_cyclades.c.patch @@ -0,0 +1,16 @@ +--- a/drivers/tty/cyclades.c ++++ b/drivers/tty/cyclades.c +@@ -3543,10 +3543,8 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, + int retval; + + retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev); +- if (retval) { +- dev_err(&pdev->dev, "can't get firmware\n"); ++ if (retval) + goto err; +- } + + /* Check whether the firmware is already loaded and running. If + positive, skip this board */ +diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c +index fc3c3ad..4cc036f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch new file mode 100644 index 00000000..f3c44456 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_moxa.c.patch @@ -0,0 +1,19 @@ +--- a/drivers/tty/moxa.c ++++ b/drivers/tty/moxa.c +@@ -867,13 +867,8 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) + } + + ret = request_firmware(&fw, file, dev); +- if (ret) { +- printk(KERN_ERR "MOXA: request_firmware failed. Make sure " +- "you've placed '%s' file into your firmware " +- "loader directory (e.g. /lib/firmware)\n", +- file); ++ if (ret) + goto err_free; +- } + + ret = moxa_load_fw(brd, fw); + +diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c +index d55709a..0ee5294 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch new file mode 100644 index 00000000..c78a7d1e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_icom.c.patch @@ -0,0 +1,28 @@ +--- a/drivers/tty/serial/icom.c ++++ b/drivers/tty/serial/icom.c +@@ -374,7 +374,6 @@ static void load_code(struct icom_port *icom_port) + + /* Load Call Setup into Adapter */ + if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) { +- dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n"); + status = -1; + goto load_code_exit; + } +@@ -394,7 +393,6 @@ static void load_code(struct icom_port *icom_port) + + /* Load Resident DCE portion of Adapter */ + if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) { +- dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n"); + status = -1; + goto load_code_exit; + } +@@ -439,7 +437,6 @@ static void load_code(struct icom_port *icom_port) + } + + if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) { +- dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n"); + status = -1; + goto load_code_exit; + } +diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c +index cea8918..97eab95 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch new file mode 100644 index 00000000..0b3b093e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_tty_serial_ucc_uart.c.patch @@ -0,0 +1,16 @@ +--- a/drivers/tty/serial/ucc_uart.c ++++ b/drivers/tty/serial/ucc_uart.c +@@ -1173,10 +1173,8 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) + struct device *dev = context; + int ret; + +- if (!fw) { +- dev_err(dev, "firmware not found\n"); ++ if (!fw) + return; +- } + + firmware = (struct qe_firmware *) fw->data; + +diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c +index 9497171..07458c0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch new file mode 100644 index 00000000..6296779d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hcd.c.patch @@ -0,0 +1,63 @@ +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -200,11 +200,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, + /* check TDI/ARC silicon is in host mode */ + static int tdi_in_host_mode (struct ehci_hcd *ehci) + { +- u32 __iomem *reg_ptr; + u32 tmp; + +- reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); +- tmp = ehci_readl(ehci, reg_ptr); ++ tmp = ehci_readl(ehci, &ehci->regs->usbmode); + return (tmp & 3) == USBMODE_CM_HC; + } + +@@ -249,11 +247,9 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, + /* put TDI/ARC silicon into EHCI mode */ + static void tdi_reset (struct ehci_hcd *ehci) + { +- u32 __iomem *reg_ptr; + u32 tmp; + +- reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); +- tmp = ehci_readl(ehci, reg_ptr); ++ tmp = ehci_readl(ehci, &ehci->regs->usbmode); + tmp |= USBMODE_CM_HC; + /* The default byte access to MMR space is LE after + * controller reset. Set the required endian mode +@@ -261,7 +257,7 @@ static void tdi_reset (struct ehci_hcd *ehci) + */ + if (ehci_big_endian_mmio(ehci)) + tmp |= USBMODE_BE; +- ehci_writel(ehci, tmp, reg_ptr); ++ ehci_writel(ehci, tmp, &ehci->regs->usbmode); + } + + /* reset a non-running (STS_HALT == 1) controller */ +@@ -285,9 +281,8 @@ static int ehci_reset (struct ehci_hcd *ehci) + + if (ehci->has_hostpc) { + ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, +- (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX)); +- ehci_writel(ehci, TXFIFO_DEFAULT, +- (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING)); ++ &ehci->regs->usbmode_ex); ++ ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning); + } + if (retval) + return retval; +@@ -1344,6 +1339,11 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_xls_driver + #endif + ++#ifdef CONFIG_USB_EHCI_BCM ++#include "../../bcmdrivers/usb2h/ehci-bcm.c" ++#define PLATFORM_DRIVER ehci_bcm_driver ++#endif ++ + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ + !defined(XILINX_OF_PLATFORM_DRIVER) +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index 4527b90..d304f9d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch new file mode 100644 index 00000000..e38f7682 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ehci-hub.c.patch @@ -0,0 +1,91 @@ +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -149,10 +149,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, + if (ehci->has_hostpc) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * port); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); + } +@@ -185,10 +183,8 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, + if (ehci->has_hostpc) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * port); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); + } +@@ -311,11 +307,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) + spin_lock_irq(&ehci->lock); + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; + u32 t3; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * port); + t3 = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); + t3 = ehci_readl(ehci, hostpc_reg); +@@ -413,10 +407,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd) + i = HCS_N_PORTS(ehci->hcs_params); + while (i--) { + if (test_bit(i, &ehci->bus_suspended)) { +- u32 __iomem *hostpc_reg; ++ u32 __iomem *hostpc_reg = ++ &ehci->regs->hostpc[i]; + +- hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs +- + HOSTPC0 + 4 * i); + temp = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp & ~HOSTPC_PHCD, + hostpc_reg); +@@ -690,7 +683,7 @@ static int ehci_hub_control ( + int ports = HCS_N_PORTS (ehci->hcs_params); + u32 __iomem *status_reg = &ehci->regs->port_status[ + (wIndex & 0xff) - 1]; +- u32 __iomem *hostpc_reg = NULL; ++ u32 __iomem *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1]; + u32 temp, temp1, status; + unsigned long flags; + int retval = 0; +@@ -703,9 +696,6 @@ static int ehci_hub_control ( + * power, "this is the one", etc. EHCI spec supports this. + */ + +- if (ehci->has_hostpc) +- hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs +- + HOSTPC0 + 4 * ((wIndex & 0xff) - 1)); + spin_lock_irqsave (&ehci->lock, flags); + switch (typeReq) { + case ClearHubFeature: +@@ -757,7 +747,7 @@ static int ehci_hub_control ( + goto error; + + /* clear phy low-power mode before resume */ +- if (hostpc_reg) { ++ if (ehci->has_hostpc) { + temp1 = ehci_readl(ehci, hostpc_reg); + ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, + hostpc_reg); +@@ -1005,7 +995,7 @@ static int ehci_hub_control ( + temp &= ~PORT_WKCONN_E; + temp |= PORT_WKDISC_E | PORT_WKOC_E; + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); +- if (hostpc_reg) { ++ if (ehci->has_hostpc) { + spin_unlock_irqrestore(&ehci->lock, flags); + msleep(5);/* 5ms for HCD enter low pwr mode */ + spin_lock_irqsave(&ehci->lock, flags); +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index b263919..e4dfafa 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch new file mode 100644 index 00000000..89df7fc5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_host_ohci-hcd.c.patch @@ -0,0 +1,17 @@ +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -1116,6 +1116,12 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ohci_xls_driver + #endif + ++#ifdef CONFIG_USB_OHCI_BCM ++#include "../../bcmdrivers/usb2h/ohci-bcm.c" ++#define PLATFORM_DRIVER ohci_bcm_driver ++#endif ++ ++ + #if !defined(PCI_DRIVER) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(OMAP1_PLATFORM_DRIVER) && \ +diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c +index a6521c9..9da3f48 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch new file mode 100644 index 00000000..0755eee1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi26.c.patch @@ -0,0 +1,29 @@ +--- a/drivers/usb/misc/emi26.c ++++ b/drivers/usb/misc/emi26.c +@@ -96,21 +96,17 @@ static int emi26_load_firmware (struct usb_device *dev) + + err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw", + &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw", + &dev->dev); +- if (err) { +- nofw: +- dev_err(&dev->dev, "%s - request_firmware() failed\n", +- __func__); ++ if (err) + goto wraperr; +- } + + /* Assert reset (stop the CPU in the EMI) */ + err = emi26_set_reset(dev,1); +diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c +index 723e833..1941439 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch new file mode 100644 index 00000000..8721ee88 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_misc_emi62.c.patch @@ -0,0 +1,27 @@ +--- a/drivers/usb/misc/emi62.c ++++ b/drivers/usb/misc/emi62.c +@@ -105,19 +105,16 @@ static int emi62_load_firmware (struct usb_device *dev) + + err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&bitstream_fw, "emi62/bitstream.fw", + &dev->dev); + if (err) +- goto nofw; ++ goto wraperr; + + err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev); +- if (err) { +- nofw: +- err( "%s - request_firmware() failed", __func__); ++ if (err) + goto wraperr; +- } + + /* Assert reset (stop the CPU in the EMI) */ + err = emi62_set_reset(dev,1); +diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c +index 8f725f6..334744f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch new file mode 100644 index 00000000..4e4c1da0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_edgeport.c.patch @@ -0,0 +1,17 @@ +--- a/drivers/usb/serial/io_edgeport.c ++++ b/drivers/usb/serial/io_edgeport.c +@@ -308,11 +308,8 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) + + response = request_ihex_firmware(&fw, fw_name, + &edge_serial->serial->dev->dev); +- if (response) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, response); ++ if (response) + return; +- } + + rec = (const struct ihex_binrec *)fw->data; + BootMajorVersion = rec->data[0]; +diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c +index 438138f..f05abe8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch new file mode 100644 index 00000000..7b347562 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_io_ti.c.patch @@ -0,0 +1,22 @@ +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -886,8 +886,6 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) + + err = request_firmware(&fw, fw_name, dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, err); + kfree(buffer); + return err; + } +@@ -1452,8 +1450,6 @@ static int download_fw(struct edgeport_serial *serial) + + err = request_firmware(&fw, fw_name, dev); + if (err) { +- printk(KERN_ERR "Failed to load image \"%s\" err %d\n", +- fw_name, err); + kfree(buffer); + return err; + } +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index e9b39e3..472fddb 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch new file mode 100644 index 00000000..8e87edf2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan.c.patch @@ -0,0 +1,16 @@ +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -1419,10 +1419,8 @@ static int keyspan_fake_startup(struct usb_serial *serial) + return 1; + } + +- if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { +- dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); ++ if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) + return(1); +- } + + dbg("Uploading Keyspan %s firmware.", fw_name); + +diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c +index 661a1a2..91091b0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch new file mode 100644 index 00000000..8f3583e8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_keyspan_pda.c.patch @@ -0,0 +1,17 @@ +--- a/drivers/usb/serial/keyspan_pda.c ++++ b/drivers/usb/serial/keyspan_pda.c +@@ -768,11 +768,8 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) + __func__); + return -ENODEV; + } +- if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { +- dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n", +- fw_name); ++ if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) + return -ENOENT; +- } + record = (const struct ihex_binrec *)fw->data; + + while (record) { +diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c +index 885d15d..7a27c18 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch new file mode 100644 index 00000000..220a3c31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_ti_usb_3410_5052.c.patch @@ -0,0 +1,16 @@ +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -1747,10 +1747,8 @@ static int ti_download_firmware(struct ti_device *tdev) + } + status = request_firmware(&fw_p, buf, &dev->dev); + } +- if (status) { +- dev_err(&dev->dev, "%s - firmware not found\n", __func__); ++ if (status) + return -ENOENT; +- } + if (fw_p->size > TI_FIRMWARE_BUF_SIZE) { + dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size); + release_firmware(fw_p); +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index 5481809..2c9a1a4 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch new file mode 100644 index 00000000..d71095df --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_usb_serial_whiteheat.c.patch @@ -0,0 +1,25 @@ +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -301,18 +301,11 @@ static int whiteheat_firmware_download(struct usb_serial *serial, + dbg("%s", __func__); + + if (request_ihex_firmware(&firmware_fw, "whiteheat.fw", +- &serial->dev->dev)) { +- dev_err(&serial->dev->dev, +- "%s - request \"whiteheat.fw\" failed\n", __func__); ++ &serial->dev->dev)) + goto out; +- } + if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw", +- &serial->dev->dev)) { +- dev_err(&serial->dev->dev, +- "%s - request \"whiteheat_loader.fw\" failed\n", +- __func__); ++ &serial->dev->dev)) + goto out; +- } + ret = 0; + response = ezusb_set_reset (serial, 1); + +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index d83e967..fe92039 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch new file mode 100644 index 00000000..26e702b4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Kconfig.patch @@ -0,0 +1,24 @@ +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -545,6 +545,19 @@ config I6300ESB_WDT + To compile this driver as a module, choose M here: the + module will be called i6300esb. + ++config IE6XX_WDT ++ tristate "Intel Atom E6xx Watchdog" ++ depends on X86 && PCI ++ select WATCHDOG_CORE ++ select MFD_CORE ++ select LPC_SCH ++ ---help--- ++ Hardware driver for the watchdog timer built into the Intel ++ Atom E6XX (TunnelCreek) processor. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ie6xx_wdt. ++ + config INTEL_SCU_WATCHDOG + bool "Intel SCU Watchdog for Mobile Platforms" + depends on X86_MRST +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +index fe893e9..8f591c5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch new file mode 100644 index 00000000..4ec330d2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_Makefile.patch @@ -0,0 +1,12 @@ +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -81,6 +81,7 @@ obj-$(CONFIG_IB700_WDT) += ib700wdt.o + obj-$(CONFIG_IBMASR) += ibmasr.o + obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o + obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o ++obj-$(CONFIG_IE6XX_WDT) += ie6xx_wdt.o + obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o + ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) + obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o +diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c +index 337265b..2af9c3a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch new file mode 100644 index 00000000..d34fcb65 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_booke_wdt.c.patch @@ -0,0 +1,314 @@ +--- a/drivers/watchdog/booke_wdt.c ++++ b/drivers/watchdog/booke_wdt.c +@@ -12,16 +12,13 @@ + * option) any later version. + */ + ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ + #include +-#include + #include +-#include +-#include + #include +-#include + + #include +-#include + #include + #include + +@@ -33,10 +30,8 @@ + * occur, and the final time the board will reset. + */ + +-u32 booke_wdt_enabled; +-u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; + +-#ifdef CONFIG_FSL_BOOKE ++#ifdef CONFIG_PPC_FSL_BOOK3E + #define WDTP(x) ((((x)&0x3)<<30)|(((x)&0x3c)<<15)) + #define WDTP_MASK (WDTP(0x3f)) + #else +@@ -44,7 +39,12 @@ u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; + #define WDTP_MASK (TCR_WP_MASK) + #endif + +-static DEFINE_SPINLOCK(booke_wdt_lock); ++static bool booke_wdt_enabled; ++module_param(booke_wdt_enabled, bool, 0); ++static int booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; ++module_param(booke_wdt_period, int, 0); ++ ++#ifdef CONFIG_PPC_FSL_BOOK3E + + /* For the specified period, determine the number of seconds + * corresponding to the reset time. There will be a watchdog +@@ -85,20 +85,39 @@ static unsigned int sec_to_period(unsigned int secs) + return 0; + } + ++#define MAX_WDT_TIMEOUT period_to_sec(1) ++ ++#else /* CONFIG_PPC_FSL_BOOK3E */ ++ ++static unsigned long long period_to_sec(unsigned int period) ++{ ++ return period; ++} ++ ++static unsigned int sec_to_period(unsigned int secs) ++{ ++ return secs; ++} ++ ++#define MAX_WDT_TIMEOUT 3 /* from Kconfig */ ++ ++#endif /* !CONFIG_PPC_FSL_BOOK3E */ ++ + static void __booke_wdt_set(void *data) + { + u32 val; ++ struct watchdog_device *wdog = data; + + val = mfspr(SPRN_TCR); + val &= ~WDTP_MASK; +- val |= WDTP(booke_wdt_period); ++ val |= WDTP(sec_to_period(wdog->timeout)); + + mtspr(SPRN_TCR, val); + } + +-static void booke_wdt_set(void) ++static void booke_wdt_set(void *data) + { +- on_each_cpu(__booke_wdt_set, NULL, 0); ++ on_each_cpu(__booke_wdt_set, data, 0); + } + + static void __booke_wdt_ping(void *data) +@@ -106,20 +125,23 @@ static void __booke_wdt_ping(void *data) + mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); + } + +-static void booke_wdt_ping(void) ++static int booke_wdt_ping(struct watchdog_device *wdog) + { + on_each_cpu(__booke_wdt_ping, NULL, 0); ++ ++ return 0; + } + + static void __booke_wdt_enable(void *data) + { + u32 val; ++ struct watchdog_device *wdog = data; + + /* clear status before enabling watchdog */ + __booke_wdt_ping(NULL); + val = mfspr(SPRN_TCR); + val &= ~WDTP_MASK; +- val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); ++ val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(sec_to_period(wdog->timeout))); + + mtspr(SPRN_TCR, val); + } +@@ -145,149 +167,73 @@ static void __booke_wdt_disable(void *data) + + } + +-static ssize_t booke_wdt_write(struct file *file, const char __user *buf, +- size_t count, loff_t *ppos) ++static int booke_wdt_start(struct watchdog_device *wdog) + { +- booke_wdt_ping(); +- return count; +-} +- +-static struct watchdog_info ident = { +- .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +- .identity = "PowerPC Book-E Watchdog", +-}; +- +-static long booke_wdt_ioctl(struct file *file, +- unsigned int cmd, unsigned long arg) +-{ +- u32 tmp = 0; +- u32 __user *p = (u32 __user *)arg; +- +- switch (cmd) { +- case WDIOC_GETSUPPORT: +- if (copy_to_user((void *)arg, &ident, sizeof(ident))) +- return -EFAULT; +- case WDIOC_GETSTATUS: +- return put_user(0, p); +- case WDIOC_GETBOOTSTATUS: +- /* XXX: something is clearing TSR */ +- tmp = mfspr(SPRN_TSR) & TSR_WRS(3); +- /* returns CARDRESET if last reset was caused by the WDT */ +- return (tmp ? WDIOF_CARDRESET : 0); +- case WDIOC_SETOPTIONS: +- if (get_user(tmp, p)) +- return -EINVAL; +- if (tmp == WDIOS_ENABLECARD) { +- booke_wdt_ping(); +- break; +- } else +- return -EINVAL; +- return 0; +- case WDIOC_KEEPALIVE: +- booke_wdt_ping(); +- return 0; +- case WDIOC_SETTIMEOUT: +- if (get_user(tmp, p)) +- return -EFAULT; +-#ifdef CONFIG_FSL_BOOKE +- /* period of 1 gives the largest possible timeout */ +- if (tmp > period_to_sec(1)) +- return -EINVAL; +- booke_wdt_period = sec_to_period(tmp); +-#else +- booke_wdt_period = tmp; +-#endif +- booke_wdt_set(); +- return 0; +- case WDIOC_GETTIMEOUT: +- return put_user(booke_wdt_period, p); +- default: +- return -ENOTTY; +- } ++ on_each_cpu(__booke_wdt_enable, wdog, 0); ++ pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout); + + return 0; + } + +-/* wdt_is_active stores wether or not the /dev/watchdog device is opened */ +-static unsigned long wdt_is_active; +- +-static int booke_wdt_open(struct inode *inode, struct file *file) ++static int booke_wdt_stop(struct watchdog_device *wdog) + { +- /* /dev/watchdog can only be opened once */ +- if (test_and_set_bit(0, &wdt_is_active)) +- return -EBUSY; +- +- spin_lock(&booke_wdt_lock); +- if (booke_wdt_enabled == 0) { +- booke_wdt_enabled = 1; +- on_each_cpu(__booke_wdt_enable, NULL, 0); +- pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n", +- period_to_sec(booke_wdt_period)); +- } +- spin_unlock(&booke_wdt_lock); ++ on_each_cpu(__booke_wdt_disable, NULL, 0); ++ pr_debug("watchdog disabled\n"); + +- return nonseekable_open(inode, file); ++ return 0; + } + +-static int booke_wdt_release(struct inode *inode, struct file *file) ++static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, ++ unsigned int timeout) + { +-#ifndef CONFIG_WATCHDOG_NOWAYOUT +- /* Normally, the watchdog is disabled when /dev/watchdog is closed, but +- * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the +- * watchdog should remain enabled. So we disable it only if +- * CONFIG_WATCHDOG_NOWAYOUT is not defined. +- */ +- on_each_cpu(__booke_wdt_disable, NULL, 0); +- booke_wdt_enabled = 0; +- pr_debug("booke_wdt: watchdog disabled\n"); +-#endif +- +- clear_bit(0, &wdt_is_active); ++ if (timeout > MAX_WDT_TIMEOUT) ++ return -EINVAL; ++ wdt_dev->timeout = timeout; ++ booke_wdt_set(wdt_dev); + + return 0; + } + +-static const struct file_operations booke_wdt_fops = { ++static struct watchdog_info booke_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++ .identity = "PowerPC Book-E Watchdog", ++}; ++ ++static struct watchdog_ops booke_wdt_ops = { + .owner = THIS_MODULE, +- .llseek = no_llseek, +- .write = booke_wdt_write, +- .unlocked_ioctl = booke_wdt_ioctl, +- .open = booke_wdt_open, +- .release = booke_wdt_release, ++ .start = booke_wdt_start, ++ .stop = booke_wdt_stop, ++ .ping = booke_wdt_ping, ++ .set_timeout = booke_wdt_set_timeout, + }; + +-static struct miscdevice booke_wdt_miscdev = { +- .minor = WATCHDOG_MINOR, +- .name = "watchdog", +- .fops = &booke_wdt_fops, ++static struct watchdog_device booke_wdt_dev = { ++ .info = &booke_wdt_info, ++ .ops = &booke_wdt_ops, ++ .min_timeout = 1, ++ .max_timeout = 0xFFFFFFFF + }; + + static void __exit booke_wdt_exit(void) + { +- misc_deregister(&booke_wdt_miscdev); ++ watchdog_unregister_device(&booke_wdt_dev); + } + + static int __init booke_wdt_init(void) + { + int ret = 0; ++ bool nowayout = WATCHDOG_NOWAYOUT; + +- pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n"); +- ident.firmware_version = cur_cpu_spec->pvr_value; +- +- ret = misc_register(&booke_wdt_miscdev); +- if (ret) { +- pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n", +- WATCHDOG_MINOR, ret); +- return ret; +- } ++ pr_info("powerpc book-e watchdog driver loaded\n"); ++ booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value; ++ booke_wdt_set_timeout(&booke_wdt_dev, ++ period_to_sec(booke_wdt_period)); ++ booke_wdt_dev.timeout = period_to_sec(booke_wdt_period); ++ watchdog_set_nowayout(&booke_wdt_dev, nowayout); ++ if (booke_wdt_enabled) ++ booke_wdt_start(&booke_wdt_dev); + +- spin_lock(&booke_wdt_lock); +- if (booke_wdt_enabled == 1) { +- pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n", +- period_to_sec(booke_wdt_period)); +- on_each_cpu(__booke_wdt_enable, NULL, 0); +- } +- spin_unlock(&booke_wdt_lock); ++ ret = watchdog_register_device(&booke_wdt_dev); + + return ret; + } +@@ -295,5 +241,6 @@ static int __init booke_wdt_init(void) + module_init(booke_wdt_init); + module_exit(booke_wdt_exit); + ++MODULE_ALIAS("booke_wdt"); + MODULE_DESCRIPTION("PowerPC Book-E watchdog driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c +index bdf401b..590d62a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch new file mode 100644 index 00000000..9286a04d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_iTCO_wdt.c.patch @@ -0,0 +1,283 @@ +--- a/drivers/watchdog/iTCO_wdt.c ++++ b/drivers/watchdog/iTCO_wdt.c +@@ -128,6 +128,7 @@ enum iTCO_chipsets { + TCO_DH89XXCC, /* DH89xxCC */ + TCO_PPT, /* Panther Point */ + TCO_LPT, /* Lynx Point */ ++ TCO_AVN, /* Avoton */ + }; + + static struct { +@@ -192,6 +193,7 @@ static struct { + {"DH89xxCC", 2}, + {"Panther Point", 2}, + {"Lynx Point", 2}, ++ {"Avoton", 3}, + {NULL, 0} + }; + +@@ -334,6 +336,10 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { + { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT}, ++ { PCI_VDEVICE(INTEL, 0x1f38), TCO_AVN}, ++ { PCI_VDEVICE(INTEL, 0x1f39), TCO_AVN}, ++ { PCI_VDEVICE(INTEL, 0x1f3a), TCO_AVN}, ++ { PCI_VDEVICE(INTEL, 0x1f3b), TCO_AVN}, + { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT}, +@@ -394,8 +400,12 @@ static struct { /* this is private data for the iTCO_wdt device */ + unsigned int iTCO_version; + /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ + unsigned long ACPIBASE; +- /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ +- unsigned long __iomem *gcs; ++ /* ++ * NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2), ++ * or memory-mapped PMC register bit 4 (TCO version 3). ++ */ ++ unsigned long __iomem *gcs_pmc; ++ + /* the lock for io operations */ + spinlock_t io_lock; + /* the PCI-device */ +@@ -428,11 +438,19 @@ MODULE_PARM_DESC(turn_SMI_watchdog_clear_off, + * Some TCO specific functions + */ + +-static inline unsigned int seconds_to_ticks(int seconds) ++/* ++ * The iTCO v1 and v2's internal timer is stored as ticks which decrement ++ * every 0.6 seconds. v3's internal timer is stored as seconds (some ++ * datasheets incorrectly state 0.6 seconds). ++ */ ++static inline unsigned int seconds_to_ticks(int secs) ++{ ++ return iTCO_wdt_private.iTCO_version == 3 ? secs : (secs * 10) / 6; ++} ++ ++static inline unsigned int ticks_to_seconds(int ticks) + { +- /* the internal timer is stored as ticks which decrement +- * every 0.6 seconds */ +- return (seconds * 10) / 6; ++ return iTCO_wdt_private.iTCO_version == 3 ? ticks : (ticks * 6) / 10; + } + + static void iTCO_wdt_set_NO_REBOOT_bit(void) +@@ -440,10 +458,14 @@ static void iTCO_wdt_set_NO_REBOOT_bit(void) + u32 val32; + + /* Set the NO_REBOOT bit: this disables reboots */ +- if (iTCO_wdt_private.iTCO_version == 2) { +- val32 = readl(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version == 3) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); ++ val32 |= 0x00000010; ++ writel(val32, iTCO_wdt_private.gcs_pmc); ++ } else if (iTCO_wdt_private.iTCO_version >= 2) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); + val32 |= 0x00000020; +- writel(val32, iTCO_wdt_private.gcs); ++ writel(val32, iTCO_wdt_private.gcs_pmc); + } else if (iTCO_wdt_private.iTCO_version == 1) { + pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32); + val32 |= 0x00000002; +@@ -457,12 +479,20 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void) + u32 val32; + + /* Unset the NO_REBOOT bit: this enables reboots */ +- if (iTCO_wdt_private.iTCO_version == 2) { +- val32 = readl(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version == 3) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); ++ val32 &= 0xffffffef; ++ writel(val32, iTCO_wdt_private.gcs_pmc); ++ ++ val32 = readl(iTCO_wdt_private.gcs_pmc); ++ if (val32 & 0x00000010) ++ ret = -EIO; ++ } else if (iTCO_wdt_private.iTCO_version == 2) { ++ val32 = readl(iTCO_wdt_private.gcs_pmc); + val32 &= 0xffffffdf; +- writel(val32, iTCO_wdt_private.gcs); ++ writel(val32, iTCO_wdt_private.gcs_pmc); + +- val32 = readl(iTCO_wdt_private.gcs); ++ val32 = readl(iTCO_wdt_private.gcs_pmc); + if (val32 & 0x00000020) + ret = -EIO; + } else if (iTCO_wdt_private.iTCO_version == 1) { +@@ -496,7 +526,7 @@ static int iTCO_wdt_start(void) + + /* Force the timer to its reload value by writing to the TCO_RLD + register */ +- if (iTCO_wdt_private.iTCO_version == 2) ++ if (iTCO_wdt_private.iTCO_version >= 2) + outw(0x01, TCO_RLD); + else if (iTCO_wdt_private.iTCO_version == 1) + outb(0x01, TCO_RLD); +@@ -544,9 +574,9 @@ static int iTCO_wdt_keepalive(void) + iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); + + /* Reload the timer by writing to the TCO Timer Counter register */ +- if (iTCO_wdt_private.iTCO_version == 2) ++ if (iTCO_wdt_private.iTCO_version >= 2) { + outw(0x01, TCO_RLD); +- else if (iTCO_wdt_private.iTCO_version == 1) { ++ } else if (iTCO_wdt_private.iTCO_version == 1) { + /* Reset the timeout status bit so that the timer + * needs to count down twice again before rebooting */ + outw(0x0008, TCO1_STS); /* write 1 to clear bit */ +@@ -574,14 +604,14 @@ static int iTCO_wdt_set_heartbeat(int t) + /* "Values of 0h-3h are ignored and should not be attempted" */ + if (tmrval < 0x04) + return -EINVAL; +- if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) || ++ if (((iTCO_wdt_private.iTCO_version >= 2) && (tmrval > 0x3ff)) || + ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f))) + return -EINVAL; + + iTCO_vendor_pre_set_heartbeat(tmrval); + + /* Write new heartbeat to watchdog */ +- if (iTCO_wdt_private.iTCO_version == 2) { ++ if (iTCO_wdt_private.iTCO_version >= 2) { + spin_lock(&iTCO_wdt_private.io_lock); + val16 = inw(TCOv2_TMR); + val16 &= 0xfc00; +@@ -615,13 +645,13 @@ static int iTCO_wdt_get_timeleft(int *time_left) + unsigned char val8; + + /* read the TCO Timer */ +- if (iTCO_wdt_private.iTCO_version == 2) { ++ if (iTCO_wdt_private.iTCO_version >= 2) { + spin_lock(&iTCO_wdt_private.io_lock); + val16 = inw(TCO_RLD); + val16 &= 0x3ff; + spin_unlock(&iTCO_wdt_private.io_lock); + +- *time_left = (val16 * 6) / 10; ++ *time_left = ticks_to_seconds(val16); + } else if (iTCO_wdt_private.iTCO_version == 1) { + spin_lock(&iTCO_wdt_private.io_lock); + val8 = inb(TCO_RLD); +@@ -630,7 +660,7 @@ static int iTCO_wdt_get_timeleft(int *time_left) + val8 += (inb(TCOv1_TMR) & 0x3f); + spin_unlock(&iTCO_wdt_private.io_lock); + +- *time_left = (val8 * 6) / 10; ++ *time_left = ticks_to_seconds(val8); + } else + return -EINVAL; + return 0; +@@ -784,6 +814,24 @@ static struct miscdevice iTCO_wdt_miscdev = { + }; + + /* ++ * From patch for Avoton/Rangeley, enable PMC space; here rather ++ * than where it is in newer kernels to avoid patch problems ++ * We don't need all the functionality related to newer kernels, ++ * so comment out a lot (keeping it for reference). ++ */ ++static void ++lpc_ich_enable_pmc_space (struct pci_dev *dev) ++{ ++ /* struct lpc_ich_priv *priv = pci_get_drvdata (dev); */ ++ u8 reg_save; ++ ++ pci_read_config_byte (dev, /* priv->actrl_pbase */0x44, ®_save); ++ pci_write_config_byte (dev, /* priv->actrl_pbase */0x44, reg_save | 0x2); ++ ++ /* priv->actrl_pbase_save = reg_save; */ ++} ++ ++/* + * Init & exit routines + */ + +@@ -810,13 +858,16 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, + } + iTCO_wdt_private.iTCO_version = + iTCO_chipset_info[ent->driver_data].iTCO_version; ++ if (iTCO_wdt_private.iTCO_version == 3) + iTCO_wdt_private.ACPIBASE = base_address; + iTCO_wdt_private.pdev = pdev; + +- /* Get the Memory-Mapped GCS register, we need it for the +- NO_REBOOT flag (TCO v2). To get access to it you have to +- read RCBA from PCI Config space 0xf0 and use it as base. +- GCS = RCBA + ICH6_GCS(0x3410). */ ++ /* ++ * Get the Memory-Mapped GCS or PMC register, we need it for the ++ * NO_REBOOT flag (TCO v2 and v3). ++ * v2: read RCBA from PCI Config space 0xf0 and use it as base. ++ * GCS = RCBA + ICH6_GCS(0x3410). ++ */ + if (iTCO_wdt_private.iTCO_version == 2) { + pci_read_config_dword(pdev, 0xf0, &base_address); + if ((base_address & 1) == 0) { +@@ -826,7 +877,19 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, + goto out; + } + RCBA = base_address & 0xffffc000; +- iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); ++ iTCO_wdt_private.gcs_pmc = ioremap((RCBA + 0x3410), 4); ++ } ++ else if (iTCO_wdt_private.iTCO_version == 3) { ++ /* ++ * comes from ACPI, in PMC space. driver resources ++ * changed a lot in this area from our 3.2 kernel to ++ * kernel where v3 support was added. 0x44 is ACPICTRL_PMBASE, ++ * 0x8 is ACPI_PMC_OFF. ++ */ ++ lpc_ich_enable_pmc_space (pdev); ++ pci_read_config_dword(pdev, 0x44, &base_address); ++ base_address &= 0xfffffe00; ++ iTCO_wdt_private.gcs_pmc = ioremap(base_address + 0x8, 4); + } + + /* Check chipset's NO_REBOOT bit */ +@@ -871,9 +934,13 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, + TCOBASE); + + /* Clear out the (probably old) status */ +- outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ +- outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ +- outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ ++ if (iTCO_wdt_private.iTCO_version == 3) { ++ outl(0x20008, TCO1_STS); ++ } else { ++ outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ ++ outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ ++ outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ ++ } + + /* Make sure the watchdog is not running */ + iTCO_wdt_stop(); +@@ -904,8 +971,8 @@ unreg_region: + unreg_smi_en: + release_region(SMI_EN, 4); + out_unmap: +- if (iTCO_wdt_private.iTCO_version == 2) +- iounmap(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version >= 2) ++ iounmap(iTCO_wdt_private.gcs_pmc); + out: + iTCO_wdt_private.ACPIBASE = 0; + return ret; +@@ -921,8 +988,8 @@ static void __devexit iTCO_wdt_cleanup(void) + misc_deregister(&iTCO_wdt_miscdev); + release_region(TCOBASE, 0x20); + release_region(SMI_EN, 4); +- if (iTCO_wdt_private.iTCO_version == 2) +- iounmap(iTCO_wdt_private.gcs); ++ if (iTCO_wdt_private.iTCO_version >= 2) ++ iounmap(iTCO_wdt_private.gcs_pmc); + pci_dev_put(iTCO_wdt_private.pdev); + iTCO_wdt_private.ACPIBASE = 0; + } +diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c +new file mode 100644 +index 0000000..8f541b9 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch new file mode 100644 index 00000000..dd78bd50 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_ie6xx_wdt.c.patch @@ -0,0 +1,353 @@ +--- /dev/null ++++ b/drivers/watchdog/ie6xx_wdt.c +@@ -0,0 +1,348 @@ ++/* ++ * Intel Atom E6xx Watchdog driver ++ * ++ * Copyright (C) 2011 Alexander Stein ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of version 2 of the GNU General ++ * Public License as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be ++ * useful, but WITHOUT ANY WARRANTY; without even the implied ++ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ++ * PURPOSE. See the GNU General Public License for more details. ++ * You should have received a copy of the GNU General Public ++ * License along with this program; if not, write to the Free ++ * Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ * The full GNU General Public License is included in this ++ * distribution in the file called COPYING. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "ie6xx_wdt" ++ ++#define PV1 0x00 ++#define PV2 0x04 ++ ++#define RR0 0x0c ++#define RR1 0x0d ++#define WDT_RELOAD 0x01 ++#define WDT_TOUT 0x02 ++ ++#define WDTCR 0x10 ++#define WDT_PRE_SEL 0x04 ++#define WDT_RESET_SEL 0x08 ++#define WDT_RESET_EN 0x10 ++#define WDT_TOUT_EN 0x20 ++ ++#define DCR 0x14 ++ ++#define WDTLR 0x18 ++#define WDT_LOCK 0x01 ++#define WDT_ENABLE 0x02 ++#define WDT_TOUT_CNF 0x03 ++ ++#define MIN_TIME 1 ++#define MAX_TIME (10 * 60) /* 10 minutes */ ++#define DEFAULT_TIME 60 ++ ++static unsigned int timeout = DEFAULT_TIME; ++module_param(timeout, uint, 0); ++MODULE_PARM_DESC(timeout, ++ "Default Watchdog timer setting (" ++ __MODULE_STRING(DEFAULT_TIME) "s)." ++ "The range is from 1 to 600"); ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, bool, 0); ++MODULE_PARM_DESC(nowayout, ++ "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++static u8 resetmode = 0x10; ++module_param(resetmode, byte, 0); ++MODULE_PARM_DESC(resetmode, ++ "Resetmode bits: 0x08 warm reset (cold reset otherwise), " ++ "0x10 reset enable, 0x20 disable toggle GPIO[4] (default=0x10)"); ++ ++static struct { ++ unsigned short sch_wdtba; ++ struct spinlock unlock_sequence; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs; ++#endif ++} ie6xx_wdt_data; ++ ++/* ++ * This is needed to write to preload and reload registers ++ * struct ie6xx_wdt_data.unlock_sequence must be used ++ * to prevent sequence interrupts ++ */ ++static void ie6xx_wdt_unlock_registers(void) ++{ ++ outb(0x80, ie6xx_wdt_data.sch_wdtba + RR0); ++ outb(0x86, ie6xx_wdt_data.sch_wdtba + RR0); ++} ++ ++static int ie6xx_wdt_ping(struct watchdog_device *wdd) ++{ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ ie6xx_wdt_unlock_registers(); ++ outb(WDT_RELOAD, ie6xx_wdt_data.sch_wdtba + RR1); ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ return 0; ++} ++ ++static int ie6xx_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) ++{ ++ u32 preload; ++ u64 clock; ++ u8 wdtcr; ++ ++ /* Watchdog clock is PCI Clock (33MHz) */ ++ clock = 33000000; ++ /* and the preload value is loaded into [34:15] of the down counter */ ++ preload = (t * clock) >> 15; ++ /* ++ * Manual states preload must be one less. ++ * Does not wrap as t is at least 1 ++ */ ++ preload -= 1; ++ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ ++ /* Set ResetMode & Enable prescaler for range 10ms to 10 min */ ++ wdtcr = resetmode & 0x38; ++ outb(wdtcr, ie6xx_wdt_data.sch_wdtba + WDTCR); ++ ++ ie6xx_wdt_unlock_registers(); ++ outl(0, ie6xx_wdt_data.sch_wdtba + PV1); ++ ++ ie6xx_wdt_unlock_registers(); ++ outl(preload, ie6xx_wdt_data.sch_wdtba + PV2); ++ ++ ie6xx_wdt_unlock_registers(); ++ outb(WDT_RELOAD | WDT_TOUT, ie6xx_wdt_data.sch_wdtba + RR1); ++ ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ ++ wdd->timeout = t; ++ return 0; ++} ++ ++static int ie6xx_wdt_start(struct watchdog_device *wdd) ++{ ++ ie6xx_wdt_set_timeout(wdd, wdd->timeout); ++ ++ /* Enable the watchdog timer */ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ outb(WDT_ENABLE, ie6xx_wdt_data.sch_wdtba + WDTLR); ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ ++ return 0; ++} ++ ++static int ie6xx_wdt_stop(struct watchdog_device *wdd) ++{ ++ if (inb(ie6xx_wdt_data.sch_wdtba + WDTLR) & WDT_LOCK) ++ return -1; ++ ++ /* Disable the watchdog timer */ ++ spin_lock(&ie6xx_wdt_data.unlock_sequence); ++ outb(0, ie6xx_wdt_data.sch_wdtba + WDTLR); ++ spin_unlock(&ie6xx_wdt_data.unlock_sequence); ++ ++ return 0; ++} ++ ++static const struct watchdog_info ie6xx_wdt_info = { ++ .identity = "Intel Atom E6xx Watchdog", ++ .options = WDIOF_SETTIMEOUT | ++ WDIOF_MAGICCLOSE | ++ WDIOF_KEEPALIVEPING, ++}; ++ ++static const struct watchdog_ops ie6xx_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = ie6xx_wdt_start, ++ .stop = ie6xx_wdt_stop, ++ .ping = ie6xx_wdt_ping, ++ .set_timeout = ie6xx_wdt_set_timeout, ++}; ++ ++static struct watchdog_device ie6xx_wdt_dev = { ++ .info = &ie6xx_wdt_info, ++ .ops = &ie6xx_wdt_ops, ++ .min_timeout = MIN_TIME, ++ .max_timeout = MAX_TIME, ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++ ++static int ie6xx_wdt_dbg_show(struct seq_file *s, void *unused) ++{ ++ seq_printf(s, "PV1 = 0x%08x\n", ++ inl(ie6xx_wdt_data.sch_wdtba + PV1)); ++ seq_printf(s, "PV2 = 0x%08x\n", ++ inl(ie6xx_wdt_data.sch_wdtba + PV2)); ++ seq_printf(s, "RR = 0x%08x\n", ++ inw(ie6xx_wdt_data.sch_wdtba + RR0)); ++ seq_printf(s, "WDTCR = 0x%08x\n", ++ inw(ie6xx_wdt_data.sch_wdtba + WDTCR)); ++ seq_printf(s, "DCR = 0x%08x\n", ++ inl(ie6xx_wdt_data.sch_wdtba + DCR)); ++ seq_printf(s, "WDTLR = 0x%08x\n", ++ inw(ie6xx_wdt_data.sch_wdtba + WDTLR)); ++ ++ seq_printf(s, "\n"); ++ return 0; ++} ++ ++static int ie6xx_wdt_dbg_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ie6xx_wdt_dbg_show, NULL); ++} ++ ++static const struct file_operations ie6xx_wdt_dbg_operations = { ++ .open = ie6xx_wdt_dbg_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void __devinit ie6xx_wdt_debugfs_init(void) ++{ ++ /* /sys/kernel/debug/ie6xx_wdt */ ++ ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt", ++ S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations); ++} ++ ++static void ie6xx_wdt_debugfs_exit(void) ++{ ++ debugfs_remove(ie6xx_wdt_data.debugfs); ++} ++ ++#else ++static void __devinit ie6xx_wdt_debugfs_init(void) ++{ ++} ++ ++static void ie6xx_wdt_debugfs_exit(void) ++{ ++} ++#endif ++ ++static int __devinit ie6xx_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ u8 wdtlr; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IO, 0); ++ if (!res) ++ return -ENODEV; ++ ++ if (!request_region(res->start, resource_size(res), pdev->name)) { ++ dev_err(&pdev->dev, "Watchdog region 0x%llx already in use!\n", ++ (u64)res->start); ++ return -EBUSY; ++ } ++ ++ ie6xx_wdt_data.sch_wdtba = res->start; ++ dev_dbg(&pdev->dev, "WDT = 0x%X\n", ie6xx_wdt_data.sch_wdtba); ++ ++ ie6xx_wdt_dev.timeout = timeout; ++ watchdog_set_nowayout(&ie6xx_wdt_dev, nowayout); ++ ++ spin_lock_init(&ie6xx_wdt_data.unlock_sequence); ++ ++ wdtlr = inb(ie6xx_wdt_data.sch_wdtba + WDTLR); ++ if (wdtlr & WDT_LOCK) ++ dev_warn(&pdev->dev, ++ "Watchdog Timer is Locked (Reg=0x%x)\n", wdtlr); ++ ++ ie6xx_wdt_debugfs_init(); ++ ++ ret = watchdog_register_device(&ie6xx_wdt_dev); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "Watchdog timer: cannot register device (err =%d)\n", ++ ret); ++ goto misc_register_error; ++ } ++ ++ return 0; ++ ++misc_register_error: ++ ie6xx_wdt_debugfs_exit(); ++ release_region(res->start, resource_size(res)); ++ ie6xx_wdt_data.sch_wdtba = 0; ++ return ret; ++} ++ ++static int __devexit ie6xx_wdt_remove(struct platform_device *pdev) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IO, 0); ++ ie6xx_wdt_stop(NULL); ++ watchdog_unregister_device(&ie6xx_wdt_dev); ++ ie6xx_wdt_debugfs_exit(); ++ release_region(res->start, resource_size(res)); ++ ie6xx_wdt_data.sch_wdtba = 0; ++ ++ return 0; ++} ++ ++static struct platform_driver ie6xx_wdt_driver = { ++ .probe = ie6xx_wdt_probe, ++ .remove = __devexit_p(ie6xx_wdt_remove), ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ie6xx_wdt_init(void) ++{ ++ /* Check boot parameters to verify that their initial values */ ++ /* are in range. */ ++ if ((timeout < MIN_TIME) || ++ (timeout > MAX_TIME)) { ++ pr_err("Watchdog timer: value of timeout %d (dec) " ++ "is out of range from %d to %d (dec)\n", ++ timeout, MIN_TIME, MAX_TIME); ++ return -EINVAL; ++ } ++ ++ return platform_driver_register(&ie6xx_wdt_driver); ++} ++ ++static void __exit ie6xx_wdt_exit(void) ++{ ++ platform_driver_unregister(&ie6xx_wdt_driver); ++} ++ ++late_initcall(ie6xx_wdt_init); ++module_exit(ie6xx_wdt_exit); ++ ++MODULE_AUTHOR("Alexander Stein "); ++MODULE_DESCRIPTION("Intel Atom E6xx Watchdog Device Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c +index 87e0527..826f6bb 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch new file mode 100644 index 00000000..f5d4b2d6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/drivers_watchdog_sp5100_tco.c.patch @@ -0,0 +1,15 @@ +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -287,6 +287,10 @@ static unsigned char __devinit sp5100_tco_setupdevice(void) + if (!sp5100_tco_pci) + return 0; + ++ /* Higher revisions are SB8x0 which have a different register set */ ++ if (sp5100_tco_pci->revision >= 0x40) ++ return 0; ++ + /* Request the IO ports used by this driver */ + pm_iobase = SP5100_IO_PM_INDEX_REG; + if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) { +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index 89588e7..f39d998 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/foopatch b/packages/base/any/kernels/3.2-lts/patches/foopatch new file mode 100644 index 00000000..11fda216 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/foopatch @@ -0,0 +1,74956 @@ +--- /dev/null ++++ b/drivers/bcmdrivers/Kconfig +@@ -0,0 +1,84 @@ ++menu "Broadcom iProc Drivers" ++ depends on ARCH_IPROC ++ ++source "drivers/bcmdrivers/timer/Kconfig" ++source "drivers/bcmdrivers/mdio/Kconfig" ++source "drivers/bcmdrivers/dma/Kconfig" ++source "drivers/bcmdrivers/gpio/Kconfig" ++source "drivers/bcmdrivers/qspi/Kconfig" ++source "drivers/bcmdrivers/nand/Kconfig" ++source "drivers/bcmdrivers/pwm/Kconfig" ++source "drivers/bcmdrivers/wdt/Kconfig" ++source "drivers/bcmdrivers/usb2h/Kconfig" ++source "drivers/bcmdrivers/gmac/et/Kconfig" ++source "drivers/bcmdrivers/gmac/hnd/Kconfig" ++source "drivers/bcmdrivers/smbus/Kconfig" ++source "drivers/bcmdrivers/pmu/Kconfig" ++ ++config BCM_IPROC_CA9_PREFETCH ++ tristate "CortexA9 cache auto-prefetching support" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable iProc CortexA9 L1/L2 cache auto-prefetching support ++ ++ If unsure, say N. ++ ++config BCM_BARRIER_PERFORMANCE ++ bool "Linux memory barrier performance improvement" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable linux memory barrier performance improvements ++ ++ If unsure, say N. ++ ++config BCM_MEM_OPTIMIZATION ++ bool "ARM Memory library optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable ARM memory library optimization ++ ++ If unsure, say N. ++ ++config BROADCOM_CUSTOM_SENDFILE ++ bool "Custom Sendfile optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable Broadcom Custom Sendfile optimization ++ ++ If unsure, say N. ++ ++config BCM_CUSTOM_RECVFILE ++ bool "Custom Receivefile optimization" ++ depends on ARCH_IPROC ++ default n ++ help ++ Enable Broadcom Custom Receivefile optimization ++ ++ If unsure, say N. ++ ++config BCM_CUSTOM_RECVFILE_MAX_PERF ++# Enabling BCM_CUSTOM_RECVFILE_MAX_PERF gives maximum write performance ++# at the risk of filesystem errors (due to skipping cache invalidation ++# on writes) and exposure to A0 hardware errata for lazy interrupts. ++ bool "Custom Receivefile Max Performance optimization" ++ depends on ARCH_IPROC && BCM_CUSTOM_RECVFILE ++ default n ++ help ++ Enable Broadcom Custom Receivefile Maximum Performance optimization ++ ++ If unsure, say N. ++ ++config BCM_GRO_ENABLE ++ bool "Broadcom GRO Enable" ++ depends on ARCH_IPROC && (ET_NAPI_POLL || ET_NAPI2_POLL) ++ default n ++ help ++ Enable Broadcom Generic Receive Offload ++ ++ If unsure, say N. ++ ++endmenu +diff --git a/drivers/bcmdrivers/Makefile b/drivers/bcmdrivers/Makefile +new file mode 100755 +index 0000000..6a8ba6f +--- /dev/null ++++ b/drivers/bcmdrivers/Makefile +@@ -0,0 +1,21 @@ ++# File: bcmdrivers/Makefile ++# ++# Makefile for the Linux kernel modules. ++# ++ ++# The following must have config defined for each driver ++ ++obj-y += timer/ ++obj-y += mdio/ ++obj-y += dma/ ++obj-y += qspi/ ++obj-$(CONFIG_IPROC_MTD_NAND) += nand/ ++obj-y += pwm/ ++obj-y += gpio/ ++obj-y += wdt/ ++obj-y += usb2h/ ++obj-$(CONFIG_ET) += gmac/et/ ++obj-y += gmac/hnd/ ++obj-y += smbus/ ++ ++obj-y += pmu/ +diff --git a/drivers/bcmdrivers/dma/.gitignore b/drivers/bcmdrivers/dma/.gitignore +new file mode 100644 +index 0000000..d741861 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/dma/Kconfig b/drivers/bcmdrivers/dma/Kconfig +new file mode 100644 +index 0000000..652fbb4 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/Kconfig +@@ -0,0 +1,15 @@ ++config IPROC_DMA ++ tristate "DMA support" ++ depends on ARCH_IPROC ++ select DMADEVICES ++ select DMADEVICES_DEBUG ++ select DMADEVICES_VDEBUG ++ select DMA_ENGINE ++ select PL330 ++ select DMAC_PL330 ++ select DMATEST ++ default n ++ help ++ DMA support for pl330 ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/dma/Makefile b/drivers/bcmdrivers/dma/Makefile +new file mode 100644 +index 0000000..0b6a480 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_DMA) += iproc_dma.o ++iproc_dma-objs := dma.o +diff --git a/drivers/bcmdrivers/dma/dma-pl330.h b/drivers/bcmdrivers/dma/dma-pl330.h +new file mode 100644 +index 0000000..bf45e7b +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma-pl330.h +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __PLAT_DMA_H ++#define __PLAT_DMA_H ++ ++#include ++ ++#define MAX_CHAN_NAME_LENGTH 32 ++ ++/* DMA direction control */ ++enum dma_direction { ++ DMA_DIRECTION_MEM_TO_MEM = 0, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC = 1, ++ DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI = 2, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC = 3, ++ DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI = 4, ++ DMA_DIRECTION_DEV_TO_DEV = 5 /* Invalid, unsupported */ ++}; ++#define DMA_DIRECTION_MASK 0x7 ++ ++/* Channel configurations definition */ ++#define DMA_CFG_SRC_ADDR_FIXED (0x0 << 0) ++#define DMA_CFG_SRC_ADDR_INCREMENT (0x1 << 0) ++#define DMA_CFG_DST_ADDR_FIXED (0x0 << 14) ++#define DMA_CFG_DST_ADDR_INCREMENT (0x1 << 14) ++ ++#define DMA_CFG_BURST_SIZE_MASK (0x7 << 1) ++#define DMA_CFG_BURST_SIZE_1 (0x0 << 1) ++#define DMA_CFG_BURST_SIZE_2 (0x1 << 1) ++#define DMA_CFG_BURST_SIZE_4 (0x2 << 1) ++#define DMA_CFG_BURST_SIZE_8 (0x3 << 1) ++#define DMA_CFG_BURST_SIZE_16 (0x4 << 1) ++#define DMA_CFG_BURST_SIZE_32 (0x5 << 1) ++#define DMA_CFG_BURST_SIZE_64 (0x6 << 1) ++#define DMA_CFG_BURST_SIZE_128 (0x7 << 1) ++ ++#define DMA_CFG_BURST_LENGTH_MASK (0xF << 4) ++#define DMA_CFG_BURST_LENGTH_1 (0x0 << 4) ++#define DMA_CFG_BURST_LENGTH_2 (0x1 << 4) ++#define DMA_CFG_BURST_LENGTH_3 (0x2 << 4) ++#define DMA_CFG_BURST_LENGTH_4 (0x3 << 4) ++#define DMA_CFG_BURST_LENGTH_5 (0x4 << 4) ++#define DMA_CFG_BURST_LENGTH_6 (0x5 << 4) ++#define DMA_CFG_BURST_LENGTH_7 (0x6 << 4) ++#define DMA_CFG_BURST_LENGTH_8 (0x7 << 4) ++#define DMA_CFG_BURST_LENGTH_9 (0x8 << 4) ++#define DMA_CFG_BURST_LENGTH_10 (0x9 << 4) ++#define DMA_CFG_BURST_LENGTH_11 (0xA << 4) ++#define DMA_CFG_BURST_LENGTH_12 (0xB << 4) ++#define DMA_CFG_BURST_LENGTH_13 (0xC << 4) ++#define DMA_CFG_BURST_LENGTH_14 (0xD << 4) ++#define DMA_CFG_BURST_LENGTH_15 (0xE << 4) ++#define DMA_CFG_BURST_LENGTH_16 (0xF << 4) ++ ++#define DMA_CFG_BURST_LEN(x) (((x - 1) & 0xF) << 4) ++ ++/* src and dest burst size and burst length are assumed to be same */ ++ ++enum pl330_xfer_status { ++ DMA_PL330_XFER_OK, ++ DMA_PL330_XFER_ERR, ++ DMA_PL330_XFER_ABORT, ++}; ++ ++struct dma_transfer_list { ++ dma_addr_t srcaddr; /* src address */ ++ dma_addr_t dstaddr; /* dst address */ ++ unsigned int xfer_size; /* In bytes */ ++ struct list_head next; /* Next item */ ++}; ++ ++typedef void (*pl330_xfer_callback_t) (void *private_data, ++ enum pl330_xfer_status status); ++ ++int dma_request_chan(unsigned int *chan, const char *name); ++int dma_free_chan(unsigned int chan); ++int dma_map_peripheral(unsigned int chan, const char *peri_name); ++int dma_unmap_peripheral(unsigned int chan); ++int dma_setup_transfer(unsigned int chan, dma_addr_t s, dma_addr_t d, ++ unsigned int xfer_size, int ctrl, int cfg); ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int ctrl, int cfg); ++int dma_start_transfer(unsigned int chan); ++int dma_stop_transfer(unsigned int chan); ++int dma_shutdown_all_chan(void); ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t cb, void *pri); ++int dma_free_callback(unsigned int chan); ++ ++#endif /* __PLAT_DMA_H */ +diff --git a/drivers/bcmdrivers/dma/dma.c b/drivers/bcmdrivers/dma/dma.c +new file mode 100755 +index 0000000..2ff23da +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma.c +@@ -0,0 +1,886 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "pl330-pdata.h" ++#include "dma-pl330.h" ++ ++#define IPROC_IDM_DMAC_RESET_CONTROL (0x18114800) ++#define IPROC_IDM_DMAC_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_DMAC_RESET_CONTROL) ++ ++/** ++ * struct pl330_chan_desc - Peripheral channel descriptor. ++ */ ++struct pl330_chan_desc { ++ int id; /* channel ID for the client */ ++ struct list_head node; /* Link to next channel desc */ ++ bool is_peri_mapped; /*Is peripheral mapped?, false if mem to mem */ ++ char *name[MAX_CHAN_NAME_LENGTH]; /* Name of the peripheral */ ++ int event_id; /* ID of event/Interrupt line to notify */ ++ u8 peri_req_id; /* mapped peripheral request interface(PRI) ID */ ++ void *pl330_chan_id; /* PL330 channel id alloted */ ++ unsigned int options; /* DMA options */ ++ struct pl330_reqcfg rqcfg; /* DMA req configurations */ ++ pl330_xfer_callback_t xfer_callback; /* DMA callback function */ ++ void *client_cookie; /* client data for callback fn */ ++ bool in_use; /* is DMA channel busy */ ++ bool is_setup; /* Is 'pl330_req' having valid transfer setup */ ++ struct pl330_req req; /* A DMA request item */ ++}; ++ ++/** ++ * struct pl330_dmac_desc - PL330 DMAC Descriptor. ++ */ ++struct pl330_dmac_desc { ++ struct pl330_info *pi; /* PL330 DMAC info */ ++ int irq_start; /* First PL330 Irq mapped */ ++ int irq_end; /* Last Irq number mapped */ ++ struct list_head chan_list; /* List of channel descriptors */ ++ int chan_count; /* channel descriptors count */ ++}; ++ ++/* PL330 DMAC Descriptor structure */ ++static struct pl330_dmac_desc *dmac = NULL; /* Allocate on platform device probe */ ++/* global resources lock */ ++static DEFINE_SPINLOCK(lock); ++ ++/* always call this function with global spinlock held */ ++static struct pl330_chan_desc *chan_id_to_cdesc(int id) ++{ ++ struct pl330_chan_desc *cdesc; ++ ++ list_for_each_entry(cdesc, &dmac->chan_list, node) ++ if (cdesc->id == id) ++ return cdesc; ++ ++ return NULL; ++} ++ ++static void _cleanup_req(struct pl330_req *rq) ++{ ++ struct pl330_xfer *x, *nxt; ++ ++ if (!rq) ++ return; ++ ++ rq->rqtype = DEVTODEV; /* Invalid type */ ++ ++ if (rq->cfg) { ++ kfree(rq->cfg); ++ rq->cfg = NULL; ++ } ++ ++ if (!rq->x) ++ return; ++ ++ /* Free all the xfer items */ ++ x = rq->x; ++ do { ++ nxt = x->next; ++ kfree(x); ++ x = nxt; ++ } while (x); ++ rq->x = NULL; ++ ++ return; ++} ++ ++static void _free_cdesc(struct pl330_chan_desc *cdesc) ++{ ++ /* Deallocate all mapped peripherals */ ++ if (cdesc->is_peri_mapped) { ++ cdesc->is_peri_mapped = false; ++ } ++ ++ /* Release PL330 channel thread */ ++ pl330_release_channel(cdesc->pl330_chan_id); ++ ++ list_del(&cdesc->node); ++ dmac->chan_count--; ++ kfree(cdesc); ++} ++ ++static void pl330_req_callback(void *token, enum pl330_op_err err) ++{ ++ struct pl330_req *r = token; ++ enum pl330_xfer_status stat; ++ struct pl330_chan_desc *c = ++ container_of(r, struct pl330_chan_desc, req); ++ ++ printk("\n----> %s ()\n", __func__); ++ if (c && c->xfer_callback) { ++ switch (err) { ++ case PL330_ERR_NONE: ++ stat = DMA_PL330_XFER_OK; ++ break; ++ case PL330_ERR_ABORT: ++ stat = DMA_PL330_XFER_ABORT; ++ break; ++ case PL330_ERR_FAIL: ++ stat = DMA_PL330_XFER_ERR; ++ break; ++ default: ++ stat = DMA_PL330_XFER_OK; ++ break; ++ } ++ /* call client callback function */ ++ c->xfer_callback(c->client_cookie, stat); ++ } ++} ++ ++int dma_request_chan(unsigned int *chan, const char *name) ++{ ++ int ch, err = -1; ++ //enum dma_peri peri; ++ u8 pri_id; ++ void *pl330_chan_id = NULL; ++ struct pl330_chan_desc *cdesc = NULL; ++ unsigned long flags; ++ bool is_peri = false; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* channel request for a 'named' peripheral, NULL if memory<->memory DMA */ ++ /* no peripheral mapping in IPROC */ ++ ++ /* Allocate PL330 DMA channel thread first */ ++ pl330_chan_id = pl330_request_channel(dmac->pi); ++ if (!pl330_chan_id) { ++ dev_info(dmac->pi->dev, ++ "Failed to allocate PL330 channel thread!!!\n"); ++ goto err_1; ++ } ++ ++ ++ if (dmac->chan_count >= 8) ++ { ++ dev_info(dmac->pi->dev, "MAX DMAC channel exceeded\n"); ++ goto err_2; ++ } ++ ++ /* No peripheral mapping in IPROC */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Channel allocation is done, create a 'channel descriptor' for the client */ ++ cdesc = (struct pl330_chan_desc *)kzalloc(sizeof(*cdesc), GFP_KERNEL); ++ ++ spin_lock_irqsave(&lock, flags); ++ if (!cdesc) { ++ err = -ENOMEM; ++ goto err_4; ++ } ++ ++ /* Populate the cdesc and return channel id to client */ ++ cdesc->id = dmac->chan_count; ++ cdesc->xfer_callback = NULL; ++ cdesc->client_cookie = NULL; ++ cdesc->is_peri_mapped = is_peri; ++ cdesc->event_id = 0; /* always use INTR/EVT line 0 */ ++ cdesc->peri_req_id = pri_id; ++ cdesc->pl330_chan_id = pl330_chan_id; ++ cdesc->in_use = false; ++ cdesc->req.rqtype = DEVTODEV; /* set invalid type */ ++ if (name) ++ strlcpy(cdesc->name, name, MAX_CHAN_NAME_LENGTH); ++ ++ /* Attach cdesc to DMAC channel list */ ++ list_add_tail(&cdesc->node, &dmac->chan_list); ++ dmac->chan_count++; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Give the channel ID to client */ ++ *chan = cdesc->id; ++ return 0; ++ ++ err_4: ++ err_3: ++ err_2: ++ pl330_release_channel(pl330_chan_id); ++ err_1: ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return err; ++} ++ ++int dma_free_chan(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *cdesc; ++ ++ spin_lock_irqsave(&lock, flags); ++ cdesc = chan_id_to_cdesc(chan); ++ if (!cdesc || cdesc->in_use) /* can free id channel is active */ ++ goto err; ++ ++ _cleanup_req(&cdesc->req); ++ ++ _free_cdesc(cdesc); ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_map_peripheral(unsigned int chan, const char *peri_name) ++{ ++ struct pl330_chan_desc *c = NULL; ++ unsigned long flags; ++ //enum dma_peri peri; ++ u8 pri_id; ++ ++ if (!peri_name) ++ return -1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err_ret; ++ ++ /* If a peripheral is already mapped, return failure */ ++ if (c->is_peri_mapped) { ++ dev_info(dmac->pi->dev, ++ "Already peripheral mapped, need to unmap first!!!\n"); ++ goto err_ret; ++ } ++ ++ /* no peripheral mapping in IPROC */ ++ ++ /* no peripheral mapping in IPROC */ ++ ++ c->peri_req_id = pri_id; ++ c->is_peri_mapped = true; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_unmap_peripheral(unsigned int chan) ++{ ++ struct pl330_chan_desc *c = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err_ret; ++ ++ /* If a peripheral is already mapped or channel in use, return failure */ ++ if (!c->is_peri_mapped || c->in_use) { ++ dev_info(dmac->pi->dev, "Peripheral is not mapped\n"); ++ goto err_ret; ++ } ++ ++ c->is_peri_mapped = false; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err_ret: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_setup_transfer(unsigned int chan, ++ dma_addr_t src_addr, ++ dma_addr_t dst_addr, ++ unsigned int xfer_size, int control, int cfg) ++{ ++ unsigned long flags; ++ enum pl330_reqtype rqtype; ++ struct pl330_reqcfg *config; ++ struct pl330_xfer *xfer; ++ struct pl330_chan_desc *c; ++ int err = -1; ++ ++ if (!xfer_size) ++ goto err1; ++ ++ /* DMA transfer direction */ ++ switch (control & DMA_DIRECTION_MASK) { ++ /* Peripheral transfers with DMAC flow control are ++ * treated as Mem to Mem transfers at PL330 microcode level. ++ */ ++ case DMA_DIRECTION_MEM_TO_MEM: ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC: ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC: ++ rqtype = MEMTOMEM; ++ break; ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI: ++ rqtype = MEMTODEV; ++ break; ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI: ++ rqtype = DEVTOMEM; ++ break; ++ case DMA_DIRECTION_DEV_TO_DEV: ++ default: ++ rqtype = DEVTODEV; /*Unsupported */ ++ break; ++ }; ++ ++ if (rqtype == DEVTODEV) ++ goto err1; ++ ++ /* Burst size max is 64 bit(AXI), not supporting >64 bit burst size */ ++ if ((cfg & DMA_CFG_BURST_SIZE_MASK) > DMA_CFG_BURST_SIZE_8) ++ goto err1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ if (c->in_use || c->is_setup) { ++ dev_info(dmac->pi->dev, ++ "Cant setup transfer, already setup/running\n"); ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ }; ++ ++ if ((rqtype != DMA_DIRECTION_MEM_TO_MEM) && (!c->is_peri_mapped)) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ c->is_setup = true; /* Mark it now, for setup */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Allocate */ ++ config = (struct pl330_reqcfg *)kzalloc(sizeof(*config), GFP_KERNEL); ++ if (!config) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ xfer = (struct pl330_xfer *)kzalloc(sizeof(*xfer), GFP_KERNEL); ++ if (!xfer) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ ++ /* configuration options */ ++ config->src_inc = (cfg & DMA_CFG_SRC_ADDR_INCREMENT) ? 1 : 0; ++ config->dst_inc = (cfg & DMA_CFG_DST_ADDR_INCREMENT) ? 1 : 0; ++ /* Burst size */ ++ config->brst_size = (cfg & DMA_CFG_BURST_SIZE_MASK) >> 1; ++ /* Burst Length */ ++ config->brst_len = (((cfg & DMA_CFG_BURST_LENGTH_MASK) >> 4) + 1); ++ ++ /* default settings: Noncacheable, nonbufferable, no swapping */ ++ config->scctl = SCCTRL0; ++ config->dcctl = DCCTRL0; ++ config->swap = SWAP_NO; ++ ++ /* TrustZone security AXPROT[2:0} = 000 */ ++ config->insnaccess = false; /* tied LOW */ ++ config->nonsecure = true; /* DMAC boots in Non Secure Mode */ ++ config->privileged = false; ++ ++ xfer->src_addr = src_addr; ++ xfer->dst_addr = dst_addr; ++ xfer->bytes = xfer_size; ++ xfer->next = NULL; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* Attach the request */ ++ c->req.rqtype = rqtype; ++ ++ if (rqtype != MEMTOMEM) ++ c->req.peri = c->peri_req_id; ++ ++ /* callback function */ ++ c->req.xfer_cb = pl330_req_callback; ++ c->req.token = &c->req; /* callback data */ ++ /* attach configuration */ ++ c->req.cfg = config; ++ /* attach xfer item */ ++ c->req.x = xfer; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err2: ++ kfree(config); ++ err1: ++ return err; ++} ++ ++int dma_setup_transfer_list(unsigned int chan, struct list_head *head, ++ int control, int cfg) ++{ ++ unsigned long flags; ++ enum pl330_reqtype rqtype; ++ struct pl330_reqcfg *config; ++ struct pl330_xfer *xfer_front, *nxt, *priv; ++ struct pl330_chan_desc *c; ++ struct dma_transfer_list *lli; ++ int err = -1; ++ ++ if (!head) ++ return -1; ++ ++ /* DMA transfer direction */ ++ switch (control & DMA_DIRECTION_MASK) { ++ /* Peripheral transfers with DMAC flow control are ++ * treated as Mem to Mem transfers at PL330 microcode level. ++ */ ++ case DMA_DIRECTION_MEM_TO_MEM: ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_DMAC: ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_DMAC: ++ rqtype = MEMTOMEM; ++ break; ++ case DMA_DIRECTION_MEM_TO_DEV_FLOW_CTRL_PERI: ++ rqtype = MEMTODEV; ++ break; ++ case DMA_DIRECTION_DEV_TO_MEM_FLOW_CTRL_PERI: ++ rqtype = DEVTOMEM; ++ break; ++ case DMA_DIRECTION_DEV_TO_DEV: ++ default: ++ rqtype = DEVTODEV; /*Unsupported */ ++ break; ++ }; ++ ++ if (rqtype == DEVTODEV) ++ goto err1; ++ ++ /* Burst size max is 64 bit(AXI), not supporting > 64 bit burst size */ ++ if ((cfg & DMA_CFG_BURST_SIZE_MASK) > DMA_CFG_BURST_SIZE_8) ++ goto err1; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ if (c->in_use || c->is_setup) { ++ dev_info(dmac->pi->dev, ++ "Cant setup transfer, already setup/running\n"); ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ }; ++ ++ if ((rqtype != DMA_DIRECTION_MEM_TO_MEM) && (!c->is_peri_mapped)) { ++ spin_unlock_irqrestore(&lock, flags); ++ goto err1; ++ } ++ ++ c->is_setup = true; /* Mark it now, for setup */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ ++ /* Allocate config strcuture */ ++ config = (struct pl330_reqcfg *)kzalloc(sizeof(*config), GFP_KERNEL); ++ if (!config) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ /* configuration options */ ++ config->src_inc = (cfg & DMA_CFG_SRC_ADDR_INCREMENT) ? 1 : 0; ++ config->dst_inc = (cfg & DMA_CFG_DST_ADDR_INCREMENT) ? 1 : 0; ++ /* Burst size */ ++ config->brst_size = (cfg & DMA_CFG_BURST_SIZE_MASK) >> 1; ++ /* Burst Length */ ++ config->brst_len = (((cfg & DMA_CFG_BURST_LENGTH_MASK) >> 4) + 1); ++ ++ /* default settings: Noncacheable, nonbufferable, no swapping */ ++ config->scctl = SCCTRL0; ++ config->dcctl = DCCTRL0; ++ config->swap = SWAP_NO; ++ ++ /* TrustZone security AXPROT[2:0} = 000 */ ++ config->insnaccess = false; /* tied LOW */ ++ config->nonsecure = true; /* DMAC boots in non Secure Mode */ ++ config->privileged = false; /* AXPROT[2:0] = 000 */ ++ ++ /* Generate xfer list based on linked list passed */ ++ xfer_front = NULL; ++ list_for_each_entry(lli, head, next) { ++ ++ if (!lli->xfer_size) ++ continue; ++ ++ nxt = (struct pl330_xfer *)kzalloc(sizeof(*nxt), GFP_KERNEL); ++ if (!nxt) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ nxt->src_addr = lli->srcaddr; ++ nxt->dst_addr = lli->dstaddr; ++ nxt->bytes = lli->xfer_size; ++ nxt->next = NULL; ++ ++ if (!xfer_front) { ++ xfer_front = nxt; /* First Item */ ++ priv = nxt; ++ } else { ++ priv->next = nxt; /* Add to the tail */ ++ priv = nxt; ++ } ++ } ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ /* Attach the request */ ++ c->req.rqtype = rqtype; ++ ++ if (rqtype != MEMTOMEM) ++ c->req.peri = c->peri_req_id; ++ ++ /* callback function */ ++ c->req.xfer_cb = pl330_req_callback; ++ c->req.token = &c->req; /* callback data */ ++ /* attach configuration */ ++ c->req.cfg = config; ++ /* attach xfer item list */ ++ c->req.x = xfer_front; ++ c->is_setup = true; /* Mark the xfer item as valid */ ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err2: ++ /* Free all allocated xfer items */ ++ if (xfer_front) { ++ nxt = xfer_front; ++ while (nxt->next) { ++ priv = nxt; ++ nxt = nxt->next; ++ kfree(priv); ++ } ++ } ++ kfree(config); ++ err1: ++ return err; ++} ++ ++int dma_start_transfer(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ ++ if (!c || !c->is_setup || c->in_use) ++ goto err; ++ ++ /* Acquire DMUX semaphore while microcode loading ++ * This call always success because protect(unprotect) happen ++ * atomically within global spinlock. ++ */ ++ if (pl330_submit_req(c->pl330_chan_id, &c->req) != 0) ++ goto err2; ++ ++ /* Start DMA channel thread */ ++ if (pl330_chan_ctrl(c->pl330_chan_id, PL330_OP_START) != 0) { ++ goto err2; ++ } ++ ++ c->in_use = true; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++ err2: ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_stop_transfer(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ pl330_chan_ctrl(c->pl330_chan_id, PL330_OP_FLUSH); ++ ++ /* Free the completed transfer req */ ++ c->in_use = false; ++ c->is_setup = false; ++ /* free memory allocated for this request */ ++ _cleanup_req(&c->req); ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_register_callback(unsigned int chan, ++ pl330_xfer_callback_t callback, void *private_data) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ c->xfer_callback = callback; ++ c->client_cookie = private_data; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++} ++ ++int dma_free_callback(unsigned int chan) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *c; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ c = chan_id_to_cdesc(chan); ++ if (!c) ++ goto err; ++ ++ c->xfer_callback = NULL; ++ c->client_cookie = NULL; ++ ++ spin_unlock_irqrestore(&lock, flags); ++ return 0; ++ ++ err: ++ spin_unlock_irqrestore(&lock, flags); ++ return -1; ++ ++} ++ ++static irqreturn_t pl330_irq_handler(int irq, void *data) ++{ ++ printk("\n-----> %s(): irq = %d\n", __func__, irq); ++ if (pl330_update(data)) ++ return IRQ_HANDLED; ++ else ++ return IRQ_NONE; ++} ++ ++static int pl330_probe(struct platform_device *pdev) ++{ ++ struct pl330_dmac_desc *pd; ++ struct iproc_pl330_data *pl330_pdata; ++ struct pl330_info *pl330_info; ++ int ret, i, irq_start, irq; ++ ++ printk("\niproc-dmac-pl330: Probe ()\n"); ++ ++ pl330_pdata = pdev->dev.platform_data; ++ ++ /* Only One Pl330 device is supported, ++ * since PL330 is closely bound to DMUX logic ++ */ ++ if (dmac) { ++ dev_err(&pdev->dev, "Multiple devices are not supported!!!\n"); ++ ret = -ENODEV; ++ goto probe_err1; ++ } ++ ++ /* Platform data is required */ ++ if (!pl330_pdata) { ++ dev_err(&pdev->dev, "platform data missing!\n"); ++ ret = -ENODEV; ++ goto probe_err1; ++ } ++ ++ pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL); ++ if (!pl330_info) { ++ ret = -ENOMEM; ++ goto probe_err1; ++ } ++ ++ pl330_info->pl330_data = NULL; ++ pl330_info->client_data = NULL; ++ pl330_info->dev = &pdev->dev; ++ ++ /* For NS DMAC is in non-secure mode */ ++ pl330_info->base = (void __iomem *)pl330_pdata->dmac_ns_base; ++ /* pl330_info->base = (void __iomem *)pl330_pdata->dmac_s_base; */ ++ ++ /* Get the first IRQ line */ ++ irq_start = pl330_pdata->irq_base; ++ irq = irq_start; ++ ++ for (i = 0; i < pl330_pdata->irq_line_count; i++) { ++ irq = irq_start + i; ++ ret = request_irq(irq, pl330_irq_handler, 0, ++ dev_name(&pdev->dev), pl330_info); ++ if (ret) { ++ irq--; ++ goto probe_err2; ++ } ++ } ++ ++ ret = pl330_add(pl330_info); ++ if (ret) ++ goto probe_err3; ++ ++ /* Allocate DMAC descriptor */ ++ pd = kmalloc(sizeof(*pd), GFP_KERNEL); ++ if (!pd) { ++ ret = -ENOMEM; ++ goto probe_err4; ++ } ++ ++ /* Hook the info */ ++ pd->pi = pl330_info; ++ pd->irq_start = irq_start; ++ pd->irq_end = irq; ++ /* init channel desc list, channels are added during dma_request_chan() */ ++ pd->chan_list.next = pd->chan_list.prev = &pd->chan_list; ++ pd->chan_count = 0; ++ ++ /* Assign the DMAC descriptor */ ++ dmac = pd; ++ ++ printk(KERN_INFO ++ "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name); ++ printk(KERN_INFO ++ "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", ++ pl330_info->pcfg.data_buf_dep, ++ pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan, ++ pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events); ++ ++ return 0; ++ ++ probe_err4: ++ pl330_del(pl330_info); ++ probe_err3: ++ probe_err2: ++ while (irq >= irq_start) { ++ free_irq(irq, pl330_info); ++ irq--; ++ } ++ ++ kfree(pl330_info); ++ probe_err1: ++ return ret; ++} ++ ++static int pl330_remove(struct platform_device *pdev) ++{ ++ unsigned long flags; ++ struct pl330_chan_desc *cdesc; ++ int irq; ++ ++ spin_lock_irqsave(&lock, flags); ++ /* Free all channel descriptors first */ ++ list_for_each_entry(cdesc, &dmac->chan_list, node) { ++ /* free requests */ ++ _cleanup_req(&cdesc->req); ++ /* Free channel desc */ ++ _free_cdesc(cdesc); ++ } ++ ++ /* Free interrupt resource */ ++ for (irq = dmac->irq_start; irq <= dmac->irq_end; irq++) ++ free_irq(irq, dmac->pi); ++ ++ pl330_del(dmac->pi); ++ /* free PL330 info handle */ ++ kfree(dmac->pi); ++ /* Free dmac descriptor */ ++ kfree(dmac); ++ dmac = NULL; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return 0; ++} ++ ++static struct platform_driver pl330_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "iproc-dmac-pl330", ++ }, ++ .probe = pl330_probe, ++ .remove = pl330_remove, ++}; ++ ++static int __init pl330_init(void) ++{ ++ int dmac_reset_state; ++ ++ dmac_reset_state = readl_relaxed(IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ printk("Initial dmac_reset_state is: %08x\n", dmac_reset_state); ++ if ((dmac_reset_state & 1) == 1) ++ { ++ writel_relaxed(0x0, IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ dmac_reset_state = readl_relaxed(IPROC_IDM_DMAC_RESET_CONTROL_VA); ++ printk("dmac_reset_state is set and now it is: %08x\n", dmac_reset_state); ++ } ++ return platform_driver_register(&pl330_driver); ++} ++ ++module_init(pl330_init); ++ ++static void __exit pl330_exit(void) ++{ ++ platform_driver_unregister(&pl330_driver); ++ return; ++} ++ ++module_exit(pl330_exit); ++ ++EXPORT_SYMBOL(dma_request_chan); ++EXPORT_SYMBOL(dma_free_chan); ++EXPORT_SYMBOL(dma_map_peripheral); ++EXPORT_SYMBOL(dma_unmap_peripheral); ++EXPORT_SYMBOL(dma_setup_transfer); ++EXPORT_SYMBOL(dma_setup_transfer_list); ++EXPORT_SYMBOL(dma_start_transfer); ++EXPORT_SYMBOL(dma_stop_transfer); ++EXPORT_SYMBOL(dma_register_callback); ++EXPORT_SYMBOL(dma_free_callback); +diff --git a/drivers/bcmdrivers/dma/dma_drv.h b/drivers/bcmdrivers/dma/dma_drv.h +new file mode 100644 +index 0000000..ca5a6b5 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/dma_drv.h +@@ -0,0 +1,602 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++/** ++* ++* @file dma_drv.h ++* ++* @brief DMA device driver defines and prototypes. ++* ++****************************************************************************/ ++/** ++* ++* @defgroup DMAGroup Direct Memory Access ++* @ingroup CSLGroup ++* @brief This group defines the APIs for DMA driver ++ ++Click here to navigate back to the Chip Support Library Overview page: \ref CSLOverview. \n ++*****************************************************************************/ ++#ifndef _DMA_DRV_H_ ++#define _DMA_DRV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @addtogroup DMAGroup ++ * @{ ++ */ ++ ++/** ++* ++* DMA driver status definition ++* ++*****************************************************************************/ ++#define DMADRV_STATUS_t DMADRV_STATUS ++typedef enum ++{ ++ DMADRV_STATUS_CLOSED, ++ DMADRV_STATUS_OPEN, ++ DMADRV_STATUS_OK, ++ DMADRV_STATUS_FAIL ++}DMADRV_STATUS_t; ++ ++/** ++* ++* DMA driver callback status definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_STATUS_t DMADRV_CALLBACK_STATUS ++typedef enum ++{ ++ DMADRV_CALLBACK_OK = 0, ++ DMADRV_CALLBACK_FAIL ++} DMADRV_CALLBACK_STATUS_t; ++ ++/** ++* ++* DMA driver channel descriptor definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 src; ++ UInt32 dest; ++ UInt32 next; ++ UInt32 control; ++ UInt32 size; ++ UInt32 owner; ++} Dma_Chan_Desc; ++ ++/** ++* ++* DMA driver data buffer feature definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 srcAddr; ++ UInt32 destAddr; ++ UInt32 length; ++ UInt32 bRepeat; ++ UInt32 interrupt; ++} Dma_Buffer; ++ ++/** ++* ++* DMA driver data buffer definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ Dma_Buffer buffers[1]; ++} Dma_Buffer_List; ++ ++/** ++* ++* DMA driver data buffer list definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ UInt32 numBuffer; ++ Dma_Buffer_List *pBufList; ++} Dma_Data; ++ ++ ++/** ++* ++* DMA data transfer width definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_DATA_SIZE_8BIT = 0x00, ++ DMA_DATA_SIZE_16BIT = 0x01, ++ DMA_DATA_SIZE_32BIT = 0x02 ++} DMA_DWIDTH; ++ ++/** ++* ++* DMA data transfer type definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_FCTRL_MEM_TO_MEM = 0, ++ DMA_FCTRL_MEM_TO_PERI = 1, ++ DMA_FCTRL_PERI_TO_MEM = 2, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI = 3, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_DESTPERI = 4, ++ DMA_FCTRL_MEM_TO_PERI_CTRL_PERI = 5, ++ DMA_FCTRL_PERI_TO_MEM_CTRL_PERI = 6, ++ DMA_FCTRL_SRCPERI_TO_DESTPERI_CTRL_SRCPERI = 7 ++} DMA_CHAN_TYPE; ++ ++/** ++* ++* DMA burst length definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_BURST_LEN_1 = 0x00, ///< ++ DMA_BURST_LEN_2 = 0x01, ///< ++ DMA_BURST_LEN_3 = 0x02, ///< ++ DMA_BURST_LEN_4 = 0x03, ///< ++ DMA_BURST_LEN_5 = 0x04, ///< ++ DMA_BURST_LEN_6 = 0x05, ///< ++ DMA_BURST_LEN_7 = 0x06, ///< ++ DMA_BURST_LEN_8 = 0x07, ///< ++ DMA_BURST_LEN_9 = 0x08, ///< ++ DMA_BURST_LEN_10 = 0x09, ///< ++ DMA_BURST_LEN_11 = 0x0A, ///< ++ DMA_BURST_LEN_12 = 0x0B, ///< ++ DMA_BURST_LEN_13 = 0x0C, ///< ++ DMA_BURST_LEN_14 = 0x0D, ///< ++ DMA_BURST_LEN_15 = 0x0E, ///< ++ DMA_BURST_LEN_16 = 0x0F ///< ++} DMADRV_BLENGTH; ++ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_2 = 0x01, ++ DMA_BURST_SIZE_4 = 0x02, ++ DMA_BURST_SIZE_8 = 0x03, ++ DMA_BURST_SIZE_16 = 0x04, ++ DMA_BURST_SIZE_32 = 0x05, ++ DMA_BURST_SIZE_64 = 0x06, ++ DMA_BURST_SIZE_128 = 0x07 ++} DMA_BSIZE; ++ ++#else ++/** ++* ++* DMA burst size definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_BURST_SIZE_1 = 0x00, ++ DMA_BURST_SIZE_4 = 0x01, ++ DMA_BURST_SIZE_8 = 0x02, ++ DMA_BURST_SIZE_16 = 0x03, ++ DMA_BURST_SIZE_32 = 0x04, ++ DMA_BURST_SIZE_64 = 0x05, ++ DMA_BURST_SIZE_128 = 0x06, ++ DMA_BURST_SIZE_256 = 0x07 ++} DMA_BSIZE; ++#endif ++ ++/** ++* ++* DMA alignment definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_ALIGNMENT_8 = 8, ++ DMA_ALIGNMENT_16 = 16, ++ DMA_ALIGNMENT_32 = 32 ++} DMA_ALIGN; ++ ++/** ++* ++* DMA data transfer incremnet definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_INC_MODE_NONE = 0, ++ DMA_INC_MODE_SRC, ++ DMA_INC_MODE_DST, ++ DMA_INC_MODE_BOTH, ++} DMA_INC_MODE; ++ ++/** ++* ++* DMA driver client type definition ++* ++*****************************************************************************/ ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++typedef enum { ++ DMA_CLIENT_EP_INVALID = 0xff, ++ DMA_CLIENT_EP_UARTB_A = 8, ++ DMA_CLIENT_EP_UARTB_B = 9, ++ DMA_CLIENT_EP_UARTB2_A = 10, ++ DMA_CLIENT_EP_UARTB2_B = 11, ++ DMA_CLIENT_EP_UARTB3_A = 12, ++ DMA_CLIENT_EP_UARTB3_B = 13, ++ DMA_CLIENT_EP_SSP_0A_RX0 = 16, ++ DMA_CLIENT_EP_SSP_0B_TX0 = 17, ++ DMA_CLIENT_EP_SSP_0C_RX1 = 18, ++ DMA_CLIENT_EP_SSP_0D_TX1 = 19, ++ DMA_CLIENT_EP_SSP_1A_RX0 = 20, ++ DMA_CLIENT_EP_SSP_1B_TX0 = 21, ++ DMA_CLIENT_EP_SSP_1C_RX1 = 22, ++ DMA_CLIENT_EP_SSP_1D_TX1 = 23, ++ DMA_CLIENT_EP_HSIA = 32, ++ DMA_CLIENT_EP_HSIB = 33, ++ DMA_CLIENT_EP_HSIC = 34, ++ DMA_CLIENT_EP_HSID = 35, ++ DMA_CLIENT_EP_EANC = 40, ++ DMA_CLIENT_EP_STEREO = 41, ++ DMA_CLIENT_EP_NVIN = 42, ++ DMA_CLIENT_EP_VIN = 43, ++ DMA_CLIENT_EP_VIBRA = 44, ++ DMA_CLIENT_EP_IHF_0 = 45, ++ DMA_CLIENT_EP_VOUT = 46, ++ DMA_CLIENT_EP_SLIMA = 47, ++ DMA_CLIENT_EP_SLIMB = 48, ++ DMA_CLIENT_EP_SLIMC = 49, ++ DMA_CLIENT_EP_SLIMD = 50, ++ DMA_CLIENT_EP_SIM_A = 51, ++ DMA_CLIENT_EP_SIM_B = 52, ++ DMA_CLIENT_EP_SIM2_A = 53, ++ DMA_CLIENT_EP_SIM2_B = 54, ++ DMA_CLIENT_EP_IHF_1 = 55, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_3A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_3B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_3C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_3D_TX1 = 59, ++#else ++ DMA_CLIENT_EP_SSP_2A_RX0 = 56, ++ DMA_CLIENT_EP_SSP_2B_TX0 = 57, ++ DMA_CLIENT_EP_SSP_2C_RX1 = 58, ++ DMA_CLIENT_EP_SSP_2D_TX1 = 59, ++#endif ++ DMA_CLIENT_EP_SPUM_SecureA = 65, ++ DMA_CLIENT_EP_SPUM_SecureB = 66, ++ DMA_CLIENT_EP_SPUM_OpenA = 67, ++ DMA_CLIENT_EP_SPUM_OpenB = 68, ++ DMA_CLIENT_MEMORY = 69, ++#if defined(_RHEA_) ++ DMA_CLIENT_EP_SSP_4A_RX0 = 76, ++ DMA_CLIENT_EP_SSP_4B_TX0 = 77, ++ DMA_CLIENT_EP_SSP_4C_RX1 = 78, ++ DMA_CLIENT_EP_SSP_4D_TX1 = 79, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#else ++typedef enum ++{ ++ DMA_CLIENT_BULK_CRYPT_OUT = 0, ++ DMA_CLIENT_CAM = 1, ++ DMA_CLIENT_I2S_TX = 2, ++ DMA_CLIENT_I2S_RX = 3, ++ DMA_CLIENT_SIM_RX = 4, ++ DMA_CLIENT_SIM_TX = 4, ++ DMA_CLIENT_CRC = 5, ++ DMA_CLIENT_SPI_RX = 6, ++ DMA_CLIENT_SPI_TX = 7, ++ DMA_CLIENT_UARTA_RX = 8, ++ DMA_CLIENT_UARTA_TX = 9, ++ DMA_CLIENT_UARTB_RX = 10, ++ DMA_CLIENT_UARTB_TX = 11, ++ DMA_CLIENT_DES_IN = 12, ++ DMA_CLIENT_DES_OUT = 13, ++ DMA_CLIENT_USB_RX = 14, ++ DMA_CLIENT_USB_TX = 15, ++ DMA_CLIENT_UARTC_RX = 16, ++ DMA_CLIENT_UARTC_TX = 17, ++ DMA_CLIENT_BULK_CRYPT_IN = 18, ++ DMA_CLIENT_LCD = 19, ++ DMA_CLIENT_MSPRO = 20, ++ DMA_CLIENT_DSI_CM = 21, ++ DMA_CLIENT_DSI_VM = 22, ++ DMA_CLIENT_TVENC1 = 23, ++ DMA_CLIENT_TVENC2 = 24, ++#if defined(_ATHENA_) ++ DMA_CLIENT_AUDIO_IN_FIFO = 25, ++ DMA_CLIENT_AUDIO_OUT_FIFO = 26, ++ DMA_CLIENT_POLYRING_OUT_FIFO = 27, ++ DMA_CLIENT_AUDIO_WB_MIXERTAP = 28, ++ DMA_CLIENT_MEMORY = 29, ++#else ++ DMA_CLIENT_MEMORY = 25, ++#endif ++ DMA_CLIENT_TOTAL ++} DMA_CLIENT; ++#endif ++ ++/** ++* ++* DMA driver channel definition ++* ++*****************************************************************************/ ++typedef enum ++{ ++ DMA_CHANNEL_INVALID = 0xFF, ++ DMA_CHANNEL_0 = 0, ++ DMA_CHANNEL_1 = 1, ++ DMA_CHANNEL_2 = 2, ++ DMA_CHANNEL_3 = 3, ++#if !defined(_SAMOA_) ++ DMA_CHANNEL_4 = 4, ++ DMA_CHANNEL_5 = 5, ++ DMA_CHANNEL_6 = 6, ++ DMA_CHANNEL_7 = 7, ++#if defined(_ATHENA_) ++ DMA_CHANNEL_8 = 8, //used for DMA_CLIENT_AUDIO_OUT_FIFO ++ DMA_CHANNEL_9 = 9, //used for DMA_CLIENT_POLYRING_OUT_FIFO ++ DMA_CHANNEL_10 = 10, //used for DMA_CLIENT_AUDIO_WB_MIXERTAP ++ DMA_CHANNEL_11 = 11, //used for DMA_CLIENT_AUDIO_IN_FIFO ++#endif ++#endif ++ TOTAL_DMA_CHANNELS ++} DMA_CHANNEL; ++ ++/** ++* ++* DMA driver callback function definition ++* ++*****************************************************************************/ ++#define DMADRV_CALLBACK_t DmaDrv_Callback ++typedef void (*DMADRV_CALLBACK_t)(DMADRV_CALLBACK_STATUS_t Err); ++ ++/** ++* ++* DMA driver channel info structure definition ++* ++*****************************************************************************/ ++typedef struct ++{ ++ DMA_CLIENT srcID; ++ DMA_CLIENT dstID; ++ DMA_CHAN_TYPE type; ++ DMA_ALIGN alignment; ++ DMA_BSIZE srcBstSize; ++ DMA_BSIZE dstBstSize; ++ DMA_DWIDTH srcDataWidth; ++ DMA_DWIDTH dstDataWidth; ++ UInt32 priority; ++ UInt32 chanNumber; ++ UInt32 dmaCfgReg; ++ UInt32 incMode; ++ DmaDrv_Callback xferCompleteCb; ++ UInt32 prot; ++ UInt32 dstMaster; ++ UInt32 srcMaster; ++ UInt32 dstIncrement; ++ UInt32 srcIncrement; ++#if (defined(_HERA_) || defined(_RHEA_) || defined(_SAMOA_)) ++ DMADRV_BLENGTH srcBstLength; ++ DMADRV_BLENGTH dstBstLength; ++#endif ++ Boolean freeChan; ++ Boolean bCircular; ++} Dma_Chan_Info, *pChanInfo; ++ ++/** ++* ++* DMA driver LLI structure definition ++* ++*****************************************************************************/ ++typedef void *DMADRV_LLI_T; ++ ++/** ++* ++* This function initialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Init(void); ++ ++/** ++* ++* This function deinitialize dma driver ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_DeInit(void); ++ ++/** ++* ++* This function allocates dma channel ++* ++* @param srcID (in) source identification ++* @param dstID (in) destination identification ++* @param chanID (in) buffer to store channel number ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Obtain_Channel( ++ DMA_CLIENT srcID, ++ DMA_CLIENT dstID, ++ DMA_CHANNEL *chanID ++); ++ ++/** ++* ++* This function release dma channel ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Release_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function configure dma channel ++* ++* @param chanID (in) channel number ++* @param pChanInfo (in) pointer to dma channe info structure ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Config_Channel( ++ DMA_CHANNEL chanID, ++ Dma_Chan_Info *pChanInfo ++); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data(DMA_CHANNEL chanID, Dma_Data *pData); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function bind data buffer for the DMA channel ++* ++* @param chanID (in) channel to bind data ++* @param pData (in) pointer to dma channel data buffer ++* @param pLLI (in) buffer to store returned LLI table ++* identification info ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Bind_Data_Ex( ++ DMA_CHANNEL chanID, ++ Dma_Data *pData, ++ DMADRV_LLI_T *pLLI ++); ++ ++/** ++* ++* This function start dma channel transfer ++* ++* @param chanID (in) channel identification ++* @param pLLI (in) one of the LLI tables needs to be used for DMA ++* transfer ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Start_Transfer_Ex( ++ DMA_CHANNEL chanID, ++ DMADRV_LLI_T pLLI ++); ++ ++/** ++* ++* This function stop dma channel trnasfer ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Stop_Transfer(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function stop dma channel trnasfer and lose all data in FIFO ++* ++* @param chanID (in) channel identification ++* ++* @return DMA driver return status ++* ++*****************************************************************************/ ++DMADRV_STATUS DMADRV_Force_Shutdown_Channel(DMA_CHANNEL chanID); ++ ++/** ++* ++* This function register hisr for client usage ++* ++* @param client (in) client identification ++* @param hisr (in) registered hisr ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_Register_HISR(DMA_CLIENT client, void *hisr); ++ ++/** ++* ++* This function unregister hisr from client usage ++* ++* @param client (in) client identification ++* ++* @return void ++* ++*****************************************************************************/ ++void DMADRV_UnRegister_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get hisr for client usage ++* ++* @param client (in) client identification ++* ++* @return hisr (out) return registered client's hisr ++* ++*****************************************************************************/ ++void *DMADRV_Get_HISR(DMA_CLIENT client); ++ ++/** ++* ++* This function get DMA driver version number ++* ++* @return driver version number ++* ++*****************************************************************************/ ++UInt32 DMADRV_Get_Version(void); ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DMA_DRV_H_ */ +diff --git a/drivers/bcmdrivers/dma/pl330-pdata.h b/drivers/bcmdrivers/dma/pl330-pdata.h +new file mode 100644 +index 0000000..21c74c8 +--- /dev/null ++++ b/drivers/bcmdrivers/dma/pl330-pdata.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef __DMA_PL330_PDATA_H ++#define __DMA_PL330_PDATA_H ++ ++/* ++ * The platforms just need to provide this info to the KONA DMA API ++ */ ++struct iproc_pl330_data { ++ /* Non Secure DMAC virtual base address */ ++ unsigned int dmac_ns_base; ++ /* Secure DMAC virtual base address */ ++ unsigned int dmac_s_base; ++ /* # of PL330 dmac channels 'configurable' */ ++ unsigned int num_pl330_chans; ++ /* DMAC irq number, connected to GIC */ ++ int irq_base; ++ /* # of PL330 Interrupts/events 'configurable' */ ++ unsigned int irq_line_count; ++ //int dmac_abort_irq; ++}; ++ ++#endif /* __DMA_PL330_PDATA_H */ +diff --git a/drivers/bcmdrivers/gmac/et/.gitignore b/drivers/bcmdrivers/gmac/et/.gitignore +new file mode 100644 +index 0000000..752a208 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/.gitignore +@@ -0,0 +1,6 @@ ++/.built-in.o.cmd ++/.et.o.cmd ++/built-in.o ++/et.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gmac/et/Kconfig b/drivers/bcmdrivers/gmac/et/Kconfig +new file mode 100644 +index 0000000..53f6462 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/Kconfig +@@ -0,0 +1,14 @@ ++config IPROC_GMAC ++ tristate "GMAC support " ++ select NETDEVICES ++ select PCI ++ select HND ++ select ET ++ select ET_47XX ++ select ET_ALL_PASSIVE_ON ++ depends on ARCH_IPROC ++ default n ++ help ++ Add GMAC support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/gmac/et/Makefile b/drivers/bcmdrivers/gmac/et/Makefile +new file mode 100755 +index 0000000..4f603a0 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/et/Makefile +@@ -0,0 +1,97 @@ ++# ++# Makefile for the Broadcom et driver ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.5 2010-12-07 04:47:36 $ ++# ++ ++ ++ETSRCDIR := ../src/et ++ ++et-objs := $(ETSRCDIR)/sys/et_linux.o $(ETSRCDIR)/sys/etc.o ++ ++## from linux dir ########## ++export SRCBASE_et := $(src)/$(ETSRCDIR)/sys/../../ ++KBUILD_CFLAGS += -I$(SRCBASE_et)/include ++KBUILD_AFLAGS += -I$(SRCBASE_et)/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++KBUILD_CFLAGS += -DCFG_NORTHSTAR -DCFG_SIM ++ ++######## ######################### ++ ++#EXTRA_CFLAGS += -DGMAC3 ++ ++EXTRA_CFLAGS += -DGMAC_RATE_LIMITING ++ ++ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) ++EXTRA_CFLAGS += -DBCMDMASGLISTOSL ++endif ++ ++ifeq ($(CONFIG_ET_47XX),y) ++et-objs += $(ETSRCDIR)/sys/etcgmac.o ++EXTRA_CFLAGS += -DCFG_GMAC -DBCMDMA64 -DBCMDMA32 -DBCMDBG_ERR ++ifeq ($(CONFIG_ROOT_NFS),y) ++else ++ifeq ($(CONFIG_MACH_NS),y) ++EXTRA_CFLAGS += -DETROBO ++endif ++endif ++ifeq ($(CONFIG_MACH_NSP),y) ++EXTRA_CFLAGS += -DETROBO ++endif ++endif ++ ++obj-$(CONFIG_ET) := et.o ++ ++EXTRA_CFLAGS += -DDMA -Wno-error ++ifeq ($(CONFIG_ET_ALL_PASSIVE_ON),y) ++#EXTRA_CFLAGS += -DET_ALL_PASSIVE_ON -DET_ALL_PASSIVE ++# Forcing the use of CONFIG_ET_ALL_PASSIVE_RUNTIME ++EXTRA_CFLAGS += -DET_ALL_PASSIVE ++else ++ifeq ($(CONFIG_ET_ALL_PASSIVE_RUNTIME),y) ++EXTRA_CFLAGS += -DET_ALL_PASSIVE ++endif ++endif ++ ++ifeq ($(CONFIG_ET_NAPI_POLL),y) ++EXTRA_CFLAGS += -DNAPI_POLL ++else ++ifeq ($(CONFIG_ET_NAPI2_POLL),y) ++EXTRA_CFLAGS += -DNAPI2_POLL ++endif ++endif ++ ++# Disable PKTC for now, it is required the CTF enabled ++#EXTRA_CFLAGS += -DPKTC ++ ++# Search for sources under src/et/sys or objects under src/et/linux ++EXTRA_CFLAGS += -I$(src)/$(ETSRCDIR)/sys ++ ++ifneq ($(KERNELRELEASE),) ++# kbuild part of makefile ++else ++# Normal makefile ++KERNELDIR := ../../kernel/linux ++all: ++ $(MAKE) -C $(KERNELDIR) M=`pwd` ++ ++clean: ++ $(MAKE) -C $(KERNELDIR) M=`pwd` clean ++endif ++ ++clean-files += $(ETSRCDIR)/sys/*.o $(ETSRCDIR)/sys/.*.o.cmd +diff --git a/drivers/bcmdrivers/gmac/hnd/.gitignore b/drivers/bcmdrivers/gmac/hnd/.gitignore +new file mode 100644 +index 0000000..e015903 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/.gitignore +@@ -0,0 +1,6 @@ ++/.built-in.o.cmd ++/.hnd.o.cmd ++/built-in.o ++/hnd.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gmac/hnd/Kconfig b/drivers/bcmdrivers/gmac/hnd/Kconfig +new file mode 100755 +index 0000000..e57b937 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/Kconfig +@@ -0,0 +1,197 @@ ++# ++# Broadcom Home Networking Division (HND) driver configuration ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Kconfig,v 1.6 2010-07-05 07:01:45 $ ++# ++ ++menu "Broadcom HND network devices" ++# Kenlo depends on PCI ++config HND ++ bool "Broadcom HND network device support" ++config ET ++ tristate "10/100 Ethernet support" ++ depends on HND ++config ET_47XX ++ bool "BCM47xx support" ++ depends on ET ++choice ++ prompt "ET ALL PASSIVE mode" ++ depends on ET ++ optional ++config ET_ALL_PASSIVE_ON ++ bool "ET ALL PASSIVE on" ++config ET_ALL_PASSIVE_RUNTIME ++ bool "ET ALL PASSIVE with runtime setting" ++endchoice ++config ET_NAPI2_POLL ++ bool "BCM GMAC NAPI2_POLL" ++ default n ++ depends on !ET_ALL_PASSIVE_ON && !ET_ALL_PASSIVE_RUNTIME ++config BCM_CTF ++ tristate "BCMCTF support" ++ depends on HND ++config BCM_CTF2 ++ tristate "BCMCTF2 support (NETFILTER and NF_DEFRAG_IPV4 required)" ++ depends on HND ++ default n ++ help ++ Add BCM_CTF2 support for performance enhancements with WLAN integration in LDK ++config BCM_IPROC_GMAC_ACP ++ tristate "BCM GMAC_ACP support" ++ depends on HND ++ default n ++ help ++ Add GMAC_ACP support to improve performance without ++ cache flushing/invalidate. The uboot's bootargs must ++ include "mem=240M" to limit whole Kernel memory inside ++ ACP region which is 256MB from 0x80000000; since kernel ++ starts from 0x81000000, total mem is 240MB only ++ If unsure, say N. ++config BCM_IPROC_GMAC_PREFETCH ++ tristate "BCM GMAC prefetching support" ++ depends on HND ++ default n ++ help ++ If unsure, say N. ++config BCM_IPROC_GMAC_TXONCPU1 ++ tristate "BCM GMAC TX-ON-CPU1 support" ++ depends on HND && SMP && (ET_ALL_PASSIVE_ON || ET_ALL_PASSIVE_RUNTIME) ++ default n ++ help ++ Run "Passive Mode" Tx workthread on CPU1 for ++ multi-cores utilizing; ++ If unsure, say N. ++config BCM_IPROC_GMAC_SKB_RECYCLING ++ tristate "BCM GMAC SKB-RECYCLING support" ++ depends on HND ++ default n ++ help ++ Recycle Tx/Rx skb_buff for high-speed IP forwarding tasks; ++ it is still an experimental feature now. ++ If unsure, say N. ++config BCM_IPROC_GMAC_LOCK_OPT ++ tristate "BCM GMAC LOCK OPTIMIZATION support" ++ depends on HND ++ default n ++ help ++ Minimize locks during Tx/Rx tasks; ++ it is tested under "Passive Mode" (workthread) only. ++ If unsure, say N. ++config BCM_IPROC_GMAC_RWREG_OPT ++ tristate "BCM GMAC R/W_REG OPTIMIZATION support" ++ depends on HND ++ default n ++ help ++ Remove unnecessary "DSB" intructions of R/W_REG Macro. ++ If unsure, say N. ++config BCM_IPROC_GMAC_SG ++ bool "BCM GMAC Scatter Gather support" ++ default n ++ depends on HND ++config WL_EMULATOR ++ bool "WL emulation using Gigabit ethernet" ++ depends on HND ++config BCM57XX ++ tristate "BCM57xx support is ON" ++ depends on WL_EMULATOR ++config WL ++ tristate "Wireless feature variant is set to AP" ++ depends on WL_EMULATOR ++ select WL_USE_AP ++config BCM57XX ++ tristate "BCM57xx Gigabit Ethernet support" ++ depends on HND && !WL_EMULATOR ++config WL ++ tristate "BCM43xx 802.11 Wireless support" ++ depends on HND && !WL_EMULATOR ++config WAPI ++ bool "Wireless Authentication Privacy Infrastructure (WAPI) support" ++ depends on HND && !WL_EMULATOR && WL ++ select MTD_BCMCONF_PARTS ++choice ++ prompt "Wireless feature variant" ++ depends on HND && !WL_EMULATOR && WL ++config WL_USE_AP ++ bool "Config file for basic AP variant" ++config WL_USE_AP_SDSTD ++ bool "Config file for basic AP sdstd variant" ++config WL_USE_STA ++ bool "Config file for basic STA variant" ++config WL_USE_APSTA ++ bool "Config file for basic APSTA variant" ++config WL_USE_AP_ONCHIP_G ++ bool "Config file for AP 1chipG variant" ++config WL_USE_STA_ONCHIP_G ++ bool "Config file for STA 1chipG variant" ++config WL_USE_APSTA_ONCHIP_G ++ bool "Config file for APSTA 1chipG variant" ++endchoice ++config WL_USBAP ++ bool "USB/HSIC Wireless Access Point support" ++config WL_AP ++ string "Config file for basic AP variant" ++ default "wlconfig_lx_router_ap" ++config WL_AP_SDSTD ++ string "Config file for basic AP sdstd variant" ++ default "wlconfig_lx_router_ap_sdstd" ++config WL_STA ++ string "Config file for basic STA variant" ++ default "wlconfig_lx_router_sta" ++config WL_APSTA ++ string "Config file for basic APSTA variant" ++ default "wlconfig_lx_router_apsta" ++config WL_AP_ONCHIP_G ++ string "Config file for AP 1chipG variant" ++ default "wlconfig_lx_router_ap_1chipG" ++config WL_STA_ONCHIP_G ++ string "Config file for STA 1chipG variant" ++ default "wlconfig_lx_router_sta_1chipG" ++config WL_HIGH ++ string "Config file for high/bmac split variant" ++ default "wlconfig_lx_router_high" ++ ++choice ++ prompt "WL ALL PASSIVE mode" ++ depends on WL ++ ++config WL_ALL_PASSIVE_ON ++ bool "WL ALL PASSIVE on" ++config WL_ALL_PASSIVE_RUNTIME ++ bool "WL ALL PASSIVE with runtime setting" ++endchoice ++config DPSTA ++ tristate "Broadcom dualband wireless proxy repeater support" ++ depends on WL ++config EMF ++ tristate "Efficient Multicast Forwarding & IGMP Snooping Layers" ++ depends on NETFILTER ++config PLC ++ bool "Broadcom PLC network failover support" ++ depends on ET && WL ++config IPROC_SDK_MGT_PORT_HANDOFF ++ bool "GMAC SDK Management port handoff" ++ default y ++ depends on HND ++config IPROC_2STAGE_RX ++ bool "GMAC 2 stage packet RX" ++ default n ++ depends on HND ++config SERDES_ASYMMETRIC_MODE ++ bool "GMAC SDK Serdes Asymmetric Mode" ++ default n ++ depends on HND && (MACH_KT2 || MACH_HX4) ++endmenu +diff --git a/drivers/bcmdrivers/gmac/hnd/Makefile b/drivers/bcmdrivers/gmac/hnd/Makefile +new file mode 100755 +index 0000000..83c02e2 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/Makefile +@@ -0,0 +1,175 @@ ++# ++# Makefile for Broadcom Home Networking Division (HND) shared driver code ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: Makefile,v 1.5 2008-05-02 22:49:54 $ ++# ++ ++SHARED := ../src/shared ++ ++include $(src)/$(SHARED)/wl_config ++ ++## from linux dir ########## ++export SRCBASE_hnd := $(src)/$(SHARED)/../ ++KBUILD_CFLAGS += -I$(SRCBASE_hnd)/include ++KBUILD_AFLAGS += -I$(SRCBASE_hnd)/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++KBUILD_CFLAGS += -DCFG_NORTHSTAR -DCFG_SIM ++ ++################################# ++ ++EXTRA_CFLAGS += $(WLFLAGS) -DBCM5354 -DLINUX_HYBRID_POSTPROCESSING_REMOVAL -DBCMDBG_ERR ++ ++ifeq ($(CONFIG_BCM_IPROC_GMAC_SG),y) ++EXTRA_CFLAGS += -DBCMDMASGLISTOSL ++endif ++ ++### for bcm5301x_otp.h ++EXTRA_CFLAGS += -I$(src)/../../otp/ ++ ++ ++#HND_OBJS += $(src)/$(SHARED)/hndfwd.o ++#hnd-objs += $(SHARED)/hndfwd.o ++#EXTRA_CFLAGS += -DGMAC3 ++ ++ifneq ($(CONFIG_BCM947XX),y) ++HND_OBJS += $(src)/$(SHARED)/nvramstubs.o ++hnd-objs += $(SHARED)/nvramstubs.o ++endif ++ ++ifeq ($(CONFIG_MACH_HX4),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_DNI_3448P),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_ACCTON_AS4610_54),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ifeq ($(CONFIG_MACH_KT2),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_serdes.o ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5461s.o ++hnd-objs += $(SHARED)/bcmiproc_phy5461s.o ++endif ++ ++ifeq ($(CONFIG_MACH_HR2),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_phy5221.o ++hnd-objs += $(SHARED)/bcmiproc_phy5221.o ++endif ++ ++ifeq ($(CONFIG_MACH_NSP),y) ++HND_OBJS += $(src)/$(SHARED)/bcmiproc_robo_serdes.o ++hnd-objs += $(SHARED)/bcmiproc_robo_serdes.o ++endif ++ ++ifeq ($(CONFIG_ET_47XX),y) ++HND_OBJS += $(src)/$(SHARED)/bcmrobo.o ++hnd-objs += $(SHARED)/bcmrobo.o ++endif ++ ++#ifdef HNDDMA ++ifeq ($(HNDDMA),1) ++HND_OBJS += $(src)/$(SHARED)/hnddma.o ++hnd-objs += $(SHARED)/hnddma.o ++endif ++#endif ++ ++#ifdef BCMUTILS ++ifeq ($(BCMUTILS),1) ++HND_OBJS += $(src)/$(SHARED)/bcmutils.o ++hnd-objs += $(SHARED)/bcmutils.o ++endif ++#endif ++ ++#ifdef SIUTILS ++ifeq ($(SIUTILS),1) ++HND_OBJS += $(src)/$(SHARED)/siutils.o ++hnd-objs += $(SHARED)/siutils.o ++HND_OBJS += $(src)/$(SHARED)/aiutils.o ++hnd-objs += $(SHARED)/aiutils.o ++ifeq ($(CONFIG_MACH_HX4),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_DNI_3448P),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_ACCTON_AS4610_54),y) ++HND_OBJS += $(src)/$(SHARED)/hx4_erom.o ++hnd-objs += $(SHARED)/hx4_erom.o ++endif ++ifeq ($(CONFIG_MACH_HR2),y) ++HND_OBJS += $(src)/$(SHARED)/hr2_erom.o ++hnd-objs += $(SHARED)/hr2_erom.o ++endif ++ifeq ($(CONFIG_MACH_NSP),y) ++HND_OBJS += $(src)/$(SHARED)/nsp_erom.o ++hnd-objs += $(SHARED)/nsp_erom.o ++endif ++ifeq ($(CONFIG_MACH_KT2),y) ++HND_OBJS += $(src)/$(SHARED)/kt2_erom.o ++hnd-objs += $(SHARED)/kt2_erom.o ++endif ++endif ++#endif /* SIUTILS */ ++ ++#ifdef BCMSROM ++ifeq ($(BCMSROM),1) ++HND_OBJS += $(src)/$(SHARED)/bcmsrom.o ++hnd-objs += $(SHARED)/bcmsrom.o ++HND_OBJS += $(src)/$(SHARED)/bcmotp.o ++hnd-objs += $(SHARED)/bcmotp.o ++endif ++#endif ++ ++#ifdef BCMOTP ++ifeq ($(BCMOTP),1) ++ifneq ($(BCMSROM),1) ++HND_OBJS += $(src)/$(SHARED)/bcmotp.o ++hnd-objs += $(SHARED)/bcmotp.o ++endif ++EXTRA_CFLAGS += -DBCMNVRAMR ++endif ++#endif ++ ++#ifdef OSLLX ++# linux osl ++ifeq ($(OSLLX),1) ++HND_OBJS += $(src)/$(SHARED)/linux_osl.o ++hnd-objs += $(SHARED)/linux_osl.o ++endif ++#endif ++ ++# BCMDMA32 ++ifeq ($(BCMDMA32),1) ++EXTRA_CFLAGS += -DBCMDMA32 ++endif ++ ++obj-$(CONFIG_HND) := hnd.o ++ ++hnd-objs += shared_ksyms.o +diff --git a/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c +new file mode 100755 +index 0000000..a615f54 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.c +@@ -0,0 +1,62 @@ ++#include ++#include ++#include ++#include ++#include ++EXPORT_SYMBOL(bcm_atoi); ++EXPORT_SYMBOL(bcm_binit); ++EXPORT_SYMBOL(bcm_bprintf); ++EXPORT_SYMBOL(bcm_ether_atoe); ++EXPORT_SYMBOL(bcm_ether_ntoa); ++EXPORT_SYMBOL(bcm_robo_attach); ++EXPORT_SYMBOL(bcm_robo_config_vlan); ++EXPORT_SYMBOL(bcm_robo_detach); ++EXPORT_SYMBOL(bcm_robo_enable_device); ++EXPORT_SYMBOL(bcm_robo_enable_switch); ++EXPORT_SYMBOL(bcm_strtoul); ++EXPORT_SYMBOL(getgpiopin); ++EXPORT_SYMBOL(getintvar); ++EXPORT_SYMBOL(getvar); ++EXPORT_SYMBOL(nvram_env_gmac_name); ++EXPORT_SYMBOL(nvram_get); ++#ifdef CTFPOOL ++EXPORT_SYMBOL(osl_ctfpool_add); ++EXPORT_SYMBOL(osl_ctfpool_cleanup); ++EXPORT_SYMBOL(osl_ctfpool_init); ++EXPORT_SYMBOL(osl_ctfpool_replenish); ++EXPORT_SYMBOL(osl_ctfpool_stats); ++#endif ++EXPORT_SYMBOL(osl_delay); ++EXPORT_SYMBOL(osl_detach); ++EXPORT_SYMBOL(osl_dma_map); ++EXPORT_SYMBOL(osl_malloc); ++EXPORT_SYMBOL(osl_malloced); ++EXPORT_SYMBOL(osl_mfree); ++EXPORT_SYMBOL(osl_pkt_frmnative); ++EXPORT_SYMBOL(osl_pkt_tonative); ++EXPORT_SYMBOL(osl_pktfree); ++EXPORT_SYMBOL(pktsetprio); ++EXPORT_SYMBOL(robo_bprintf_mib); ++EXPORT_SYMBOL(robo_dump_mib); ++EXPORT_SYMBOL(robo_dump_regs); ++EXPORT_SYMBOL(robo_is_port_cfg); ++EXPORT_SYMBOL(robo_power_save_mode_get); ++EXPORT_SYMBOL(robo_power_save_mode_set); ++EXPORT_SYMBOL(robo_power_save_mode_update); ++EXPORT_SYMBOL(robo_power_save_toggle); ++EXPORT_SYMBOL(robo_reset_mib); ++EXPORT_SYMBOL(robo_watchdog); ++EXPORT_SYMBOL(si_core_cflags); ++EXPORT_SYMBOL(si_core_disable); ++EXPORT_SYMBOL(si_core_reset); ++EXPORT_SYMBOL(si_core_sflags); ++EXPORT_SYMBOL(si_coreid); ++EXPORT_SYMBOL(si_coreidx); ++EXPORT_SYMBOL(si_corerev); ++EXPORT_SYMBOL(si_coreunit); ++EXPORT_SYMBOL(si_detach); ++EXPORT_SYMBOL(si_gpioout); ++EXPORT_SYMBOL(si_gpioouten); ++EXPORT_SYMBOL(si_iscoreup); ++EXPORT_SYMBOL(si_kattach); ++EXPORT_SYMBOL(si_setcoreidx); +diff --git a/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh +new file mode 100755 +index 0000000..8b537a3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/hnd/shared_ksyms.sh +@@ -0,0 +1,30 @@ ++#!/bin/sh ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# ++# $Id: shared_ksyms.sh,v 1.2 2008-12-05 20:10:41 $ ++# ++ ++cat < ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include ++#endif ++EOF ++ ++for file in $* ; do ++ ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [BDRT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' ++done +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/.gitignore b/drivers/bcmdrivers/gmac/src/et/sys/.gitignore +new file mode 100644 +index 0000000..25794d4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/.gitignore +@@ -0,0 +1,6 @@ ++/.et_linux.o.cmd ++/.etc.o.cmd ++/.etcgmac.o.cmd ++/et_linux.o ++/etc.o ++/etcgmac.o +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h b/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h +new file mode 100755 +index 0000000..38ded3d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_cfg.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM ET driver config options ++ * ++ * $Id: et_cfg.h,v 1.1.4.1 2010-08-05 19:17:00 $ ++ */ ++ ++#if defined(__NetBSD__) || defined(__FreeBSD__) ++#include ++#include ++#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h b/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h +new file mode 100755 +index 0000000..7d209a1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_dbg.h +@@ -0,0 +1,59 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Minimal debug/trace/assert driver definitions for ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Device Driver. ++ * ++ * $Id: et_dbg.h 286404 2011-09-27 19:29:08Z $ ++ */ ++ ++#ifndef _et_dbg_ ++#define _et_dbg_ ++ ++#ifdef BCMDBG ++struct ether_header; ++extern void etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit); ++extern void etc_prhex(char *msg, uchar *buf, uint nbytes, int unit); ++/* ++ * et_msg_level is a bitvector: ++ * 0 errors ++ * 1 function-level tracing ++ * 2 one-line frame tx/rx summary ++ * 3 complex frame tx/rx in hex ++ */ ++#define ET_ERROR(args) if (!(et_msg_level & 1)) ; else printf args ++#define ET_TRACE(args) if (!(et_msg_level & 2)) ; else printf args ++#define ET_PRHDR(msg, eh, len, unit) if (!(et_msg_level & 4)) ; else etc_prhdr(msg, eh, len, unit) ++#define ET_PRPKT(msg, buf, len, unit) if (!(et_msg_level & 8)) ; else etc_prhex(msg, buf, len, unit) ++#else /* BCMDBG */ ++#define ET_ERROR(args) ++#define ET_TRACE(args) ++#define ET_PRHDR(msg, eh, len, unit) ++#define ET_PRPKT(msg, buf, len, unit) ++#endif /* BCMDBG */ ++ ++extern uint32 et_msg_level; ++ ++#define ET_LOG(fmt, a1, a2) ++ ++/* include port-specific tunables */ ++#if defined(linux) ++#include ++#else ++#error ++#endif ++ ++#endif /* _et_dbg_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_export.h b/drivers/bcmdrivers/gmac/src/et/sys/et_export.h +new file mode 100755 +index 0000000..e06bf27 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_export.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Required functions exported by the port-specific (os-dependent) driver ++ * to common (os-independent) driver code. ++ * ++ * $Id: et_export.h 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#ifndef _et_export_h_ ++#define _et_export_h_ ++ ++/* misc callbacks */ ++extern void et_init(void *et, uint options); ++extern void et_reset(void *et); ++extern void et_link_up(void *et); ++extern void et_link_down(void *et); ++extern bool et_is_link_up(void *et); ++extern int et_up(void *et); ++extern int et_down(void *et, int reset); ++extern void et_dump(void *et, struct bcmstrbuf *b); ++extern void et_intrson(void *et); ++ ++/* for BCM5222 dual-phy shared mdio contortion */ ++extern void *et_phyfind(void *et, uint coreunit); ++extern uint16 et_phyrd(void *et, uint phyaddr, uint reg); ++extern void et_phywr(void *et, uint reg, uint phyaddr, uint16 val); ++#ifdef HNDCTF ++extern void et_dump_ctf(void *et, struct bcmstrbuf *b); ++#endif ++#endif /* _et_export_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c +new file mode 100755 +index 0000000..e510812 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.c +@@ -0,0 +1,3896 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux device driver for ++ * Broadcom BCM47XX 10/100/1000 Mbps Ethernet Controller ++ * ++ * $Id: et_linux.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#include ++#define __UNDEF_NO_VERSION__ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef SIOCETHTOOL ++#include ++#endif /* SIOCETHTOOL */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HNDCTF ++#include ++#endif /* HNDCTF */ ++#ifdef GMAC3 ++#include /* GMAC3 */ ++#endif /* GMAC3 */ ++ ++/* to be cleaned and fixed */ ++/* to be cleaned Makefile */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "plat/shm.h" ++ ++#if defined(CONFIG_IPROC_FA2) ++#include "../../../fa2/fa2_defs.h" ++#include "../../../fa2/fa2_if.h" ++#endif /* CONFIG_IPROC_FA2 */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#include ++ ++#define SKB_PREFETCH_LEN (128) ++ ++/* 30 rxhdr + 34 mac & ip */ ++#define SKB_DATA_PREFETCH_LEN (96) ++ ++#endif ++ ++#define MIN_PACKET_SIZE 70 /* for gmac2 (&GMAC3?) */ ++ /* if packet is less than 64 bytes, it will not tx */ ++ /* if packet is less than 66 bytes, CRC is not generated) */ ++ /* this length is after brm tag is stripped off */ ++#define NS_MAX_GMAC_CORES 4 ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) ++#define HAVE_NET_DEVICE_OPS 1 ++#define HAVE_NETDEV_PRIV 1 ++#endif ++ ++int gmac_pdev_loaded[NS_MAX_GMAC_CORES]; ++ ++/* Global SB handle */ ++si_t *bcm947xx_sih = NULL; ++spinlock_t bcm947xx_sih_lock; ++EXPORT_SYMBOL(bcm947xx_sih); ++EXPORT_SYMBOL(bcm947xx_sih_lock); ++ ++/* Convenience */ ++#define sih bcm947xx_sih ++#define sih_lock bcm947xx_sih_lock ++ ++#ifdef ET_ALL_PASSIVE_ON ++/* When ET_ALL_PASSIVE_ON, ET_ALL_PASSIVE must be true */ ++#define ET_ALL_PASSIVE_ENAB(et) 1 ++#else ++#ifdef ET_ALL_PASSIVE ++#define ET_ALL_PASSIVE_ENAB(et) (!(et)->all_dispatch_mode) ++#else /* ET_ALL_PASSIVE */ ++#define ET_ALL_PASSIVE_ENAB(et) 0 ++#endif /* ET_ALL_PASSIVE */ ++#endif /* ET_ALL_PASSIVE_ON */ ++ ++//#define BRCM_TAG true ++//#define PRINT_PKT true ++//#define PRINT_PKT_SUM true ++ ++#ifdef ET_ALL_PASSIVE ++#define ET_LIMIT_TXQ ++#endif ++ ++#ifdef PKTC ++#ifndef HNDCTF ++#error "Packet chaining feature can't work w/o CTF" ++#endif ++#define PKTC_ENAB(et) ((et)->etc->pktc) ++ ++#ifdef GMAC3 ++#define PKT_CHAINABLE(et, p, evh, prio, h_sa, h_da, h_prio) \ ++ (!eacmp((h_da), ((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_sa), ((struct ethervlan_header *)(evh))->ether_shost) && \ ++ ((h_prio) == (prio)) && !RXH_FLAGS((et)->etc, PKTDATA((et)->osh, (p))) && \ ++ ((((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \ ++ (((struct ether_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6)))) ++#else /* !GMAC3 */ ++#define PKT_CHAINABLE(et, p, evh, prio, h_sa, h_da, h_prio) \ ++ (!ETHER_ISNULLDEST(((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_da), ((struct ethervlan_header *)(evh))->ether_dhost) && \ ++ !eacmp((h_sa), ((struct ethervlan_header *)(evh))->ether_shost) && \ ++ (et)->brc_hot && CTF_HOTBRC_CMP((et)->brc_hot, (evh), (void *)(et)->dev) && \ ++ ((h_prio) == (prio)) && !RXH_FLAGS((et)->etc, PKTDATA((et)->osh, (p))) && \ ++ (((struct ethervlan_header *)(evh))->vlan_type == HTON16(ETHER_TYPE_8021Q)) && \ ++ ((((struct ethervlan_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IP)) || \ ++ (((struct ethervlan_header *)(evh))->ether_type == HTON16(ETHER_TYPE_IPV6)))) ++#endif /* !GMAC3 */ ++ ++#define PKTCMC 2 ++struct pktc_data { ++ void *chead; /* chain head */ ++ void *ctail; /* chain tail */ ++ uint8 *h_da; /* pointer to da of chain head */ ++ uint8 *h_sa; /* pointer to sa of chain head */ ++ uint8 h_prio; /* prio of chain head */ ++}; ++typedef struct pktc_data pktc_data_t; ++#else /* PKTC */ ++#define PKTC_ENAB(et) 0 ++#define PKT_CHAINABLE(et, p, evh, h_sa, h_da, h_prio) 0 ++#endif /* PKTC */ ++ ++static char bcm5301x_gmac0_string[] = "bcmiproc-gmac0"; ++static char bcm5301x_gmac1_string[] = "bcmiproc-gmac1"; ++static char bcm5301x_gmac2_string[] = "bcmiproc-gmac2"; ++static char bcm5301x_gmac3_string[] = "bcmiproc-gmac3"; ++ ++#ifdef GMAC_RATE_LIMITING ++static int et_rx_rate_limit = 0; ++extern void etc_check_rate_limiting(etc_info_t *etc, void *pch); ++#endif /* GMAC_RATE_LIMITING */ ++extern int nvram_env_gmac_name(int gmac, char *name); ++ ++#if defined(CONFIG_IPROC_FA) ++extern int fc_receive(struct sk_buff *skb_p); ++extern int fc_transmit(struct sk_buff *skb_p); ++#else ++#define fc_receive(arg) {} ++#define fc_transmit(arg) {} ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++#if defined(CONFIG_IPROC_FA2) ++extern int fa2_receive(struct sk_buff *skb_p); ++extern int fa2_transmit(struct sk_buff *skb_p, struct fa2_pkt_info *pkt_info); ++extern int fa2_get_packet_info(struct sk_buff *skb, struct fa2_pkt_info *info); ++extern int fa2_modify_header(struct sk_buff *skb); ++ ++#else ++#define fa2_receive(arg) {} ++#define fa2_transmit(arg) {} ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++extern int gmac_has_mdio_access(void); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++/* In 2.6.20 kernels work functions get passed a pointer to the ++ * struct work, so things will continue to work as long as the work ++ * structure is the first component of the task structure. ++ */ ++typedef struct et_task { ++ struct work_struct work; ++ void *context; ++} et_task_t; ++ ++typedef struct et_info { ++ etc_info_t *etc; /* pointer to common os-independent data */ ++ struct net_device *dev; /* backpoint to device */ ++ struct pci_dev *pdev; /* backpoint to pci_dev */ ++ void *osh; /* pointer to os handle */ ++#ifdef GMAC3 ++ struct fwder *fwdh; /* pointer to my upstream forwarder handle */ ++#endif /* GMAC3 */ ++#ifdef HNDCTF ++ ctf_t *cih; /* ctf instance handle */ ++ ctf_brc_hot_t *brc_hot; /* hot bridge cache entry */ ++#endif ++ struct semaphore sem; /* use semaphore to allow sleep */ ++ spinlock_t lock; /* per-device perimeter lock */ ++ spinlock_t txq_lock; /* lock for txq protection */ ++ spinlock_t tx_lock; /* lock for tx protection */ ++ spinlock_t isr_lock; /* lock for irq reentrancy protection */ ++ struct sk_buff_head txq[NUMTXQ]; /* send queue */ ++ void *regsva; /* opaque chip registers virtual address */ ++ struct timer_list timer; /* one second watchdog timer */ ++ bool set; /* indicate the timer is set or not */ ++ struct net_device_stats stats; /* stat counter reporting structure */ ++ int events; /* bit channel between isr and dpc */ ++ struct et_info *next; /* pointer to next et_info_t in chain */ ++#ifdef NAPI2_POLL ++ struct napi_struct napi_poll; ++#endif /* NAPI2_POLL */ ++#ifndef NAPI_POLL ++ struct tasklet_struct tasklet; /* dpc tasklet */ ++#endif /* NAPI_POLL */ ++#ifdef ET_ALL_PASSIVE ++ et_task_t dpc_task; /* work queue for rx dpc */ ++ et_task_t txq_task; /* work queue for tx frames */ ++ bool all_dispatch_mode; /* dispatch mode: tasklets or passive */ ++#endif /* ET_ALL_PASSIVE */ ++ bool resched; /* dpc was rescheduled */ ++#ifdef CONFIG_IPROC_2STAGE_RX ++ bool rxinisr; ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++} et_info_t; ++ ++static int et_found = 0; ++static et_info_t *et_list = NULL; ++ ++/* defines */ ++#define DATAHIWAT 1000 /* data msg txq hiwat mark */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) ++#define init_MUTEX(x) sema_init(x,1) ++#endif ++ ++ ++#ifndef HAVE_NETDEV_PRIV ++#define HAVE_NETDEV_PRIV ++#define netdev_priv(dev) ((dev)->priv) ++#define ET_INFO(dev) (et_info_t *)((dev)->priv) ++#else ++#define ET_INFO(dev) netdev_priv(dev) ++#endif /* HAVE_NETDEV_PRIV */ ++ ++ ++#define ET_LOCK(et) \ ++do { \ ++ if (ET_ALL_PASSIVE_ENAB(et)) \ ++ down(&(et)->sem); \ ++ else \ ++ spin_lock_bh(&(et)->lock); \ ++} while (0) ++ ++#define ET_UNLOCK(et) \ ++do { \ ++ if (ET_ALL_PASSIVE_ENAB(et)) \ ++ up(&(et)->sem); \ ++ else \ ++ spin_unlock_bh(&(et)->lock); \ ++} while (0) ++ ++#define ET_TXQ_LOCK(et) spin_lock_bh(&(et)->txq_lock) ++#define ET_TXQ_UNLOCK(et) spin_unlock_bh(&(et)->txq_lock) ++ ++#define ET_TX_LOCK(et) spin_lock_bh(&(et)->tx_lock) ++#define ET_TX_UNLOCK(et) spin_unlock_bh(&(et)->tx_lock) ++ ++#define INT_LOCK(et, flags) spin_lock_irqsave(&(et)->isr_lock, flags) ++#define INT_UNLOCK(et, flags) spin_unlock_irqrestore(&(et)->isr_lock, flags) ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) ++#error Linux version must be newer than 2.4.5 ++#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) */ ++ ++/* linux 2.4 doesn't have in_atomic */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) ++#define in_atomic() 0 ++#endif ++ ++/* prototypes called by etc.c */ ++void et_init(et_info_t *et, uint options); ++void et_reset(et_info_t *et); ++void et_link_up(et_info_t *et); ++void et_link_down(et_info_t *et); ++bool et_is_link_down(et_info_t *et); ++void et_up(et_info_t *et); ++void et_down(et_info_t *et, int reset); ++void et_dump(et_info_t *et, struct bcmstrbuf *b); ++#ifdef HNDCTF ++void et_dump_ctf(et_info_t *et, struct bcmstrbuf *b); ++#endif ++ ++/* local prototypes */ ++static void et_free(et_info_t *et); ++static int et_open(struct net_device *dev); ++static int et_close(struct net_device *dev); ++static int et_start(struct sk_buff *skb, struct net_device *dev); ++static void et_sendnext(et_info_t *et); ++static struct net_device_stats *et_get_stats(struct net_device *dev); ++static int et_set_mac_address(struct net_device *dev, void *addr); ++static void et_set_multicast_list(struct net_device *dev); ++static void _et_watchdog(struct net_device *data); ++static void et_watchdog(ulong data); ++#ifdef ET_ALL_PASSIVE ++static void et_watchdog_task(et_task_t *task); ++#endif /* ET_ALL_PASSIVE */ ++static int et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++static irqreturn_t et_isr(int irq, void *dev_id); ++#else ++static irqreturn_t et_isr(int irq, void *dev_id, struct pt_regs *ptregs); ++#endif ++#ifdef NAPI2_POLL ++static int et_poll(struct napi_struct *napi, int budget); ++#elif defined(NAPI_POLL) ++static int et_poll(struct net_device *dev, int *budget); ++#else /* ! NAPI_POLL */ ++static void et_dpc(ulong data); ++#endif /* NAPI_POLL */ ++#ifdef ET_ALL_PASSIVE ++static void et_dpc_work(struct et_task *task); ++static void et_txq_work(struct et_task *task); ++static int et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context); ++#endif /* ET_ALL_PASSIVE */ ++static void et_sendup(et_info_t *et, struct sk_buff *skb); ++static void et_dumpet(et_info_t *et, struct bcmstrbuf *b); ++ ++static int et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd); ++static int et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd); ++static void et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++static const struct ethtool_ops et_ethtool_ops = ++{ ++ .get_settings = et_get_settings, ++ .set_settings = et_set_settings, ++ .get_drvinfo = et_get_driver_info, ++}; ++#endif ++ ++static int bcm5301x_gmac_probe(struct platform_device*); ++static int __exit bcm5301x_gmac_remove(struct platform_device*); ++static int __init bcm5301x_gmac_init_module(void); ++static void __exit bcm5301x_gmac_cleanup_module(void); ++#ifdef CONFIG_PM ++static int bcm5301x_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state); ++static int bcm5301x_gmac_drv_resume(struct platform_device *pdev); ++#endif ++static void bcm5301x_gmac_release (struct device *dev); ++#if 0 //dgb /* Functions related to PROC file system support */ ++static int get_debug_level(char *page, char **start, off_t off, int count, int *eof, void *data); ++static int set_debug_level(struct file *file, const char *buffer, unsigned long count, void *data); ++#define MIN_DEBUG_LEVEL 0 ++#define MAX_DEBUG_LEVEL 3 ++static int cur_dbg_lvl = MIN_DEBUG_LEVEL; ++ ++#endif ++static int eth_mac_proc_create(struct net_device *dev ); ++static void eth_mac_proc_remove(void); ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++static et_info_t *et_get_eth3_info(void); ++#endif ++static int et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota); ++ ++#define DISABLE_FA_BYPASS 0 ++#define ENABLE_FA_BYPASS 1 ++static unsigned int gBypass = DISABLE_FA_BYPASS; ++ ++#ifdef HAVE_NET_DEVICE_OPS ++static const struct net_device_ops et_netdev_ops = { ++ .ndo_open = et_open, ++ .ndo_stop = et_close, ++ .ndo_start_xmit = et_start, ++ .ndo_get_stats = et_get_stats, ++ .ndo_set_mac_address = et_set_mac_address, ++ .ndo_set_rx_mode = et_set_multicast_list, ++ .ndo_do_ioctl = et_ioctl, ++}; ++#endif /*HAVE_NET_DEVICE_OPS*/ ++ ++static struct resource bcm5301x_gmac0_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC0_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC0_REG_BASE, ++ .end = IPROC_GMAC0_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac1_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC1_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC1_REG_BASE, ++ .end = IPROC_GMAC1_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac2_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC2_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC2_REG_BASE, ++ .end = IPROC_GMAC2_REG_BASE+0xbff, ++ }, ++}; ++static struct resource bcm5301x_gmac3_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IPROC_GMAC3_INT, ++ }, ++ [1] = { ++ .flags = IORESOURCE_MEM, ++ .start = IPROC_GMAC3_REG_BASE, ++ .end = IPROC_GMAC3_REG_BASE+0xbff, ++ }, ++}; ++ ++#if defined(BCMDBG) ++static uint32 msglevel = 0xdeadbeef; ++module_param(msglevel, uint, 0644); ++#endif /* defined(BCMDBG) */ ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++static bool brcm_tag=true; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++#ifdef ET_ALL_PASSIVE ++/* passive mode: 1: enable, 0: disable */ ++static int passivemode = 0; ++module_param(passivemode, int, 0); ++#endif /* ET_ALL_PASSIVE */ ++#ifdef ET_LIMIT_TXQ ++#define ET_TXQ_THRESH 0 ++static int et_txq_thresh = ET_TXQ_THRESH; ++module_param(et_txq_thresh, int, 0); ++#endif /* ET_LIMIT_TXQ */ ++ ++#ifdef HNDCTF ++//int32 ctf_init(void); ++void ctf_exit(void); ++ ++static void ++et_ctf_detach(ctf_t *ci, void *arg) ++{ ++ et_info_t *et = (et_info_t *)arg; ++ ++ et->cih = NULL; ++ ++#ifdef CTFPOOL ++ /* free the buffers in fast pool */ ++ osl_ctfpool_cleanup(et->osh); ++#endif /* CTFPOOL */ ++ ++ return; ++} ++#endif /* HNDCTF */ ++ ++static bool ++et_ctf_active(et_info_t *et) ++{ ++ bool retval=false; ++#if defined(CONFIG_IPROC_FA) ++ if (brcm_tag == true) { ++ if (et->etc->unit == 2) { ++ retval = true; ++ } ++ } ++#elif defined(CONFIG_MACH_NSP) ++ if (et->etc->unit == 2 || et->etc->unit == 3) { ++ retval = true; ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++ return retval; ++} ++ ++static bool ++et_ctf_pipeline_loopback(et_info_t *et) ++{ ++ if (et->etc->unit == 3) { ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++static int ++et_bcmtag_len(et_info_t *et) ++{ ++ if (et_ctf_pipeline_loopback(et)) ++ return 8; ++ if (et_ctf_active(et)) ++ return 4; ++ return 0; ++} ++ ++void *et_get_hndl(uint unit) ++{ ++ et_info_t *listptr; ++ void *roboptr; ++ ++ roboptr = NULL; ++ ++ for (listptr = et_list; listptr; listptr = listptr->next) { ++ if (listptr->etc->unit == unit) { ++ roboptr = listptr->etc->robo; ++ break; ++ } ++ } ++ ++ return roboptr; ++} ++ ++static void ++et_free(et_info_t *et) ++{ ++ et_info_t **prev; ++ osl_t *osh; ++ ++ if (et == NULL) ++ return; ++ ++ ET_TRACE(("et: et_free\n")); ++ ++ if (et->dev && et->dev->irq) ++ free_irq(et->dev->irq, et); ++ ++#ifdef NAPI2_POLL ++ napi_disable(&et->napi_poll); ++ netif_napi_del(&et->napi_poll); ++#endif /* NAPI2_POLL */ ++ ++#ifdef HNDCTF ++ if (et->cih) ++ ctf_dev_unregister(et->cih, et->dev); ++#endif /* HNDCTF */ ++ ++ if (et->dev) { ++ unregister_netdev(et->dev); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ free_netdev(et->dev); ++#else ++ MFREE(et->osh, et->dev, sizeof(struct net_device)); ++#endif ++ et->dev = NULL; ++ } ++ ++#ifdef CTFPOOL ++ /* free the buffers in fast pool */ ++ osl_ctfpool_cleanup(et->osh); ++#endif /* CTFPOOL */ ++ ++#ifdef HNDCTF ++ /* free ctf resources */ ++ if (et->cih) ++ ctf_detach(et->cih); ++#endif /* HNDCTF */ ++ ++ /* free common resources */ ++ if (et->etc) { ++ etc_detach(et->etc); ++ et->etc = NULL; ++ } ++ ++ /* ++ * unregister_netdev() calls get_stats() which may read chip registers ++ * so we cannot unmap the chip registers until after calling unregister_netdev() . ++ */ ++ if (et->regsva) { ++ iounmap((void *)et->regsva); ++ et->regsva = NULL; ++ } ++ ++ /* remove us from the global linked list */ ++ for (prev = &et_list; *prev; prev = &(*prev)->next) ++ if (*prev == et) { ++ *prev = et->next; ++ break; ++ } ++ ++ osh = et->osh; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ free_netdev(et->dev); ++ et->dev = NULL; ++#else ++ MFREE(et->osh, et, sizeof(et_info_t)); ++#endif ++ ++ if (MALLOCED(osh)) { ++ ET_ERROR(("Memory leak of bytes %d\n", MALLOCED(osh))); ++ } ++ ASSERT(MALLOCED(osh) == 0); ++ ++ osl_detach(osh); ++} ++ ++static int ++et_open(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_open\n", et->etc->unit)); ++ ++ et->etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; ++ et->etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: et->etc->promisc; ++#ifdef GMAC_RATE_LIMITING ++ et->etc->rl_enabled = et_rx_rate_limit; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ ET_LOCK(et); ++ et_up(et); ++ ET_UNLOCK(et); ++ ++ OLD_MOD_INC_USE_COUNT; ++ ++ return (0); ++} ++ ++static int ++et_close(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_close\n", et->etc->unit)); ++ ++ et->etc->promisc = FALSE; ++ et->etc->allmulti = FALSE; ++ ++ ET_LOCK(et); ++ et_down(et, 1); ++ ET_UNLOCK(et); ++ ++ OLD_MOD_DEC_USE_COUNT; ++ ++ return (0); ++} ++ ++#if defined(BCMDMASGLISTOSL) ++/* ++ * Driver level checksum offload. This is being done so that we can advertise ++ * checksum offload support to Linux. ++ */ ++static void BCMFASTPATH_HOST ++et_cso(et_info_t *et, struct sk_buff *skb) ++{ ++ struct ethervlan_header *evh; ++ uint8 *th = skb_transport_header(skb); ++ uint16 thoff, eth_type, *check; ++ uint8 prot; ++ ++ ASSERT(!PKTISCTF(et->osh, skb)); ++ ++ evh = (struct ethervlan_header *)PKTDATA(et->osh, skb); ++ eth_type = ((evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) ? ++ evh->ether_type : evh->vlan_type); ++ ++ /* tcp/udp checksum calculation */ ++ thoff = (th - skb->data); ++ if (eth_type == HTON16(ETHER_TYPE_IP)) { ++ struct iphdr *ih = ip_hdr(skb); ++ prot = ih->protocol; ++ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); ++ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? ++ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); ++ *check = 0; ++ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); ++ *check = csum_tcpudp_magic(ih->saddr, ih->daddr, ++ skb->len - thoff, prot, skb->csum); ++ } else if (eth_type == HTON16(ETHER_TYPE_IPV6)) { ++ struct ipv6hdr *ih = ipv6_hdr(skb); ++ prot = IPV6_PROT(ih); ++ ASSERT((prot == IP_PROT_TCP) || (prot == IP_PROT_UDP)); ++ check = (uint16 *)(th + ((prot == IP_PROT_UDP) ? ++ offsetof(struct udphdr, check) : offsetof(struct tcphdr, check))); ++ *check = 0; ++ skb->csum = skb_checksum(skb, thoff, skb->len - thoff, 0); ++ *check = csum_ipv6_magic(&ih->saddr, &ih->daddr, ++ skb->len - thoff, prot, skb->csum); ++ } else { ++ return; ++ } ++ ++ if ((*check == 0) && (prot == IP_PROT_UDP)) ++ *check = CSUM_MANGLED_0; ++} ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++#ifdef ET_ALL_PASSIVE ++/* Schedule a completion handler to run at safe time */ ++static int ++et_schedule_task(et_info_t *et, void (*fn)(struct et_task *task), void *context) ++{ ++ et_task_t *task; ++ ++ ET_TRACE(("et%d: et_schedule_task\n", et->etc->unit)); ++ ++ if (!(task = MALLOC(et->osh, sizeof(et_task_t)))) { ++ ET_ERROR(("et%d: et_schedule_task: out of memory, malloced %d bytes\n", ++ et->etc->unit, MALLOCED(et->osh))); ++ return -ENOMEM; ++ } ++ ++ MY_INIT_WORK(&task->work, (work_func_t)fn); ++ task->context = context; ++ ++ if (!schedule_work(&task->work)) { ++ ET_ERROR(("et%d: schedule_work() failed\n", et->etc->unit)); ++ MFREE(et->osh, task, sizeof(et_task_t)); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static void BCMFASTPATH ++et_txq_work(struct et_task *task) ++{ ++ et_info_t *et = (et_info_t *)task->context; ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_LOCK(et); ++#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ et_sendnext(et); ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_UNLOCK(et); ++#endif /* !CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ return; ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++#ifdef GMAC3 ++/* et_start counterpart (test performance of using a queue) */ ++static int BCMFASTPATH ++et_forward(struct sk_buff *skb, struct net_device *dev, int cnt) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++ void *p, *n; ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++ ++ et = ET_INFO(dev); ++ etc = et->etc; ++ ++ /* BUZZZ_DPL1(ET_FORWARD, 3, etc->unit, (uint32)skb, cnt); */ ++ ET_TRACE(("et%d: et_forward\n", etc->unit)); ++ ET_LOG("et%d: et_forward", etc->unit, 0); ++ ++ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); ++ ++ //p = PKTFRMFORWARD(etc->osh, skb, cnt); ++ p = PKTFRMNATIVE(etc->osh, skb); ++ ASSERT(p != NULL); ++ ++ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", ++ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) fwdpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ ++ /* ---------------------------------------- */ ++ /* ---------------------------------------- */ ++ ++ FOREACH_CHAINED_PKT(p, n) { ++ ++ PKTCLRCHAINED(et->osh, p); ++ if (n == NULL) ++ PKTCSETFLAG(p, 1); ++ (*etc->chops->tx)(etc->ch, p); ++ ++ etc->txframe++; ++ etc->txbyte += PKTLEN(et->osh, p); ++ } ++ /* BUZZZ_DPL2(ET_FORWARD_RTN, 0); */ ++ ++ return FWDER_SUCCESS; ++} ++#endif /* GMAC3 */ ++ ++ ++#if defined(BCMDMASGLISTOSL) ++/* ++ * Convert a non leaner packet to a linear packet ++ */ ++static int BCMFASTPATH ++et_convert2linear_skb(struct sk_buff *skb, et_info_t *et) ++{ ++ int copy_len, z; ++ unsigned char my_buff[100]; ++ unsigned char *to_buffer; ++ ++ if (skb_is_nonlinear(skb)) { ++ ++ copy_len = skb->data_len; ++ skb_header_pointer(skb, skb_headlen(skb), ++ skb->data_len, (void*)my_buff); ++ ++ /* Trim packet to only header, should make linear */ ++ if (__pskb_trim(skb, skb_headlen(skb))) { ++ ET_ERROR(("et%d: __pskb_trim() error\n", et->etc->unit)); ++ return -1; ++ } ++ ++ if (skb_is_nonlinear(skb)) { ++ ET_ERROR(("et%d: skb_is_nonlinear() error\n", et->etc->unit)); ++ return -1; ++ } else { ++ to_buffer = skb_put(skb, copy_len); ++ ++ for (z=0; z < copy_len; z++) { ++ to_buffer[z] = my_buff[z]; ++ } ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Calculate checksum ++ */ ++static int BCMFASTPATH ++et_linear_skb_cksum(struct sk_buff *skb, et_info_t *et, int brcmtag) ++{ ++ int ret; ++ void *usr_data; ++ int ip_hdr_len, ip_tot_len, tcp_hdr_len, udp_hdr_len, usr_data_len; ++ struct iphdr *iph = NULL; ++ int save_len; ++ int offset; ++ int brcm_tag_len, hdr_len, vlan_tag_len; ++ struct ethervlan_header *evh; ++ ++ brcm_tag_len=0; ++ if (brcmtag) { ++ brcm_tag_len = et_bcmtag_len(et); ++ } ++ evh = (struct ethervlan_header *)(skb->data+brcm_tag_len); ++ ++ iph = (struct iphdr *)skb->network_header; ++ ip_hdr_len = ip_hdr(skb)->ihl << 2; ++ ip_tot_len = ntohs(ip_hdr(skb)->tot_len); ++ tcp_hdr_len = tcp_hdr(skb)->doff << 2; ++ udp_hdr_len = 8; ++ vlan_tag_len = 0; ++ if (evh->vlan_type == HTON16(ETHER_TYPE_8021Q)) { ++ /* add in vlan tags */ ++ vlan_tag_len = 4; ++ } ++ ++ /* Generate IPv4 checksum */ ++ ret = skb_checksum_help(skb); ++ ++ // printk(" ip done: skb len=%d ip_checksum=%x ret=%x (csum=%x tcp_checksum=%x)\n", ++ // skb->len, iph->check, ret, skb->csum, tcp_hdr(skb)->check); ++ ++ /* mark checksum mode */ ++ /* - clear partial checksum */ ++ skb->ip_summed = CHECKSUM_NONE; ++ skb->csum = 0; ++ ++ hdr_len=0; ++ /* build csum for user data */ ++ if (iph->protocol == IPPROTO_TCP) { ++ usr_data = skb->network_header + ip_hdr_len + tcp_hdr_len; ++ usr_data_len = ip_tot_len - ip_hdr_len - tcp_hdr_len; ++ hdr_len = 20; ++ } else { ++ usr_data = skb->network_header + ip_hdr_len + udp_hdr_len; ++ usr_data_len = ip_tot_len - ip_hdr_len - udp_hdr_len; ++ hdr_len = 8; ++ } ++ ++ /* offset = 12-mac, 2-etype, 20-ip, x-bcm, (20-tcp or 8-udp), [4-vlan] */ ++ offset = 34 + brcm_tag_len + hdr_len + vlan_tag_len; ++ if (usr_data != ((skb->data)+offset)) { ++ printk("et%d: FIXME usr_data not expected %p vs %p\n", ++ et->etc->unit, skb->data+offset, usr_data); ++ } ++ ++ skb->csum = csum_partial(usr_data, usr_data_len, 0); ++ // printk(" csum prep: skb_data at %x=%x, skb_csum=%x \n", ++ // (skb->data + 58), *(skb->data + 58), skb->csum); ++ ++ /* save skb length */ ++ save_len = skb->len; ++ ++ /* adjust skb->len to inlcude TCP header and user data */ ++ /* - use ip_hdr.tot_len - ip_hdr_len */ ++ skb->len = ip_tot_len - ip_hdr_len; ++ ++ /* offset = 12-mac, 2-etype, 20-ip, x-bcm, [4-vlan] */ ++ offset = 34 + brcm_tag_len + vlan_tag_len; ++ if (skb->len != save_len-offset) { ++ printk("et%d: FIXME sdk_len not expected %d vs %d\n", ++ et->etc->unit, skb->len, save_len-offset); ++ } ++ ++ // printk(" tcp prep: socket=%x inet=%x \n", skb->sk, inet_sk(skb->sk)); ++ ++ if (iph->protocol == IPPROTO_TCP) { ++ /* Generate TCP checksum */ ++ tcp_hdr(skb)->check = 0; ++ tcp_v4_send_check(skb->sk, skb); ++ } else { ++ /* udp checksum optional */ ++ udp_hdr(skb)->check = 0; ++ } ++ ++ /* restore skb length */ ++ skb->len = save_len; ++ ++ // printk(" tcp done: checksum=%x\n", tcp_hdr(skb)->check); ++ ++ return 0; ++} ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ ++/* ++ * Yeah, queueing the packets on a tx queue instead of throwing them ++ * directly into the descriptor ring in the case of dma is kinda lame, ++ * but this results in a unified transmit path for both dma and pio ++ * and localizes/simplifies the netif_*_queue semantics, too. ++ */ ++static int BCMFASTPATH ++et_start(struct sk_buff *skb, struct net_device *dev) ++{ ++ et_info_t *et; ++ uint32 q = 0; ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ int less68 = 0; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++#if (defined(CONFIG_IPROC_FA2_NAPT_BYPASS) || defined(BCMDMASGLISTOSL)) ++ struct iphdr *iph = NULL; ++#endif /* (defined(CONFIG_IPROC_FA2_NAPT_BYPASS) || defined(BCMDMASGLISTOSL)) */ ++#ifdef ET_LIMIT_TXQ ++ int qlen; ++#endif /* ET_LIMIT_TXQ */ ++ ++ et = ET_INFO(dev); ++ ++#if defined(BCMDMASGLISTOSL) ++ { ++ bool sw_cksum=true; ++ ++ if (!PKTSUMNEEDED(skb)) ++ sw_cksum=false; ++ ++ #if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++ if (et->etc->unit == 2) ++ sw_cksum=false; ++ #endif /* (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) */ ++ ++ #if !defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ /* can only update checksum once. */ ++ /* if checksum is updated later, don't do it here */ ++ iph = (struct iphdr *)skb->network_header; ++ if (((skb->len+et_bcmtag_len(et)) < MIN_PACKET_SIZE) && ++ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ sw_cksum=false; ++ } ++ #endif /* !defined(CONFIG_IPROC_FA2_CS_OFFLOAD) */ ++ ++ if (sw_cksum) { ++ et_cso(et, skb); ++ } ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ if (skb_is_nonlinear(skb)) ++ et->etc->txsgpkt++; ++ ++ if (skb->len > et->etc->txmaxlen) { ++ et->etc->txmaxlen = skb->len; ++ } ++ ++#if defined(CONFIG_MACH_NS) ++ if (ET_GMAC(et->etc) && (et->etc->qos)) ++ q = etc_up2tc(PKTPRIO(skb)); ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ET_TRACE(("et%d: et_start: len %d\n", et->etc->unit, skb->len)); ++ ET_LOG("et%d: et_start: len %d", et->etc->unit, skb->len); ++ ++ et->etc->txfrm++; ++#ifdef ET_LIMIT_TXQ ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_TXQ_LOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ qlen = skb_queue_len(&et->txq[q]); ++#ifndef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_TXQ_UNLOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ if (qlen > et->etc->txqlen) ++ et->etc->txqlen = qlen; ++ if (et_txq_thresh && (qlen >= et_txq_thresh)) { ++ //PKTCFREE(et->osh, skb, TRUE); ++ //return 0; ++ et->etc->txfrmdropped++; ++ /* schedule work */ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++#else ++ schedule_work(&et->txq_task.work); ++#endif ++ } ++#endif /* ET_ALL_PASSIVE */ ++ return NETDEV_TX_BUSY; ++ } ++#endif /* ET_LIMIT_TXQ */ ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) ++ ++ if (et_ctf_pipeline_loopback(et)) { ++ int bcm_hdr_size = 8; /* type 3 */ ++ ++ /* add brcm tag; tag is locate at offset 0-3 */ ++ ET_TRACE(("et%d %s: headroom(0x%x)\n", et->etc->unit, __FUNCTION__, skb_headroom(skb))); ++ ET_TRACE(("et%d: NOT enough headroom for BRCM tag.\n", et->etc->unit)); ++ if (skb_headroom(skb) < bcm_hdr_size) { ++ struct sk_buff *sk_tmp = skb; ++ skb = skb_realloc_headroom(sk_tmp, bcm_hdr_size); ++ PKTCFREE(et->osh, sk_tmp, TRUE); ++ if (!skb) { ++ ET_ERROR(("et%d: Failed to realloc headroom for BRCM tag; NOT transmitting frame.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ET_TRACE(("Adding BRCM TAG\n")); ++ __skb_push(skb, bcm_hdr_size); ++ ++ /* insert egress hdr type 3*/ ++ skb->data[0] = 0x60; /* opcode b011 */ ++ skb->data[1] = 0x00; ++ skb->data[2] = 0x00; ++ skb->data[3] = 0x00; ++ skb->data[4] = 0x00; ++ skb->data[5] = 0x00; ++ skb->data[6] = 0x00; ++ skb->data[7] = 0x28; /* fwd to AXI1, proc by SPU */ ++ ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ET_TRACE(("forcing skb->len (%d) to %d\n", skb->len, MIN_PACKET_SIZE)); ++ skb->len = MIN_PACKET_SIZE; ++ } ++ __pskb_trim(skb, skb->len); ++ ++ } else if (et_ctf_active(et)) { ++ int bcm_hdr_size = 4; ++ ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ bcm_hdr_size = 8; ++#endif ++ /* add brcm tag; tag is located at offset 0-3 */ ++ ET_TRACE(("et%d %s: headroom(0x%x)\n", et->etc->unit, __FUNCTION__, skb_headroom(skb))); ++ if (skb_headroom(skb) < bcm_hdr_size) { ++ struct sk_buff *sk_tmp = skb; ++ ++ ET_TRACE(("et%d: NOT enough headroom for BRCM tag.\n", et->etc->unit)); ++ skb = skb_realloc_headroom(sk_tmp, bcm_hdr_size); ++ PKTCFREE(et->osh, sk_tmp, TRUE); ++ if (!skb) { ++ ET_ERROR(("et%d: Failed to realloc headroom for BRCM tag; NOT transmitting frame.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ET_TRACE(("Adding BRCM TAG\n")); ++ __skb_push(skb, 4); ++ ++ /* insert ingress hdr type 0*/ ++ skb->data[0] = 0x00; ++ skb->data[1] = 0x00; ++ skb->data[2] = 0x00; ++ skb->data[3] = 0x00; ++ ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD) && \ ++ defined(CONFIG_IPROC_FA2_CS_OFFLOAD_SMALL_PKT_WA)) ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ int ret; ++ ret = skb_checksum_help(skb); ++ if (ret) { ++ ET_ERROR(("et%d: skb_checksum_help() returned error %d\n", et->etc->unit, ret)); ++ } ++ } ++ } ++#endif ++ ++#if defined(BCMDMASGLISTOSL) ++ iph = (struct iphdr *)skb->network_header; ++ if ((skb->len < MIN_PACKET_SIZE) && ++ ((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ /* convert nonlinear SKB to linear */ ++ et_convert2linear_skb(skb, et); ++ if (skb->sk) { ++ /* if socket - calculate checksum */ ++ et_linear_skb_cksum(skb, et, 1); ++ } ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ if (skb->len < MIN_PACKET_SIZE) { ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ less68 = 1; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ET_TRACE(("forcing skb->len (%d) to %d\n", skb->len, MIN_PACKET_SIZE)); ++ skb->len = MIN_PACKET_SIZE; ++ } ++ __pskb_trim(skb, skb->len); ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++ iph = (struct iphdr *)skb->network_header; ++ if (!less68 &&((iph->protocol == IPPROTO_TCP) || (iph->protocol == IPPROTO_UDP))) { ++ fa2_modify_header(skb); ++ /* Send pkt to AXI1 */ ++ et = et_get_eth3_info(); ++ if (!et->etc->up) { ++ ET_ERROR(("et%d: eth3 not up, exit.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ goto send_packet; ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ++#if defined(CONFIG_IPROC_FA) ++ if(!gBypass) { ++ fc_transmit(skb); ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++#if defined(CONFIG_IPROC_FA2) ++ if(!gBypass) { ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++ struct fa2_pkt_info pkt_info; ++ extern spinlock_t fa2_lock; ++ uint8_t p_op; ++ ++ //memset((void *)&pkt_info, 0x0, sizeof(pkt_info)); ++ /* Initialize pkt_info */ ++ pkt_info.mac = pkt_info.ipv4_or_ipv6 = pkt_info.tcp_or_udp = NULL; ++ ++ pkt_info.vlan_tag = pkt_info.vlan_tag_next = pkt_info.et_type = ++ pkt_info.eth_snapllc = pkt_info.need_hdr_bytes = ++ pkt_info.hdr_words[0] = pkt_info.hdr_words[1] = 0; ++ ++ pkt_info.proto = FA2_PROTO_NOT_SUPPORTED; ++ pkt_info.pkt_type = FA2_INVALID_PKT; ++ ++ spin_lock(&fa2_lock); ++ fa2_get_packet_info(skb, &pkt_info); ++ spin_unlock(&fa2_lock); ++ ++ /* Check if this packet can be processed by FA+ pipeline. ++ * If not, let the eth driver handle it. ++ * If yes, do fa+ processing ++ */ ++ if (pkt_info.proto != FA2_PROTO_NOT_SUPPORTED) { ++ if (pkt_info.pkt_type != FA2_FWD_PKT) { ++ ++ p_op = pkt_info.hdr_words[1] & FA2_BCMHDR_OP_3_PROC_OP; ++ ++ /* Check for proc_ops 0, 1, 2 and 5 */ ++ if ((p_op <= 0x2) || (p_op == 0x5)) { ++ ++ fa2_transmit(skb, &pkt_info); ++ } ++ } else { ++ fa2_transmit(skb, &pkt_info); ++ } ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD_SMALL_PKT_WA) ++ if (pkt_info.pkt_type == FA2_LOCAL_SMALL_TX_PKT) { ++ fa2_transmit(skb, &pkt_info); ++ } ++#endif ++ } ++ ++ /* If the packet is a L4 packet, and it is _not_ a forwarded packet, ++ * then add bcm hdr 0x3 bytes ++ */ ++ if ((pkt_info.proto != FA2_PROTO_NOT_SUPPORTED) && ++ (pkt_info.pkt_type == FA2_LOCAL_TX_PKT)) { ++ ++ /* Add Broadcom header bytes (8 bytes). Note 4 bytes were ++ * 'push'ed earlier ++ */ ++ __skb_push(skb, 4); ++ *((uint32_t *)skb->data) = htonl(pkt_info.hdr_words[0]); ++ *((uint32_t *)skb->data + 1) = htonl(pkt_info.hdr_words[1]); ++ __pskb_trim(skb, skb->len); ++ ++ /* Send pkt to AXI1 */ ++ et = et_get_eth3_info(); ++ if (!et->etc->up) { ++ ET_ERROR(("et%d: eth3 not up, exit.\n", et->etc->unit)); ++ return 0; ++ } ++ } ++ ++ ++#else ++ fa2_transmit(skb, NULL); ++#endif ++ } ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ } ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) */ ++ ++#ifdef CONFIG_IPROC_FA2_NAPT_BYPASS ++send_packet: ++#endif /* CONFIG_IPROC_FA2_NAPT_BYPASS */ ++ ++ /* put it on the tx queue and call sendnext */ ++ ET_TXQ_LOCK(et); ++ __skb_queue_tail(&et->txq[q], skb); ++ et->etc->txq_state |= (1 << q); ++ ET_TXQ_UNLOCK(et); ++ ++ if (!ET_ALL_PASSIVE_ENAB(et)) { ++ ET_LOCK(et); ++ et_sendnext(et); ++ ET_UNLOCK(et); ++ } ++#ifdef ET_ALL_PASSIVE ++ else ++#ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++#else ++ schedule_work(&et->txq_task.work); ++#endif ++ ++#endif /* ET_ALL_PASSIVE */ ++ ++ ET_LOG("et%d: et_start ret\n", et->etc->unit, 0); ++ ++ return (0); ++} ++ ++static void BCMFASTPATH ++et_sendnext(et_info_t *et) ++{ ++ etc_info_t *etc; ++ struct sk_buff *skb; ++ void *p, *n; ++ uint32 priq = TX_Q0; ++#ifdef DMA ++ uint32 txavail; ++#endif ++#ifdef PRINT_PKT_SUM ++ int tagoff=12; ++#endif /* PRINT_PKT_SUM */ ++ ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++ ++ etc = et->etc; ++ ++ ET_TRACE(("et%d: et_sendnext\n", etc->unit)); ++ ET_LOG("et%d: et_sendnext", etc->unit, 0); ++ ++ /* dequeue packets from highest priority queue and send */ ++ while (1) { ++ ET_TXQ_LOCK(et); ++ ++ if (etc->txq_state == 0) ++ break; ++ ++ priq = etc_priq(etc->txq_state); ++ ++ ET_TRACE(("et%d: txq_state %x priq %d txavail %d\n", ++ etc->unit, etc->txq_state, priq, ++ *(uint *)etc->txavail[priq])); ++ ++ if ((skb = skb_peek(&et->txq[priq])) == NULL) { ++ etc->txq_state &= ~(1 << priq); ++ ET_TXQ_UNLOCK(et); ++ continue; ++ } ++ ++#ifdef DMA ++ /* current highest priority dma queue is full */ ++ txavail = *(uint *)(etc->txavail[priq]); ++ if ((PKTISCHAINED(skb) && (txavail < PKTCCNT(skb))) || (txavail == 0)) ++#else /* DMA */ ++ if (etc->pioactive != NULL) ++#endif /* DMA */ ++ { ++ etc->txdmafull++; ++ break; ++ } ++ ++ skb = __skb_dequeue(&et->txq[priq]); ++ ++ ET_TXQ_UNLOCK(et); ++ ET_PRHDR("tx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("txpkt", skb->data, skb->len, etc->unit); ++ ++#ifdef PRINT_PKT_SUM ++ tagoff = 16; ++ printf("et%d: txpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, ++ skb->data[tagoff], skb->data[tagoff+1], skb->data[tagoff+2], skb->data[tagoff+3]); ++#endif /* PRINT_PKT_SUM */ ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) txpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ /* convert the packet. */ ++ p = PKTFRMNATIVE(etc->osh, skb); ++ ASSERT(p != NULL); ++ ++ ET_TRACE(("%s: sdu %p chained %d chain sz %d next %p\n", ++ __FUNCTION__, p, PKTISCHAINED(p), PKTCCNT(p), PKTCLINK(p))); ++ ++ ET_TX_LOCK(et); ++ FOREACH_CHAINED_PKT(p, n) { ++ /* replicate vlan header contents from curr frame */ ++ if (n != NULL) { ++ uint8 *n_evh; ++ n_evh = PKTPUSH(et->osh, n, VLAN_TAG_LEN); ++ *(struct ethervlan_header *)n_evh = ++ *(struct ethervlan_header *)PKTDATA(et->osh, p); ++ } ++ (*etc->chops->tx)(etc->ch, p); ++#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_LOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ etc->txframe++; ++ etc->txbyte += PKTLEN(et->osh, p); ++#ifdef CONFIG_BCM_IPROC_GMAC_LOCK_OPT ++ ET_UNLOCK(et); ++#endif /* CONFIG_BCM_IPROC_GMAC_LOCK_OPT */ ++ } ++ ET_TX_UNLOCK(et); ++ } ++ ++ /* no flow control when qos is enabled */ ++ if (!et->etc->qos) { ++ /* stop the queue whenever txq fills */ ++ if ((skb_queue_len(&et->txq[TX_Q0]) > DATAHIWAT) && !netif_queue_stopped(et->dev)) { ++ et->etc->txqstop++; ++ netif_stop_queue(et->dev); ++ } ++ else if (netif_queue_stopped(et->dev) && ++ (skb_queue_len(&et->txq[TX_Q0]) < (DATAHIWAT/2))) { ++ netif_wake_queue(et->dev); ++ } ++ } else { ++ /* drop the frame if corresponding prec txq len exceeds hiwat ++ * when qos is enabled. ++ */ ++ if ((priq != TC_NONE) && (skb_queue_len(&et->txq[priq]) > DATAHIWAT)) { ++ skb = __skb_dequeue(&et->txq[priq]); ++ PKTCFREE(et->osh, skb, TRUE); ++ ET_ERROR(("et%d: %s: txqlen %d\n", et->etc->unit, ++ __FUNCTION__, skb_queue_len(&et->txq[priq]))); ++ } ++ } ++ ++ ET_TXQ_UNLOCK(et); ++} ++ ++void ++et_init(et_info_t *et, uint options) ++{ ++ ET_TRACE(("et%d: et_init\n", et->etc->unit)); ++ ET_LOG("et%d: et_init", et->etc->unit, 0); ++ ++ etc_init(et->etc, options); ++} ++ ++ ++void ++et_reset(et_info_t *et) ++{ ++ ET_TRACE(("et%d: et_reset\n", et->etc->unit)); ++ ++ etc_reset(et->etc); ++ ++ /* zap any pending dpc interrupt bits */ ++ et->events = 0; ++ ++ /* dpc will not be rescheduled */ ++ et->resched = 0; ++} ++ ++void ++et_up(et_info_t *et) ++{ ++ etc_info_t *etc; ++ ++ etc = et->etc; ++ ++ if (etc->up) ++ return; ++ ++ ET_TRACE(("et%d: et_up\n", etc->unit)); ++ ++ etc_up(etc); ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (et->set) { ++ /* This will happen if running watchdog to monitor mdio bus */ ++ /* and port not up */ ++ del_timer(&et->timer); ++ et->set = FALSE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++ /* schedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set=TRUE; ++ ++ netif_start_queue(et->dev); ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ et->etc->pktc = TRUE; ++ ++ /* ++ * Attach my transmit handler to UPSTREAM fwder instance on core=unit ++ * wl# MAC -> wl_sendup -> et_forward -> et::GMAC# ++ * and get the DNSTREAM direction transmit handler for use in sendup. ++ * et_sendup/chain -> et->fwdh->start_xmit=wl_start -> wl# MAC ++ */ ++ et->fwdh = fwder_attach(et_forward, et->dev, et->etc->unit, FWD_UPSTREAM); ++ /* fwder_dump_all(); */ ++ } ++#endif /* GMAC3 */ ++} ++ ++void ++et_down(et_info_t *et, int reset) ++{ ++ etc_info_t *etc; ++ struct sk_buff *skb; ++ int32 i; ++ bool stoptmr = TRUE; ++ ++ etc = et->etc; ++ ++ ET_TRACE(("et%d: et_down\n", etc->unit)); ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ et->fwdh = fwder_dettach(et->fwdh); ++ /* fwder_dump_all(); */ ++ } ++#endif /* GMAC3 */ ++ ++ netif_down(et->dev); ++ netif_stop_queue(et->dev); ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (gmac_has_mdio_access()) { ++ /* we have mdio bus don't stop timer so we can continue to monitor */ ++ stoptmr = FALSE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++ if ( stoptmr ) { ++ /* stop watchdog timer */ ++ del_timer(&et->timer); ++ et->set = FALSE; ++ } ++ ++#ifdef GMAC_RATE_LIMITING ++ /* stop ratelimiting timer */ ++ del_timer(&et->etc->rl_timer); ++ et->etc->rl_set = FALSE; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ etc_down(etc, reset); ++ ++ /* flush the txq(s) */ ++ for (i = 0; i < NUMTXQ; i++) ++ while ((skb = skb_dequeue(&et->txq[i]))) ++ PKTFREE(etc->osh, skb, TRUE); ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ /* kill dpc */ ++ ET_UNLOCK(et); ++ tasklet_kill(&et->tasklet); ++ ET_LOCK(et); ++#endif /* NAPI_POLL */ ++} ++ ++/* ++ * These are interrupt on/off entry points. Disable interrupts ++ * during interrupt state transition. ++ */ ++void ++et_intrson(et_info_t *et) ++{ ++ unsigned long flags; ++ INT_LOCK(et, flags); ++ (*et->etc->chops->intrson)(et->etc->ch); ++ INT_UNLOCK(et, flags); ++} ++ ++static void ++_et_watchdog(struct net_device *dev) ++{ ++ et_info_t *et; ++ ++ et = ET_INFO(dev); ++ ++ ET_LOCK(et); ++ ++ etc_watchdog(et->etc); ++ ++ if (et->set) { ++ /* reschedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ } ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ /* this in case port when up then down before we released mdio */ ++ else if (gmac_has_mdio_access()) { ++ /* interface not up but we have mdio bus */ ++ /* reschedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set = TRUE; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++#ifdef CTFPOOL ++ /* allocate and add a new skb to the pkt pool */ ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ if (CTF_ENAB(et->cih)) ++#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ osl_ctfpool_replenish(et->osh, CTFPOOL_REFILL_THRESH); ++#endif /* CTFPOOL */ ++ ET_UNLOCK(et); ++} ++ ++#ifdef ET_ALL_PASSIVE ++static void ++et_watchdog_task(et_task_t *task) ++{ ++ et_info_t *et = ET_INFO((struct net_device *)task->context); ++ ++ _et_watchdog((struct net_device *)task->context); ++ MFREE(et->osh, task, sizeof(et_task_t)); ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++static void ++et_watchdog(ulong data) ++{ ++ struct net_device *dev = (struct net_device *)data; ++#ifdef ET_ALL_PASSIVE ++ et_info_t *et = ET_INFO(dev); ++#endif /* ET_ALL_PASSIVE */ ++ ++ if (!ET_ALL_PASSIVE_ENAB(et)) ++ _et_watchdog(dev); ++#ifdef ET_ALL_PASSIVE ++ else ++ et_schedule_task(et, et_watchdog_task, dev); ++#endif /* ET_ALL_PASSIVE */ ++} ++ ++/* Rate limiting */ ++#ifdef GMAC_RATE_LIMITING ++static void et_release_congestion(ulong data) ++{ ++ struct net_device *dev = (struct net_device *)data; ++ et_info_t *et = ET_INFO(dev); ++ ++ if (!et) { ++ return; ++ } ++ if (et->etc->rl_stopping_broadcasts) { ++ //printf("et%d: %s: releasing broadcast packet congestion; dropped: 0x%x\n", et->etc->unit, __FUNCTION__, et->etc->rl_dropped_bc_packets); ++ et->etc->rl_stopping_broadcasts = 0; ++ /* clear the number of dropped broadcast packets */ ++ et->etc->rl_dropped_bc_packets = 0; ++ } ++ if (et->etc->rl_stopping_all_packets) { ++ //printf("et%d: %s: releasing all packet congestion; dropped: 0x%x\n", et->etc->unit, __FUNCTION__, et->etc->rl_dropped_all_packets); ++ et->etc->rl_stopping_all_packets = 0; ++ et->etc->rl_dropped_all_packets = 0; ++ } ++} ++#endif /* GMAC_RATE_LIMITING */ ++ ++ ++ ++static int ++et_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ++{ ++ et_info_t *et = ET_INFO(dev); ++ ++ ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | ++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | ++ SUPPORTED_Autoneg | SUPPORTED_TP); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ ecmd->supported |= SUPPORTED_1000baseT_Full | SUPPORTED_Pause; ++#endif ++#if defined(CONFIG_MACH_HR2) ++ ecmd->supported |= SUPPORTED_Pause; ++#endif ++ ++ ecmd->advertising = ADVERTISED_TP; ++ ecmd->advertising |= (et->etc->advertise & ADV_10HALF) ? ++ ADVERTISED_10baseT_Half : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_10FULL) ? ++ ADVERTISED_10baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_100HALF) ? ++ ADVERTISED_100baseT_Half : 0; ++ ecmd->advertising |= (et->etc->advertise & ADV_100FULL) ? ++ ADVERTISED_100baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise2 & ADV_1000FULL) ? ++ ADVERTISED_1000baseT_Full : 0; ++ ecmd->advertising |= (et->etc->advertise2 & ADV_1000HALF) ? ++ ADVERTISED_1000baseT_Half : 0; ++ ecmd->advertising |= (et->etc->forcespeed == ET_AUTO) ? ++ ADVERTISED_Autoneg : 0; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_HR2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ ecmd->advertising |= ADVERTISED_Pause; ++#endif ++ if (et->etc->linkstate) { ++ ecmd->speed = (et->etc->speed == 1000) ? SPEED_1000 : ++ ((et->etc->speed == 100) ? SPEED_100 : SPEED_10); ++ ecmd->duplex = (et->etc->duplex == 1) ? DUPLEX_FULL : DUPLEX_HALF; ++ } else { ++ ecmd->speed = 0; ++ ecmd->duplex = 0; ++ } ++ ecmd->port = PORT_TP; ++ ecmd->phy_address = et->etc->phyaddr; ++ ecmd->transceiver = XCVR_INTERNAL; ++ ecmd->autoneg = (et->etc->forcespeed == ET_AUTO) ? AUTONEG_ENABLE : AUTONEG_DISABLE; ++ ecmd->maxtxpkt = 0; ++ ecmd->maxrxpkt = 0; ++ ++ return 0; ++} ++ ++static int ++et_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ++{ ++ int speed[2]; ++ ++ et_info_t *et = ET_INFO(dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return (-EPERM); ++ ++ if (ecmd->autoneg == AUTONEG_ENABLE) { ++ speed[0] = ET_AUTO; ++ speed[1] = ecmd->advertising; ++ } else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) ++ speed[0] = ET_10HALF; ++ else if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_10FULL; ++ else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) ++ speed[0] = ET_100HALF; ++ else if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_100FULL; ++ else if (ecmd->speed == SPEED_1000 && ecmd->duplex == DUPLEX_FULL) ++ speed[0] = ET_1000FULL; ++ else ++ return (-EINVAL); ++ ++ return etc_ioctl(et->etc, ETCSPEED, speed); ++} ++ ++static void ++et_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info) ++{ ++ et_info_t *et = ET_INFO(dev); ++ bzero(info, sizeof(struct ethtool_drvinfo)); ++ info->cmd = ETHTOOL_GDRVINFO; ++ sprintf(info->driver, "et%d", et->etc->unit); ++ strncpy(info->version, EPI_VERSION_STR, sizeof(info->version)); ++ info->version[(sizeof(info->version))-1] = '\0'; ++} ++ ++#ifdef SIOCETHTOOL ++static int ++et_ethtool(et_info_t *et, struct ethtool_cmd *ecmd) ++{ ++ int ret = 0; ++ ++ ET_LOCK(et); ++ ++ switch (ecmd->cmd) { ++ case ETHTOOL_GSET: ++ ret = et_get_settings(et->dev, ecmd); ++ break; ++ case ETHTOOL_SSET: ++ ret = et_set_settings(et->dev, ecmd); ++ break; ++ case ETHTOOL_GDRVINFO: ++ et_get_driver_info(et->dev, (struct ethtool_drvinfo *)ecmd); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ ET_UNLOCK(et); ++ ++ return (ret); ++} ++#endif /* SIOCETHTOOL */ ++ ++static int ++et_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ et_info_t *et; ++ int error; ++ char *buf; ++ int size, ethtoolcmd; ++ bool get = 0, set; ++ et_var_t *var = NULL; ++ void *buffer = NULL; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_ioctl: cmd 0x%x\n", et->etc->unit, cmd)); ++ ++ switch (cmd) { ++#ifdef SIOCETHTOOL ++ case SIOCETHTOOL: ++ if (copy_from_user(ðtoolcmd, ifr->ifr_data, sizeof(uint32))) ++ return (-EFAULT); ++ ++ if (ethtoolcmd == ETHTOOL_GDRVINFO) ++ size = sizeof(struct ethtool_drvinfo); ++ else ++ size = sizeof(struct ethtool_cmd); ++ get = TRUE; set = TRUE; ++ break; ++#endif /* SIOCETHTOOL */ ++ case SIOCGETCDUMP: ++ size = IOCBUFSZ; ++ get = TRUE; set = FALSE; ++ break; ++ case SIOCGETCPHYRD: ++ case SIOCGETCPHYRD2: ++ case SIOCGETCROBORD: ++ size = sizeof(int) * 2; ++ get = TRUE; set = TRUE; ++ break; ++ case SIOCSETCSPEED: ++ case SIOCSETCPHYWR: ++ case SIOCSETCPHYWR2: ++ case SIOCSETCROBOWR: ++ size = sizeof(int) * 2; ++ get = FALSE; set = TRUE; ++ break; ++ case SIOCSETGETVAR: ++ size = sizeof(et_var_t); ++ set = TRUE; ++ break; ++ default: ++ size = sizeof(int); ++ get = FALSE; set = TRUE; ++ break; ++ } ++ ++ if ((buf = MALLOC(et->osh, size)) == NULL) { ++ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", MALLOCED(et->osh))); ++ return (-ENOMEM); ++ } ++ ++ if (set && copy_from_user(buf, ifr->ifr_data, size)) { ++ MFREE(et->osh, buf, size); ++ return (-EFAULT); ++ } ++ ++ if (cmd == SIOCSETGETVAR) { ++ var = (et_var_t *)buf; ++ if (var->buf) { ++ if (!var->set) ++ get = TRUE; ++ ++ if (!(buffer = (void *) MALLOC(et->osh, var->len))) { ++ ET_ERROR(("et: et_ioctl: out of memory, malloced %d bytes\n", ++ MALLOCED(et->osh))); ++ MFREE(et->osh, buf, size); ++ return (-ENOMEM); ++ } ++ ++ if (copy_from_user(buffer, var->buf, var->len)) { ++ MFREE(et->osh, buffer, var->len); ++ MFREE(et->osh, buf, size); ++ return (-EFAULT); ++ } ++ } ++ } ++ ++ switch (cmd) { ++#ifdef SIOCETHTOOL ++ case SIOCETHTOOL: ++ error = et_ethtool(et, (struct ethtool_cmd *)buf); ++ break; ++#endif /* SIOCETHTOOL */ ++ case SIOCSETGETVAR: ++ ET_LOCK(et); ++ error = etc_iovar(et->etc, var->cmd, var->set, buffer); ++ ET_UNLOCK(et); ++ if (!error && get) ++ error = copy_to_user(var->buf, buffer, var->len); ++ ++ if (buffer) ++ MFREE(et->osh, buffer, var->len); ++ break; ++ default: ++ ET_LOCK(et); ++ error = etc_ioctl(et->etc, cmd - SIOCSETCUP, buf) ? -EINVAL : 0; ++ ET_UNLOCK(et); ++ break; ++ } ++ ++ if (!error && get) ++ error = copy_to_user(ifr->ifr_data, buf, size); ++ ++ MFREE(et->osh, buf, size); ++ ++ return (error); ++} ++ ++static struct net_device_stats * ++et_get_stats(struct net_device *dev) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++ struct net_device_stats *stats; ++ int locked = 0; ++ ++ et = ET_INFO(dev); ++ ++ ET_TRACE(("et%d: et_get_stats\n", et->etc->unit)); ++ ++ if (!in_atomic()) { ++ locked = 1; ++ ET_LOCK(et); ++ } ++ ++ etc = et->etc; ++ stats = &et->stats; ++ bzero(stats, sizeof(struct net_device_stats)); ++ ++ /* refresh stats */ ++ if (et->etc->up) ++ (*etc->chops->statsupd)(etc->ch); ++ ++ /* SWAG */ ++ stats->rx_packets = etc->rxframe; ++ stats->tx_packets = etc->txframe; ++ stats->rx_bytes = etc->rxbyte; ++ stats->tx_bytes = etc->txbyte; ++ stats->rx_errors = etc->rxerror; ++ stats->tx_errors = etc->txerror; ++ ++ if (ET_GMAC(etc)) { ++ gmacmib_t *mib; ++ ++ mib = etc->mib; ++ stats->collisions = mib->tx_total_cols; ++ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); ++ stats->rx_crc_errors = mib->rx_crc_errs; ++ stats->rx_frame_errors = mib->rx_align_errs; ++ stats->rx_missed_errors = mib->rx_missed_pkts; ++ } else { ++ bcmenetmib_t *mib; ++ ++ mib = etc->mib; ++ stats->collisions = mib->tx_total_cols; ++ stats->rx_length_errors = (mib->rx_oversize_pkts + mib->rx_undersize); ++ stats->rx_crc_errors = mib->rx_crc_errs; ++ stats->rx_frame_errors = mib->rx_align_errs; ++ stats->rx_missed_errors = mib->rx_missed_pkts; ++ ++ } ++ ++ stats->rx_fifo_errors = etc->rxoflo; ++ stats->rx_over_errors = etc->rxoflo; ++ stats->tx_fifo_errors = etc->txuflo; ++ ++ //etc_robomib(etc); ++ ++ if (locked) ++ ET_UNLOCK(et); ++ ++ return (stats); ++} ++ ++static int ++et_set_mac_address(struct net_device *dev, void *addr) ++{ ++ et_info_t *et; ++ struct sockaddr *sa = (struct sockaddr *) addr; ++ ++ et = ET_INFO(dev); ++ ET_TRACE(("et%d: et_set_mac_address\n", et->etc->unit)); ++ ++ if (et->etc->up) ++ return -EBUSY; ++ ++ bcopy(sa->sa_data, dev->dev_addr, ETHER_ADDR_LEN); ++ bcopy(dev->dev_addr, &et->etc->cur_etheraddr, ETHER_ADDR_LEN); ++ ++ return 0; ++} ++ ++static void ++et_set_multicast_list(struct net_device *dev) ++{ ++ et_info_t *et; ++ etc_info_t *etc; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ struct dev_mc_list *mclist; ++#else ++ struct netdev_hw_addr *ha ; ++#endif ++ int i; ++ int locked = 0; ++ ++ et = ET_INFO(dev); ++ etc = et->etc; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ mclist = NULL ; /* fend off warnings */ ++#else ++ ha = NULL ; ++#endif ++ ++ ET_TRACE(("et%d: et_set_multicast_list\n", etc->unit)); ++ ++ if (!in_atomic()) { ++ locked = 1; ++ ET_LOCK(et); ++ } ++ ++ if (etc->up) { ++ etc->promisc = (dev->flags & IFF_PROMISC)? TRUE: FALSE; ++ etc->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: etc->promisc; ++ ++ /* copy the list of multicasts into our private table */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ for (i = 0, mclist = dev->mc_list; mclist && (i < dev->mc_count); ++ i++, mclist = mclist->next) { ++ if (i >= MAXMULTILIST) { ++ etc->allmulti = TRUE; ++ i = 0; ++ break; ++ } ++ etc->multicast[i] = *((struct ether_addr *)mclist->dmi_addr); ++ } ++#else /* >= 2.6.36 */ ++ i = 0; ++ netdev_for_each_mc_addr(ha, dev) { ++ i ++; ++ if (i >= MAXMULTILIST) { ++ etc->allmulti = TRUE; ++ i = 0; ++ break; ++ } ++ etc->multicast[i] = *((struct ether_addr *)ha->addr); ++ } /* for each ha */ ++#endif /* LINUX_VERSION_CODE */ ++ etc->nmulticast = i; ++ ++ /* LR: partial re-init, DMA is already initialized */ ++ et_init(et, ET_INIT_INTRON); ++ } ++ ++ if (locked) ++ ET_UNLOCK(et); ++} ++ ++#ifdef CONFIG_BCM_GRO_ENABLE ++void et_flush(void *dev_id) ++{ ++ et_info_t *et; ++ struct chops *chops; ++ void *ch; ++ osl_t *osh; ++ ++ et = (et_info_t *)dev_id; ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ /* guard against shared interrupts */ ++ if (!et->etc->up) { ++ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); ++ return; ++ } ++ if (!et->napi_poll.gro_list) { ++ return; ++ } ++ /* disable interrupts */ ++ (*chops->intrsoff)(ch); ++ ++ et->resched = TRUE; ++ ++ napi_gro_flush(&et->napi_poll); ++ ++ /* enable interrupts now */ ++ (*chops->intrson)(ch); ++} ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++static irqreturn_t BCMFASTPATH ++et_isr(int irq, void *dev_id) ++#else ++static irqreturn_t BCMFASTPATH ++et_isr(int irq, void *dev_id, struct pt_regs *ptregs) ++#endif ++{ ++ et_info_t *et; ++ struct chops *chops; ++ void *ch; ++ uint events = 0; ++ osl_t *osh; ++ ++ et = (et_info_t *)dev_id; ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ /* guard against shared interrupts */ ++ if (!et->etc->up) { ++ ET_TRACE(("et%d: et_isr: not up\n", et->etc->unit)); ++ goto done; ++ } ++ ++ /* get interrupt condition bits */ ++ events = (*chops->getintrevents)(ch, TRUE); ++ ++ /* not for us */ ++ if (!(events & INTR_NEW)) ++ goto done; ++ ++ ET_TRACE(("et%d: et_isr: events 0x%x\n", et->etc->unit, events)); ++ ET_LOG("et%d: et_isr: events 0x%x", et->etc->unit, events); ++ ++#ifdef CONFIG_IPROC_2STAGE_RX ++ if (events & INTR_RX) { ++ et->rxinisr = true; ++ /* process a few RX interrupts */ ++ et_rxevent(osh, et, chops, ch, 1); ++ ++ et->rxinisr = false; ++ /* get interrupt condition bits */ ++ events = (*chops->getintrevents)(ch, TRUE); ++ et->resched = FALSE; ++ ++ /* not for us */ ++ if (!(events & INTR_NEW)) ++ goto done; ++ } ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++ ++ /* disable interrupts */ ++ (*chops->intrsoff)(ch); ++ ++ /* save intstatus bits */ ++ ASSERT(et->events == 0); ++ et->events = events; ++ ++ ASSERT(et->resched == FALSE); ++ ++#ifdef NAPI2_POLL ++ ++ napi_schedule(&et->napi_poll); ++ ++#elif defined(NAPI_POLL) ++ /* allow the device to be added to the cpu polling list if we are up */ ++ if (netif_rx_schedule_prep(et->dev)) { ++ /* tell the network core that we have packets to send up */ ++ __netif_rx_schedule(et->dev); ++ } else { ++ ET_ERROR(("et%d: et_isr: intr while in poll!\n", ++ et->etc->unit)); ++ (*chops->intrson)(ch); ++ } ++#else /* ! NAPI_POLL && ! NAPI2_POLL */ ++ /* schedule dpc */ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++ schedule_work(&et->dpc_task.work); ++ } else ++#endif /* ET_ALL_PASSIVE */ ++ tasklet_schedule(&et->tasklet); ++#endif /* NAPI_POLL */ ++ ++done: ++ ET_LOG("et%d: et_isr ret", et->etc->unit, 0); ++ ++ return IRQ_RETVAL(events & INTR_NEW); ++} ++ ++#ifdef GMAC3 ++static struct net_device * BCMFASTPATH ++et_find_dev(struct sk_buff *skb) { ++ ++ /* ----------------------------------------------- */ ++ /* ----------------------------------------------- */ ++ ++ return NULL; ++} ++#endif /* GMAC3 */ ++ ++#ifdef PKTC ++static void BCMFASTPATH ++et_sendup_chain(et_info_t *et, void *h) ++{ ++ struct sk_buff *skb; ++ uint sz = PKTCCNT(h); ++ ++ ASSERT(h != NULL); ++ ASSERT((sz > 0) && (sz <= PKTCBND)); ++ ET_TRACE(("et%d: %s: sending up packet chain of sz %d\n", ++ et->etc->unit, __FUNCTION__, sz)); ++ et->etc->chained += sz; ++ et->etc->currchainsz = sz; ++ et->etc->maxchainsz = MAX(et->etc->maxchainsz, sz); ++ ++#ifdef GMAC3 ++ /* Forward chain directly to wl transmit */ ++ if (DEV_FWDER(et->etc)) { ++ struct net_device * dev; ++ ++ //skb = PKTTOFORWARD(et->etc->osh, h, sz); ++ skb = PKTTONATIVE(et->etc->osh, h); ++ skb->dev = et->dev; ++ ++ dev = et_find_dev(skb); ++ ++ if (fwder_transmit(skb, dev, et->fwdh, sz) == FWDER_FAILURE) { ++ PKTCFREE(et->etc->osh, skb, FALSE); ++ } ++ } ++ else ++ ASSERT(DEV_NTKIF(et->etc)); ++#else /* !GMAC3 */ ++ ++ skb = PKTTONATIVE(et->etc->osh, h); ++ skb->dev = et->dev; ++ ++ /* send up the packet chain */ ++ ctf_forward(et->cih, h, et->dev); ++#endif /* !GMAC3 */ ++ ++} ++#endif /* PKTC */ ++ ++static inline int ++et_rxevent(osl_t *osh, et_info_t *et, struct chops *chops, void *ch, int quota) ++{ ++ uint processed = 0; ++ void *p, *h = NULL, *t = NULL; ++ struct sk_buff *skb; ++#ifdef PKTC ++ pktc_data_t cd[PKTCMC] = {{0}}; ++ uint8 *evh, prio; ++ int32 i = 0, cidx = 0; ++#ifdef GMAC3 ++ bool chaining = DEV_FWDER(et->etc); ++#else /* !GMAC3 */ ++ bool chaining = PKTC_ENAB(et); ++#endif /* !GMAC3 */ ++#endif ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ if ( et->etc->rl_enabled ) ++ etc_check_rate_limiting(et->etc, ch); ++#endif /* GMAC_RATE_LIMITING */ ++ ++ /* read the buffers first */ ++ while ((p = (*chops->rx)(ch))) { ++#ifdef PKTC ++ ASSERT(PKTCLINK(p) == NULL); ++ evh = PKTDATA(et->osh, p) + HWRXOFF; ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) ++ prio = IP_TOS46(evh + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ else ++#endif /* GMAC3 */ ++ prio = IP_TOS46(evh + ETHERVLAN_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ if (cd[0].h_da == NULL) { ++ cd[0].h_da = evh; cd[0].h_sa = evh + ETHER_ADDR_LEN; ++ cd[0].h_prio = prio; ++ } ++ ++ /* if current frame doesn't match cached src/dest/prio or has err flags ++ * set then stop chaining. ++ */ ++ if (chaining) { ++ for (i = 0; i <= cidx; i++) { ++ if (PKT_CHAINABLE(et, p, evh, prio, cd[i].h_sa, ++ cd[i].h_da, cd[i].h_prio)) ++ break; ++ else if ((i + 1 < PKTCMC) && (cd[i + 1].h_da == NULL)) { ++ cidx++; ++ cd[cidx].h_da = evh; ++ cd[cidx].h_sa = evh + ETHER_ADDR_LEN; ++ cd[cidx].h_prio = prio; ++ } ++ } ++ chaining = (i < PKTCMC); ++ } ++ ++ if (chaining) { ++ PKTCENQTAIL(cd[i].chead, cd[i].ctail, p); ++ /* strip off rxhdr */ ++ PKTPULL(et->osh, p, HWRXOFF); ++ ++ et->etc->rxframe++; ++ et->etc->rxbyte += PKTLEN(et->osh, p); ++ ++ /* strip off crc32 */ ++ PKTSETLEN(et->osh, p, PKTLEN(et->osh, p) - ETHER_CRC_LEN); ++ ++#ifndef GMAC3 ++ /* update header for non-first frames */ ++ if (cd[i].chead != p) ++ CTF_HOTBRC_L2HDR_PREP(et->osh, et->brc_hot, prio, ++ PKTDATA(et->osh, p), p); ++#endif /* !GMAC3 */ ++ ++ PKTCINCRCNT(cd[i].chead); ++ PKTSETCHAINED(et->osh, p); ++ PKTCADDLEN(cd[i].chead, PKTLEN(et->osh, p)); ++ } else ++ PKTCENQTAIL(h, t, p); ++#else /* PKTC */ ++ PKTSETLINK(p, NULL); ++ if (t == NULL) ++ h = t = p; ++ else { ++ PKTSETLINK(t, p); ++ t = p; ++ } ++#endif /* PKTC */ ++ ++ /* we reached quota already */ ++ if (++processed >= quota) { ++ /* reschedule et_dpc()/et_poll() */ ++ et->resched = TRUE; ++ et->etc->rxquota++; ++ break; ++ } ++ } ++ ++ /* prefetch the headers */ ++ if (h != NULL) ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); ++#else ++ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); ++#endif ++ ++ /* post more rx bufs */ ++ (*chops->rxfill)(ch); ++ ++#ifdef PKTC ++ /* send up the chain(s) at one fell swoop */ ++ ASSERT(cidx < PKTCMC); ++ for (i = 0; i <= cidx; i++) { ++ if (cd[i].chead != NULL) { ++#ifdef GMAC3 ++ PKTSETPRIO(cd[i].chead, cd[i].h_prio); ++#endif ++ et_sendup_chain(et, cd[i].chead); ++ } ++ } ++#endif ++ ++ while ((p = h) != NULL) { ++#ifdef PKTC ++ h = PKTCLINK(h); ++ PKTSETCLINK(p, NULL); ++#else ++ h = PKTLINK(h); ++ PKTSETLINK(p, NULL); ++#endif ++ /* prefetch the headers */ ++ if (h != NULL) ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(PKTDATA(osh, h), SKB_DATA_PREFETCH_LEN); ++#else ++ ETPREFHDRS(PKTDATA(osh, h), PREFSZ); ++#endif ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ uint8 *evh1; ++ //skb = PKTTOFORWARD(osh, p, 1); ++ skb = PKTTONATIVE(osh, p); ++ evh1 = skb->data + HWRXOFF; ++ skb->priority = IPV4_TOS(evh1 + ETHER_HDR_LEN) >> IPV4_TOS_PREC_SHIFT; ++ } else ++#endif ++ skb = PKTTONATIVE(osh, p); ++ et->etc->unchained++; ++ et_sendup(et, skb); ++ } ++ ++ return (processed); ++} ++ ++#if defined(NAPI2_POLL) ++static int BCMFASTPATH ++et_poll(struct napi_struct *napi, int budget) ++{ ++ int quota = budget; ++ struct net_device *dev = napi->dev; ++ et_info_t *et = ET_INFO(dev); ++ ++#elif defined(NAPI_POLL) ++static int BCMFASTPATH ++et_poll(struct net_device *dev, int *budget) ++{ ++ int quota = min(RXBND, *budget); ++ et_info_t *et = ET_INFO(dev); ++#else /* NAPI_POLL */ ++static void BCMFASTPATH ++et_dpc(ulong data) ++{ ++ et_info_t *et = (et_info_t *)data; ++ #ifndef GMAC3 ++ int quota = PKTC_ENAB(et) ? et->etc->pktcbnd : RXBND; ++ #else /* GMAC3 */ ++ int quota = PKTC_ENAB(et) ? et->etc->pktcbnd : RXBND; ++ #endif /* GMAC3 */ ++#endif /* NAPI_POLL */ ++ struct chops *chops; ++ void *ch; ++ osl_t *osh; ++ uint nrx = 0; ++ ++ chops = et->etc->chops; ++ ch = et->etc->ch; ++ osh = et->etc->osh; ++ ++ ET_TRACE(("et%d: et_dpc: events 0x%x\n", et->etc->unit, et->events)); ++ ET_LOG("et%d: et_dpc: events 0x%x", et->etc->unit, et->events); ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ ET_LOCK(et); ++#endif /* ! NAPIx_POLL */ ++ ++ if (!et->etc->up) ++ goto done; ++ ++ /* get interrupt condition bits again when dpc was rescheduled */ ++ if (et->resched) { ++ et->events = (*chops->getintrevents)(ch, FALSE); ++ et->resched = FALSE; ++ } ++ ++ if (et->events & INTR_RX) ++ nrx = et_rxevent(osh, et, chops, ch, quota); ++ ++ if (et->events & INTR_TX) { ++ (*chops->txreclaim)(ch, FALSE); ++ } ++ ++ (*chops->rxfill)(ch); ++ ++ /* handle error conditions, if reset required leave interrupts off! */ ++ if (et->events & INTR_ERROR) { ++ if ((*chops->errors)(ch)) { ++ printk("%s error, calling et_init() for et%d\n", __FUNCTION__, et->etc->unit); ++ et_init(et, ET_INIT_INTROFF); ++ } ++ else ++ if (nrx < quota) ++ nrx += et_rxevent(osh, et, chops, ch, quota); ++ } ++ ++ /* run the tx queue */ ++ if (et->etc->txq_state != 0) { ++ if (!ET_ALL_PASSIVE_ENAB(et)) { ++ et_sendnext(et); ++ } ++#ifdef ET_ALL_PASSIVE ++ else ++ #ifdef CONFIG_BCM_IPROC_GMAC_TXONCPU1 ++ schedule_work_on(1, &et->txq_task.work); ++ #else ++ schedule_work(&et->txq_task.work); ++ #endif ++ ++#endif /* ET_ALL_PASSIVE */ ++ } ++ ++ /* clear this before re-enabling interrupts */ ++ et->events = 0; ++ ++ /* something may bring the driver down */ ++ if (!et->etc->up) { ++ et->resched = FALSE; ++ goto done; ++ } ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ #ifdef ET_ALL_PASSIVE ++ if (et->resched) { ++ if (!ET_ALL_PASSIVE_ENAB(et)) ++ tasklet_schedule(&et->tasklet); ++ else ++ schedule_work(&et->dpc_task.work); ++ } ++ else ++ (*chops->intrson)(ch); ++ #else /* ET_ALL_PASSIVE */ ++ /* there may be frames left, reschedule et_dpc() */ ++ if (et->resched) ++ tasklet_schedule(&et->tasklet); ++ /* re-enable interrupts */ ++ else ++ (*chops->intrson)(ch); ++ #endif /* ET_ALL_PASSIVE */ ++#endif /* ! NAPIx_POLL */ ++ ++done: ++ ET_LOG("et%d: et_dpc ret", et->etc->unit, 0); ++ ++#if defined(NAPI_POLL) || defined(NAPI2_POLL) ++ #ifdef NAPI_POLL ++ /* update number of frames processed */ ++ *budget -= nrx; ++ dev->quota -= nrx; ++ ++ ET_TRACE(("et%d: et_poll: quota %d budget %d\n", ++ et->etc->unit, dev->quota, *budget)); ++ #else ++ ET_TRACE(("et%d: et_poll: budget %d\n", ++ et->etc->unit, budget)); ++ #endif ++ ++ /* we got packets but no quota */ ++ if (et->resched) ++ /* indicate that we are not done, don't enable ++ * interrupts yet. linux network core will call ++ * us again. ++ */ ++ return (1); ++ ++ #ifdef NAPI2_POLL ++ napi_complete(napi); ++ #else /* NAPI_POLL */ ++ netif_rx_complete(dev); ++ #endif ++ ++ /* enable interrupts now */ ++ (*chops->intrson)(ch); ++ ++ /* indicate that we are done */ ++ return (0); ++#else /* NAPI_POLL */ ++ ET_UNLOCK(et); ++ return; ++#endif /* NAPI_POLL */ ++} ++ ++#ifdef ET_ALL_PASSIVE ++static void BCMFASTPATH ++et_dpc_work(struct et_task *task) ++{ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ et_info_t *et = (et_info_t *)task->context; ++ et_dpc((unsigned long)et); ++#else ++ BUG_ON(1); ++#endif ++ return; ++} ++#endif /* ET_ALL_PASSIVE */ ++ ++static void ++et_error(et_info_t *et, struct sk_buff *skb, void *rxh) ++{ ++ uchar eabuf[32]; ++ struct ether_header *eh; ++ ++ eh = (struct ether_header *)skb->data; ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, eabuf); ++ ++ if (RXH_OVERSIZE(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: over size packet from %s\n", et->etc->unit, eabuf)); ++ } ++ if (RXH_CRC(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: crc error from %s\n", et->etc->unit, eabuf)); ++ } ++ if (RXH_OVF(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: fifo overflow\n", et->etc->unit)); ++ } ++ if (RXH_NO(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: crc error (odd nibbles) from %s\n", ++ et->etc->unit, eabuf)); ++ } ++ if (RXH_RXER(et->etc, rxh)) { ++ ET_ERROR(("et%d: rx: symbol error from %s\n", et->etc->unit, eabuf)); ++ } ++} ++ ++static inline int32 ++et_ctf_forward(et_info_t *et, struct sk_buff *skb) ++{ ++#ifdef HNDCTF ++ /* use slow path if ctf is disabled */ ++ if (!CTF_ENAB(et->cih)) ++ return (BCME_ERROR); ++ ++ /* try cut thru first */ ++ if (ctf_forward(et->cih, skb, skb->dev) != BCME_ERROR) ++ return (BCME_OK); ++ ++ /* clear skipct flag before sending up */ ++ PKTCLRSKIPCT(et->osh, skb); ++#endif /* HNDCTF */ ++ ++#ifdef CTFPOOL ++ /* allocate and add a new skb to the pkt pool */ ++ if (PKTISFAST(et->osh, skb)) ++ osl_ctfpool_add(et->osh); ++ ++ /* clear fast buf flag before sending up */ ++ PKTCLRFAST(et->osh, skb); ++ ++ /* re-init the hijacked field */ ++ CTFPOOLPTR(et->osh, skb) = NULL; ++#endif /* CTFPOOL */ ++ ++ /* map the unmapped buffer memory before sending up */ ++ PKTCTFMAP(et->osh, skb); ++ ++ return (BCME_ERROR); ++} ++ ++void BCMFASTPATH ++et_sendup(et_info_t *et, struct sk_buff *skb) ++{ ++ etc_info_t *etc; ++ void *rxh; ++ uint16 flags; ++#ifdef PRINT_PKT ++ int i; ++#endif /* PRINT_PKT */ ++#if defined(CONFIG_IPROC_FA2) ++ uint32 rcv_sts_word; ++#endif ++ ++ etc = et->etc; ++ ++ /* packet buffer starts with rxhdr */ ++ rxh = skb->data; ++ ++#if defined(CONFIG_IPROC_FA2) ++ rcv_sts_word = LTOH32(*((uint32 *)skb->data)); ++#endif ++ /* strip off rxhdr */ ++ __skb_pull(skb, HWRXOFF); ++ ++ ET_TRACE(("et%d: et_sendup: %d bytes\n", et->etc->unit, skb->len)); ++ ET_LOG("et%d: et_sendup: len %d", et->etc->unit, skb->len); ++ ++ etc->rxframe++; ++ etc->rxbyte += skb->len; ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) ++ if (et_ctf_active(et)) { ++#if defined(CONFIG_IPROC_FA) ++ if(!gBypass) { ++ if (fc_receive(skb) == -1) ++ goto err; ++ } ++#endif /* defined(CONFIG_IPROC_FA) */ ++ ++#if defined(CONFIG_IPROC_FA2) ++ if(!gBypass) { ++ ++ /* If pipeline did not indicate error, proceed with rx processing */ ++ if (!(RXH_CTFERROR(etc, rxh))) { ++ if (fa2_receive(skb) == FA2_PKT_DONE) { ++ goto drop_pkt; ++ } ++ } else { ++ /* ++ printk(KERN_DEBUG "\n=== rxstsword is 0x%08X\n", ++ rcv_sts_word); ++ */ ++ } ++ } ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ ++ /* remove brcm tag */ ++ ET_TRACE(("Removing BRCM TAG\n")); ++ /* size depends on egress tag opcode */ ++ switch ((skb->data[0] & 0xe0) >> 5) { ++ case 0: ++ case 1: ++ case 2: ++ skb_pull(skb, 4); ++ break; ++ case 3: ++ skb_pull(skb, 8); ++ break; ++ } ++ } ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2) || defined(CONFIG_MACH_NSP)) */ ++ ++ /* eh should now be aligned 2-mod-4 */ ++ ASSERT(((ulong)skb->data & 3) == 2); ++ ++ /* strip off crc32 */ ++ __skb_trim(skb, skb->len - ETHER_CRC_LEN); ++ ++ ET_PRHDR("rx", (struct ether_header *)skb->data, skb->len, etc->unit); ++ ET_PRPKT("rxpkt", skb->data, skb->len, etc->unit); ++#ifdef PRINT_PKT_SUM ++ printk("et%d: rxpkt len(0x%x) tag:0x%02x%02x%02x%02x\n", etc->unit, skb->len, ++ skb->data[12], skb->data[13], skb->data[14], skb->data[15]); ++#endif /* PRINT_PKT_SUM */ ++#ifdef PRINT_PKT ++ printk("et%d: %s len(0x%x) rxpkt:", etc->unit, __FUNCTION__, skb->len); ++ for (i=0; ilen; i++) { ++ if ( (i % 16) == 0 ) ++ printk("\n"); ++ printk("%02x ", skb->data[i]); ++ } ++ printk("\n"); ++#endif /* PRINT_PKT */ ++ ++ /* get the error flags */ ++ flags = RXH_FLAGS(etc, rxh); ++ ++ /* check for reported frame errors */ ++ if (flags) ++ goto err; ++ ++ skb->dev = et->dev; ++ ++#ifdef GMAC3 ++ if (DEV_FWDER(et->etc)) { ++ struct net_device * dev = et_find_dev(skb); ++ ++ if (fwder_transmit(skb, dev, et->fwdh, 1) == FWDER_FAILURE) { ++ PKTFRMNATIVE(etc->osh, skb); ++ PKTFREE(etc->osh, skb, FALSE); ++ } ++ return; ++ } ++#endif /* !GMAC3 */ ++ ++#ifdef HNDCTF ++ /* try cut thru' before sending up */ ++ if (et_ctf_forward(et, skb) != BCME_ERROR) ++ return; ++#endif /* HNDCTF */ ++ ++ ASSERT(!PKTISCHAINED(skb)); ++ ++ /* extract priority from payload and store it out-of-band ++ * in skb->priority ++ */ ++ if (et->etc->qos) ++ pktsetprio(skb, TRUE); ++ ++ skb->protocol = eth_type_trans(skb, et->dev); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ { ++ struct sk_buff *next = skb->next; ++ while (1) { ++ if (next != NULL) { ++ ++ prefetch_range(next, SKB_PREFETCH_LEN); ++ next = next->next; ++ } else { ++ break; ++ } ++ } ++ } ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif ++ ++ /* send it up */ ++#if defined(NAPI_POLL) || defined(NAPI2_POLL) ++#ifdef CONFIG_IPROC_2STAGE_RX ++ if (!et->rxinisr) ++ netif_receive_skb(skb); ++ else ++ netif_rx(skb); ++#else /* CONFIG_IPROC_2STAGE_RX */ ++ if (et->dev->features & NETIF_F_GRO) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { ++ skb = vlan_untag(skb); ++ if (unlikely(!skb)) { ++ goto err; ++ } ++ } ++ napi_gro_receive(&et->napi_poll, skb); ++ } else { ++ netif_receive_skb(skb); ++ } ++#endif /* CONFIG_IPROC_2STAGE_RX */ ++ ++#else /* NAPI_POLL */ ++ netif_rx(skb); ++#endif /* NAPI_POLL */ ++ ++ ET_LOG("et%d: et_sendup ret", et->etc->unit, 0); ++ ++ return; ++ ++err: ++ et_error(et, skb, rxh); ++ ++#if defined(CONFIG_IPROC_FA2) ++drop_pkt: ++#endif /* defined(CONFIG_IPROC_FA2) */ ++ PKTFRMNATIVE(etc->osh, skb); ++ PKTFREE(etc->osh, skb, FALSE); ++ ++ return; ++} ++ ++#ifdef HNDCTF ++void ++et_dump_ctf(et_info_t *et, struct bcmstrbuf *b) ++{ ++ ctf_dump(et->cih, b); ++} ++#endif ++ ++void ++et_dump(et_info_t *et, struct bcmstrbuf *b) ++{ ++ bcm_bprintf(b, "et%d: %s %s version %s\n", et->etc->unit, ++ __DATE__, __TIME__, EPI_VERSION_STR); ++ ++#ifdef HNDCTF ++#if defined(BCMDBG) ++ ctf_dump(et->cih, b); ++#endif ++#endif /* HNDCTF */ ++ ++ et_dumpet(et, b); ++ etc_dump(et->etc, b); ++ ++ bcm_bprintf(b, "txdfrm(%d); txdfrmropped(%d); txqlen(%d); txqstop(%d); txdmafull(%d) txmaxlen(%d) txsgpkt(%d)\n", ++ et->etc->txfrm, et->etc->txfrmdropped, et->etc->txqlen, et->etc->txqstop, et->etc->txdmafull, ++ et->etc->txmaxlen, et->etc->txsgpkt); ++ et->etc->txfrm=0; ++ et->etc->txfrmdropped=0; ++ et->etc->txqlen=0; ++ et->etc->txqstop=0; ++ et->etc->txdmafull=0; ++ et->etc->txmaxlen=0; ++ et->etc->txsgpkt=0; ++ ++ bcm_bprintf(b, "rxquota(%d); rxdmastopped(%d)\n", ++ et->etc->rxquota, et->etc->rxdmastopped); ++ et->etc->rxquota=0; ++ et->etc->rxdmastopped=0; ++#ifdef GMAC_RATE_LIMITING ++ bcm_bprintf(b, "rxd_dropped_packets(%d)\n", ++ et->etc->rl_dropped_packets); ++ et->etc->rl_dropped_packets=0; ++#endif /* GMAC_RATE_LIMITING */ ++ ++} ++ ++static void ++et_dumpet(et_info_t *et, struct bcmstrbuf *b) ++{ ++ bcm_bprintf(b, "et %p dev %p name %s tbusy %d txq[0].qlen %d malloced %d\n", ++ et, et->dev, et->dev->name, (uint)netif_queue_stopped(et->dev), et->txq[0].qlen, ++ MALLOCED(et->osh)); ++} ++ ++void ++et_link_up(et_info_t *et) ++{ ++ ET_ERROR(("et%d: link up (%d%s)\n", ++ et->etc->unit, et->etc->speed, (et->etc->duplex? "FD" : "HD"))); ++ printf("et%d Link Up: %d%s\n", et->etc->unit, et->etc->speed, et->etc->duplex?"FD":"HD"); ++ netif_carrier_on(et->dev); ++} ++ ++void ++et_link_down(et_info_t *et) ++{ ++ ET_ERROR(("et%d: link down\n", et->etc->unit)); ++ printf("et%d Link Down\n", et->etc->unit); ++ netif_carrier_off(et->dev); ++} ++ ++bool ++et_is_link_up(et_info_t *et) ++{ ++ return netif_carrier_ok(et->dev); ++} ++ ++int ++et_enable_device( uint idx ) ++{ ++ ulong flags; ++ uint coreidx, coreid; ++ int rc = -1; ++ ++ spin_lock_irqsave(&sih_lock, flags); ++ ++ si_setcore(sih, GMAC_CORE_ID, idx); ++ coreidx = si_coreidx(sih); ++ coreid = si_coreid(sih); ++ ++ //printk("%s coreidx(0x%x) coreid(0x%x)\n", __FUNCTION__, coreidx, coreid); ++ /* 2G_ENABLED: Enable IDM 250MHz for 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ si_core_reset(sih, 0x44, 0); ++#else ++ si_core_reset(sih, 0, 0); ++#endif ++ ++ /* Initialize USBHC core OK */ ++ rc = 0; ++ ++ si_setcoreidx(sih, coreidx); ++ spin_unlock_irqrestore(&sih_lock, flags); ++ ++ return rc; ++} ++ ++ ++/********************************************************************** ++ * bcm5301x_gmac_probe(device) ++ * ++ * The Platform Driver Probe function. ++ * ++ * Input parameters: ++ * device: The Device Context ++ * ++ * Return value: ++ * 0: Driver Probe is Succesful ++ * not 0: ERROR ++ **********************************************************************/ ++static int bcm5301x_gmac_probe(struct platform_device* pldev) ++{ ++ struct net_device *dev = NULL; ++ void __iomem *macbase = NULL; ++ struct resource *memres = NULL; ++ struct resource *irqres = NULL; ++ osl_t *osh = NULL; ++ et_info_t *et = NULL; ++ int unit = et_found; ++ int err = 0; ++ char name[128]; ++ int i; ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ char *var; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++ printk("%s enter name:%s; id:0x%x; unit:%d\n", __FUNCTION__, pldev->name, pldev->id, unit); ++ ++ /*Validation of platform device structure*/ ++ if (!pldev) { ++ ET_ERROR(("WRONG INPUT\nplatfrom_device ppointer should not be NULL.\n")); ++ return -EINVAL; ++ } ++ ++ et_found++; ++ ++ /* pre-qualify et unit, that can save the effort to do et_detach */ ++ ++ nvram_env_gmac_name(unit, name); ++ if (getvar(NULL, name) == NULL) { ++ printk("et%d: %s not found, ignore it\n", unit, name); ++ return -ENODEV; ++ } ++ ++ osh = osl_attach(pldev, PCI_BUS, FALSE); ++ ASSERT(osh); ++ ++ /* Get global SB handle */ ++ sih = si_kattach(SI_OSH); ++ ++ /* reset core */ ++ et_enable_device(unit); ++ ++ ET_TRACE(("%s call alloc_etherdev\n", __FUNCTION__)); ++ if ((dev = alloc_etherdev(sizeof( et_info_t ))) == NULL) { ++ ET_ERROR(("%s: alloc_etherdev() failed\n", __FUNCTION__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ et = ET_INFO(dev); ++ bzero(et, sizeof(et_info_t)); /* Is this needed in 2.6.36 ? -LR */ ++ et->dev = dev; ++ et->osh = osh; ++ ++ ET_TRACE(("%s get resources\n", __FUNCTION__)); ++ memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); ++ if (NULL == memres) { ++ ET_ERROR(("ERROR: Could not get Platform Resource MAC Register Memory Resurce\n")); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ if (!request_mem_region(memres->start, (memres->end - memres->start + 1), pldev->name)) { ++ ET_ERROR(("ERROR: Could not request mem region. In file %s, LN:%d\n", ++ __FILE__, __LINE__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0); ++ if (NULL == irqres) { ++ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register IRQ Resource\n")); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ dev->base_addr = memres->start; ++ dev->irq = irqres->start; ++ ++ printk("et%d: base_addr (0x%x) irq (%d)\n", unit, (uint32)dev->base_addr, dev->irq); ++ ++// if ((et->regsva = ioremap_nocache(dev->base_addr, PCI_BAR0_WINSZ)) == NULL) { ++ if ((et->regsva = ioremap_nocache(dev->base_addr, 0xc00)) == NULL) { ++ ET_ERROR(("et%d: ioremap() failed\n", unit)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ET_TRACE(("%s base_addr: 0x%x; regsva:0x%x\n", __FUNCTION__, (uint32)dev->base_addr, (uint32)et->regsva)); ++ ++ pldev->id = dev->base_addr; ++ dev_set_drvdata(&(pldev->dev), dev); ++ SET_NETDEV_DEV(dev, (&pldev->dev)); ++ ++ init_MUTEX(&et->sem); ++ spin_lock_init(&et->lock); ++ spin_lock_init(&et->txq_lock); ++ spin_lock_init(&et->tx_lock); ++ spin_lock_init(&et->isr_lock); ++ ++ for (i = 0; i < NUMTXQ; i++) ++ skb_queue_head_init(&et->txq[i]); ++ ++ /* common load-time initialization */ ++ et->etc = etc_attach((void *)et, VENDOR_BROADCOM, BCMIPROC_CHIP_ID, unit, osh, et->regsva); ++ if (et->etc == NULL) { ++ ET_ERROR(("et%d: etc_attach() failed\n", unit)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++#ifdef GMAC3 ++ et->fwdh = (fwder_t *)NULL; /* attached/dettached on et up/dn */ ++ /* The ethernet network interface uses "eth0". Use fwd0, fwd1 instead */ ++ if (DEV_FWDER(et->etc)) ++ strncpy(dev->name, DEV_FWDER_NAME, 3); ++ ++#endif /* GMAC3 */ ++ ++#ifdef HNDCTF ++ et->cih = ctf_attach(osh, dev->name, &et_msg_level, et_ctf_detach, et); ++ ++ if(et->cih) ++ { ++ printk("%s: et->cih not NULL \n", __FUNCTION__); ++ } ++ else ++ { ++ printk("%s: et->cih is NULL \n", __FUNCTION__); ++ } ++ printk("%s: CTF_ENAB(ci) = %d \n", __FUNCTION__, (CTF_ENAB(et->cih) ? 1 : 0)); ++ if (ctf_dev_register(et->cih, dev, FALSE) != BCME_OK) { ++ ET_ERROR(("et%d: ctf_dev_register() failed\n", unit)); ++ goto Exit; ++ } ++#endif /* HNDCTF */ ++ ++#ifdef CTFPOOL ++ /* create ctf packet pool with specified number of buffers */ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++if ((osl_ctfpool_init(unit, osh, CTFPOOLSZ, RXBUFSZ+BCMEXTRAHDROOM) < 0)) { ++ ET_ERROR(("et%d: chipattach: ctfpool alloc/init failed\n", unit)); ++ goto Exit; ++ } else { ++ printk("\net%d: chipattach: ctfpool alloc/init successful\n", unit); ++ } ++#else ++ if (CTF_ENAB(et->cih)) { ++ uint32 poolsz; ++ /* use large ctf poolsz for platforms with more memory */ ++ poolsz = ((num_physpages >= 32767) ? CTFPOOLSZ * 2 : ++ ((num_physpages >= 8192) ? CTFPOOLSZ : 0)); ++ if ((poolsz > 0) && ++ (osl_ctfpool_init(osh, poolsz, RXBUFSZ+BCMEXTRAHDROOM) < 0)) { ++ ET_ERROR(("et%d: chipattach: ctfpool alloc/init failed\n", unit)); ++ goto Exit; ++ } else { ++ printk("\net%d: chipattach: ctfpool alloc/init successful\n", unit); ++ } ++ } ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif /* CTFPOOL */ ++ ++ bcopy(&et->etc->cur_etheraddr, dev->dev_addr, ETHER_ADDR_LEN); ++ ++ /* init 1 second watchdog timer */ ++ init_timer(&et->timer); ++ et->timer.data = (ulong)dev; ++ et->timer.function = et_watchdog; ++ ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ /* schedule one second watchdog timer */ ++ et->timer.expires = jiffies + HZ; ++ mod_timer(&et->timer, et->timer.expires); ++ et->set = TRUE; ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ ++#ifdef GMAC_RATE_LIMITING ++ /* init 1 second watchdog timer */ ++ init_timer(&et->etc->rl_timer); ++ et->etc->rl_timer.data = (ulong)dev; ++ et->etc->rl_timer.function = et_release_congestion; ++#endif /* GMAC_RATE_LIMITING */ ++ ++#ifdef NAPI2_POLL ++ netif_napi_add(dev, & et->napi_poll, et_poll, 64); ++ napi_enable(&et->napi_poll); ++#endif /* NAPI2_POLL */ ++ ++#if !defined(NAPI_POLL) && !defined(NAPI2_POLL) ++ /* setup the bottom half handler */ ++ tasklet_init(&et->tasklet, et_dpc, (ulong)et); ++#endif /* NAPI_POLL */ ++ ++#ifdef ET_ALL_PASSIVE ++ if (ET_ALL_PASSIVE_ENAB(et)) { ++ MY_INIT_WORK(&et->dpc_task.work, (work_func_t)et_dpc_work); ++ et->dpc_task.context = et; ++ MY_INIT_WORK(&et->txq_task.work, (work_func_t)et_txq_work); ++ et->txq_task.context = et; ++ } ++ if (et_ctf_pipeline_loopback(et)) { ++ et->all_dispatch_mode = FALSE; ++ } else { ++ et->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE; ++ } ++#endif /* ET_ALL_PASSIVE */ ++ ++ ET_TRACE(("%s request irq\n", __FUNCTION__)); ++ /* register our interrupt handler */ ++ if (request_irq(dev->irq, et_isr, IRQF_SHARED, dev->name, et)) { ++ ET_ERROR(("%s: request_irq(%d) failed\n", __FUNCTION__, dev->irq)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ++ /* add us to the global linked list */ ++ et->next = et_list; ++ et_list = et; ++ ++#ifndef HAVE_NET_DEVICE_OPS ++ /* lastly, enable our entry points */ ++ dev->open = et_open; ++ dev->stop = et_close; ++ dev->hard_start_xmit = et_start; ++ dev->get_stats = et_get_stats; ++ dev->set_mac_address = et_set_mac_address; ++ dev->set_multicast_list = et_set_multicast_list; ++ dev->do_ioctl = et_ioctl; ++#ifdef NAPI_POLL ++ dev->poll = et_poll; ++ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); ++#endif /* NAPI_POLL */ ++#else /* HAVE_NET_DEVICE_OPS */ ++ /* Linux 2.6.36 and up. - LR */ ++ dev->netdev_ops = &et_netdev_ops ; ++#ifdef NAPI_POLL ++ dev->poll = et_poll; ++ dev->weight = (ET_GMAC(et->etc) ? 64 : 32); ++#endif /* NAPI_POLL */ ++ ++#endif /* !HAVE_NET_DEVICE_OPS */ ++ ++#if (defined(CONFIG_IPROC_FA2) && defined(CONFIG_IPROC_FA2_CS_OFFLOAD)) ++ if (et->etc->unit == 2) { ++ dev->features = (NETIF_F_IP_CSUM); ++ //dev->features = (NETIF_F_IP_CSUM | NETIF_F_SG); ++ //dev->hw_features = dev->features; ++ dev->vlan_features = (NETIF_F_IP_CSUM); ++ printk("\n Enabling checksum offload ...\n"); ++ } ++#endif /* CONFIG_IPROC_FA2 && CONFIG_IPROC_FA2_CS_OFFLOAD */ ++ ++#if defined(BCMDMASGLISTOSL) ++#ifdef CONFIG_BCM_GRO_ENABLE ++ dev->features = (NETIF_F_GRO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ dev->vlan_features = (NETIF_F_GRO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ printk("et%d: Enable Checksum-SG-GRO\n", unit); ++#else ++ dev->features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ dev->vlan_features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_CSUM); ++ printk("et%d: Enable Checksum-SG\n", unit); ++#endif ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ dev->ethtool_ops = &et_ethtool_ops; ++#endif ++ ++ /* Assign netdev name consistently, even if GMAC0 or 1 is disabled */ ++ { ++ unsigned char devname[8] = {0}; ++ snprintf(devname, 8, "eth%d", unit); ++ dev_alloc_name(dev, devname); ++ } ++ ++ ET_TRACE(("%s register netdev\n", __FUNCTION__)); ++ if (register_netdev(dev)) { ++ ET_ERROR(("%s register_netdev() failed\n", __FUNCTION__)); ++ err = -ENOMEM; ++ goto Exit; ++ } ++ ET_LOCK(et); ++ et->etc->linkstate = FALSE; ++ et_link_down(et); ++ ET_UNLOCK(et); ++ ++ /* print hello string */ ++ (*et->etc->chops->longname)(et->etc->ch, name, sizeof(name)); ++ printk("%s: %s %s\n", dev->name, name, EPI_VERSION_STR); ++ ++ eth_mac_proc_create(dev); ++ ++#ifdef HNDCTF ++ if (ctf_enable(et->cih, dev, TRUE, &et->brc_hot) != BCME_OK) { ++ ET_ERROR(("et%d: ctf_enable() failed\n", unit)); ++ goto Exit; ++ } ++#endif ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ /* check if brcm tag is turned off */ ++ var = getvar(NULL, "brcmtag"); ++ if (var) { ++ int tag = bcm_strtoul(var, NULL, 0); ++ if (tag==0) { ++ ET_ERROR(("BRCM TAG disabled\n")); ++ brcm_tag = false; ++ } ++ } ++ printk("BRCM TAG %sabled\n", brcm_tag?"en":"dis"); ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ printk("et_ctf_active %sabled\n", et_ctf_active(et)?"en":"dis"); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++ ++Exit: ++ if (macbase) { ++ iounmap(macbase); ++ macbase=NULL; ++ } ++ if (memres) { ++ release_mem_region(memres->start, (memres->end - memres->start + 1)); ++ memres=NULL; ++ } ++ if (dev) { ++ free_netdev(dev); ++ dev = NULL; ++ } ++ if (osh) { ++ osl_detach(osh); ++ osh=NULL; ++ } ++ if (et) { ++ etc_detach(et->etc); ++ et->dev = NULL; ++ et->osh = NULL; ++ et_free(et); ++ et=NULL; ++ } ++ return err; ++} ++ ++ ++/********************************************************************** ++ * bcm5301x_gmac_remove(device) ++ * ++ * The Removal of Platform Device, and un-initialize the previously ++ * added MAC, and it's MEM Regions and Resources. ++ * ++ * Input parameters: ++ * device: The Device Context ++ * ++ * Return value: ++ * 0: Driver Entry is Succesfull ++ **********************************************************************/ ++static int __exit bcm5301x_gmac_remove(struct platform_device *pldev) ++{ ++ struct net_device *dev = platform_get_drvdata(pldev); ++ int retVal = 0; ++ et_info_t *et = NULL; ++ struct resource *memres = NULL; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++#ifdef CONFIG_PM ++ bcm5301x_gmac_drv_suspend(pldev, PMSG_SUSPEND); ++#endif ++ ++ et = ET_INFO(dev); ++ ++ iounmap(et->regsva); ++ unregister_netdev(dev); ++ ++ memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); ++ if (memres) { ++ release_mem_region(memres->start, (memres->end - memres->start + 1)); ++ } else { ++ ET_ERROR(("ERROR: Could not get Platform Resource GMAC Register Memory Resource\n")); ++ retVal = -ENOMEM; ++ } ++ ++ free_netdev(dev); ++ ++ et->dev = NULL; ++ et_free(et); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return retVal; ++} ++ ++#ifdef CONFIG_PM ++static int bcm5301x_gmac_drv_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ int ret; ++ char *filename = "/usr/sbin/ifdown"; ++ char *argv[] = {filename, "eth0", NULL}; ++ char *envp[] = {"HOME=/", ++ "TERM=linux", ++ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", ++ NULL}; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++} ++ ++static int bcm5301x_gmac_drv_resume(struct platform_device *pdev) ++{ ++ int ret; ++ char *filename = "/usr/sbin/ifup"; ++ char *argv[] = {filename, "eth0", NULL}; ++ char *envp[] = {"HOME=/", ++ "TERM=linux", ++ "PATH=/sbin:/usr/sbin:/bin:/usr/bin", ++ NULL}; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ret = kernel_execve(filename, (const char * const*) argv, (const char * const*) envp); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ ++ return 0; ++} ++#else ++#define bcm5301x_gmac_drv_suspend NULL ++#define bcm5301x_gmac_drv_resume NULL ++#endif ++ ++/********************************************************************** ++ * GMAC0 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac0_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac0_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC0 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac0_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac0_pdev = { ++ .name = bcm5301x_gmac0_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac0_string, ++ .dma_mask = &gmac0_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac0_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac0_resources), ++}; ++ ++/********************************************************************** ++ * GMAC1 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac1_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac1_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC1 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac1_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac1_pdev = { ++ .name = bcm5301x_gmac1_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac1_string, ++ .dma_mask = &gmac1_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac1_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac1_resources), ++}; ++ ++/********************************************************************** ++ * GMAC2 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac2_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac2_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC2 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac2_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac2_pdev = { ++ .name = bcm5301x_gmac2_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac2_string, ++ .dma_mask = &gmac2_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac2_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac2_resources), ++}; ++ ++/********************************************************************** ++ * GMAC3 driver: ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. ++**********************************************************************/ ++static struct platform_driver bcm5301x_gmac3_driver = ++{ ++ .probe = bcm5301x_gmac_probe, ++ .remove = __exit_p(bcm5301x_gmac_remove), ++ .suspend = bcm5301x_gmac_drv_suspend, ++ .resume = bcm5301x_gmac_drv_resume, ++ .driver = ++ { ++ .name = bcm5301x_gmac3_string, ++ }, ++}; ++ ++/********************************************************************** ++ * GMAC3 device: ++ * This structure defines the methods to be called by a platform device ++ * during the lifecycle of a device ++**********************************************************************/ ++static u64 gmac3_dmamask = DMA_BIT_MASK(32); ++static struct platform_device bcm5301x_gmac3_pdev = { ++ .name = bcm5301x_gmac3_string, ++ .id = 0, ++ .dev = { ++ .release = bcm5301x_gmac_release, ++ .init_name = bcm5301x_gmac3_string, ++ .dma_mask = &gmac3_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++ .resource = bcm5301x_gmac3_resources, ++ .num_resources = ARRAY_SIZE(bcm5301x_gmac3_resources), ++}; ++ ++/********************************************************************** ++ * This function calls the device structure. ++ * Input Parameter: ++ * dev - pointer to the struct device ++ **********************************************************************/ ++ ++static void bcm5301x_gmac_release (struct device *dev) {} ++ ++/********************************************************************** ++ * bcm5301x_gmac_init_module(VOID) ++ * ++ * The Driver Entry Function ++ * ++ * Input parameters: ++ * None ++ * ++ * Return value: ++ * 0: Driver Entry is Succesful ++ * not 0: ERROR ++ **********************************************************************/ ++static int __init ++bcm5301x_gmac_init_module(void) ++{ ++ int err = -1; ++ int deverr = -1; ++ int idx; ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ ++ spin_lock_init(&sih_lock); ++ ++#if defined(BCMDBG) ++ if (msglevel != 0xdeadbeef) ++ et_msg_level = msglevel; ++ else { ++ char *var = getvar(NULL, "et_msglevel"); ++ if (var) ++ et_msg_level = bcm_strtoul(var, NULL, 0); ++ } ++ ++ printk("%s: msglevel set to 0x%x\n", __FUNCTION__, et_msg_level); ++#endif /* defined(BCMDBG) */ ++ ++#ifdef ET_ALL_PASSIVE ++ { ++ char *var = getvar(NULL, "et_dispatch_mode"); ++ if (var) ++ passivemode = bcm_strtoul(var, NULL, 0); ++ printk("%s: passivemode set to 0x%x\n", __FUNCTION__, passivemode); ++ } ++#endif /* ET_ALL_PASSIVE */ ++#ifdef NAPI_POLL ++ printk("%s: NAPI_POLL mode\n", __FUNCTION__); ++#endif /* NAPI_POLL */ ++#ifdef NAPI2_POLL ++ printk("%s: NAPI2_POLL mode\n", __FUNCTION__); ++#endif /* NAPI2_POLL */ ++ ++#ifdef ET_LIMIT_TXQ ++ { ++ char *var = getvar(NULL, "et_txq_thresh"); ++ if (var) ++ et_txq_thresh = bcm_strtoul(var, NULL, 0); ++ printk("%s: et_txq_thresh set to 0x%x\n", __FUNCTION__, et_txq_thresh); ++ } ++#endif /* ET_LIMIT_TXQ */ ++#ifdef GMAC_RATE_LIMITING ++ { ++ char *var = getvar(NULL, "et_rx_rate_limit"); ++ if (var) ++ et_rx_rate_limit = bcm_strtoul(var, NULL, 0); ++ printk("%s: et_rx_rate_limit set to 0x%x\n", __FUNCTION__, et_rx_rate_limit); ++ } ++#endif /* GMAC_RATE_LIMITING */ ++ ++#ifdef GMAC3 ++ fwder_init(); ++ /* fwder_dump_all(); */ ++#endif /* GMAC3 */ ++ ++ /* keep track of which ones loaded */ ++ for (idx=0; idx1) { ++ /* load GMAC1 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac1_driver); ++ if (!err) { ++ /* load GMAC1 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac1_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac1_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[1] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>2) { ++ /* load GMAC2 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac2_driver); ++ if (!err) { ++ /* load GMAC2 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac2_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac2_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[2] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>3) { ++ /* load GMAC3 driver */ ++ err = iproc_platform_driver_register(&bcm5301x_gmac3_driver); ++ if (!err) { ++ /* load GMAC3 device */ ++ err = iproc_platform_device_register(&bcm5301x_gmac3_pdev); ++ if (err) { ++ iproc_platform_driver_unregister(&bcm5301x_gmac3_driver); ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } else { ++ gmac_pdev_loaded[3] = true; ++ deverr = 0; ++ } ++ } else { ++ ET_ERROR(("ERROR module_init, could not iproc_platform_driver_register\n")); ++ ET_ERROR(("Error Code = 0x%08x\n", err)); ++ } ++ } ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return deverr; ++} ++ ++/********************************************************************** ++ * bcm5301x_gmac_cleanup_module(VOID) ++ * ++ * The Driver Exit Function ++ * ++ * Input parameters: ++ * None ++ * ++ * Return value: ++ * Nothing ++ **********************************************************************/ ++static void __exit ++bcm5301x_gmac_cleanup_module(void) ++{ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++ if ( gmac_pdev_loaded[0] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac0_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac0_driver); ++ } ++ ++ if (IPROC_NUM_GMACS>1) { ++ if ( gmac_pdev_loaded[1] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac1_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac1_driver); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>2) { ++ if ( gmac_pdev_loaded[2] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac2_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac2_driver); ++ } ++ } ++ ++ if (IPROC_NUM_GMACS>3) { ++ if ( gmac_pdev_loaded[3] ) { ++ /* unregister device */ ++ iproc_platform_device_unregister(&bcm5301x_gmac3_pdev); ++ /* Unregister the driver*/ ++ iproc_platform_driver_unregister(&bcm5301x_gmac3_driver); ++ } ++ } ++ ++ //clean up the proc directory ++ eth_mac_proc_remove(); ++ ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return; ++} ++ ++static int get_fa_bypass(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ unsigned int len=0; ++ len += sprintf(page+len, "\n\n## Current FA Bypass setting = 0x%x, %s ##\n\n",gBypass, gBypass?"enabled":"disabled"); ++ *eof = 1; ++ return len; ++} ++ ++static int set_fa_bypass(struct file *file, const char *buffer, unsigned long count, void *data) ++{ ++ unsigned int len=1; ++ unsigned char debug_buffer[2]; ++ int bypass =0; ++ ++ //printk("count %x ## \n\n",(unsigned int) count); ++ if (count != 2) ++ { ++ ET_ERROR(("Please pass (one:1) digit FA bypass value only, 0=disable FA bypass, 1 = enable FA bypass\n")); ++ return -EINVAL; ++ } ++ ++ // Last buffer byte will be LF or CR only ++ if(copy_from_user(&debug_buffer[0], buffer, len)) ++ { ++ ET_ERROR(("Problem in copying invalid user buffer\n")); ++ return -EFAULT; ++ } ++ ++ debug_buffer[len]='\0'; // Only one byte value is available now ++ if ( sscanf(debug_buffer,"%d",&bypass) != 1) ++ { ++ ET_ERROR(("\n##Invalid value :%s: is passed ##\n",debug_buffer)); ++ return -EINVAL; ++ } ++ if (!((bypass >=DISABLE_FA_BYPASS) && (bypass <= ENABLE_FA_BYPASS))) ++ { ++ ET_ERROR(("\n##Passed value :%d: is not in valid range %d-%d \n",bypass,DISABLE_FA_BYPASS,ENABLE_FA_BYPASS)); ++ return -EINVAL; ++ } ++ ET_TRACE(("\n##set_fa_bypass(): Previous: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); ++ gBypass = bypass; ++ ET_TRACE(("\n##set_fa_bypass(): New: 0x%x %s ##\n", gBypass, gBypass?"enabled":"disabled")); ++ return count; ++} ++ ++ ++static char* bcm5301x_eth_proc_root="bcm5301x_eth"; ++static struct proc_dir_entry *bcm5301x_eth_root_dir ; // BCM5892 eth proc root directory ++ ++static int eth_mac_proc_create(struct net_device *dev ) ++{ ++ struct proc_dir_entry *dent, *ent; ++ et_info_t *et; ++ etc_info_t *etc; ++ char fname[32]; ++ ++ et = ET_INFO(dev); ++ if (et != NULL) { ++ etc = et->etc; ++ } ++ ++ if ((et == NULL) || (etc == NULL)) { ++ printk("%s: error: Unit probably not initialized by probe function." ++ " et=0x%pm etc=0x%p\n", __FUNCTION__, et, etc); ++ return -1; ++ } ++ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ ++ snprintf(fname, 32, "%s%u", bcm5301x_eth_proc_root, etc->unit); ++ ++ dent = proc_mkdir(fname,bcm5301x_eth_root_dir); ++ if (dent) { ++ /* unit 2 has FA connectivity, create bypass path only for unit 2 */ ++ if (etc->unit == 2) { ++ printk("\nCreating fa bypass proc entry\n"); ++ ++ ent = create_proc_entry("fa_bypass", S_IFREG|S_IRUGO, dent); ++ if (ent) { ++ ent->read_proc = get_fa_bypass; ++ ent->write_proc = set_fa_bypass; ++ } ++ else { ++ printk("Error creating proc_entry, returning\n"); ++ return -1; ++ } ++ } ++ } ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++ return 0; ++} ++ ++static void eth_mac_proc_remove(void) ++{ ++ ET_TRACE(("%s: enter\n", __FUNCTION__)); ++ printk("%s: enter\n", __FUNCTION__); ++ remove_proc_entry(bcm5301x_eth_proc_root,NULL); ++ ET_TRACE(("%s: exit\n", __FUNCTION__)); ++} ++ ++ ++#if defined(CONFIG_IPROC_FA2) ++int et_fa2_spu_tx(struct sk_buff *skb) ++{ ++ struct net_device *dev = platform_get_drvdata(&bcm5301x_gmac3_pdev); ++ return et_start(skb, dev); ++} ++ ++#if defined(CONFIG_IPROC_FA2_CS_OFFLOAD) ++static et_info_t *et_get_eth3_info() ++{ ++ et_info_t *et; ++ struct net_device *d = platform_get_drvdata(&bcm5301x_gmac3_pdev); ++ ++ et = ET_INFO(d); ++ ++ if (et == NULL) { ++ printk(KERN_INFO "\net for dev3 is NULL, using dev2\n"); ++ // NOTEet = ET_INFO(dev); ++ ++ } ++ ++ return(et); ++} ++#endif /* CONFIG_IPROC_FA2_CS_OFFLOAD */ ++#endif /* CONFIG_IPROC_FA2 */ ++ ++ ++module_init(bcm5301x_gmac_init_module); ++module_exit(bcm5301x_gmac_cleanup_module); ++ ++MODULE_DESCRIPTION("Broadcom Northstar Ethernet Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h +new file mode 100755 +index 0000000..68b4de8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/et_linux.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux device driver tunables for ++ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver ++ * ++ * $Id: et_linux.h 320789 2012-03-13 04:01:27Z $ ++ */ ++ ++#ifndef _et_linux_h_ ++#define _et_linux_h_ ++ ++/* tunables */ ++#define NTXD 512 /* # tx dma ring descriptors (must be ^2) */ ++#define NRXD 512 /* # rx dma ring descriptors (must be ^2) */ ++#if defined(CONFIG_RAM_SIZE) && (CONFIG_RAM_SIZE <= 16) ++#define NRXBUFPOST 256 /* try to keep this # rbufs posted to the chip */ ++#else ++#define NRXBUFPOST 420 /* try to keep this # rbufs posted to the chip */ ++#endif ++#ifdef CONFIG_JUMBO_FRAME ++#define BCM_ETHER_MAX_LEN 2500 ++#else ++#define BCM_ETHER_MAX_LEN 1518 //ETHER_MAX_LEN (1518) ++#endif /* CONFIG_JUMBO_FRAME */ ++#define RXBUFSZ (BCM_ETHER_MAX_LEN + HWRXOFF + BCMEXTRAHDROOM) /* receive buffer size */ ++ ++#ifndef RXBND ++#define RXBND 64 //32 /* max # rx frames to process in dpc */ ++#endif ++ ++#if defined(ILSIM) || defined(__arch_um__) ++#undef NTXD ++#define NTXD 16 ++#undef NRXD ++#define NRXD 16 ++#undef NRXBUFPOST ++#define NRXBUFPOST 2 ++#endif ++ ++#define PKTCBND 48 ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define CTFPOOLSZ (2048) ++#else ++#define CTFPOOLSZ 768 ++#endif ++ ++#define PREFSZ 96 ++#ifndef PKTC ++#define ETPREFHDRS(h, sz) OSL_PREF_RANGE_ST((h), (sz)) ++#else ++#define ETPREFHDRS(h, sz) ++#endif ++ ++#endif /* _et_linux_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etc.c b/drivers/bcmdrivers/gmac/src/et/sys/etc.c +new file mode 100755 +index 0000000..a356421 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etc.c +@@ -0,0 +1,899 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Common [OS-independent] portion of ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Device Driver. ++ * ++ * $Id: etc.c 323634 2012-03-26 10:26:11Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef ETROBO ++#ifndef _siutils_h_ ++typedef const struct si_pub si_t; ++#endif ++#include ++#endif /* ETROBO */ ++ ++uint32 et_msg_level = ++#ifdef BCMDBG ++ 1; ++#else ++ 0; ++#endif /* BCMDBG */ ++ ++uint8 ethup=0; ++uint8 ethupmask=0; ++etc_info_t *ethupetcptr[IPROC_NUM_GMACS]; ++ ++/* local prototypes */ ++static void etc_loopback(etc_info_t *etc, int on); ++static void etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b); ++int etc_gmac_speed(int gmac); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++extern void gmac_set_amac_mdio(int en); ++extern int gmac_has_mdio_access(void); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++void gmac_serdes_asym_mode(etc_info_t *etcptrs[]); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++ ++/* 802.1d priority to traffic class mapping. queues correspond one-to-one ++ * with traffic classes. ++ */ ++uint32 up2tc[NUMPRIO] = { ++ TC_BE, /* 0 BE TC_BE Best Effort */ ++ TC_BK, /* 1 BK TC_BK Background */ ++ TC_BK, /* 2 -- TC_BK Background */ ++ TC_BE, /* 3 EE TC_BE Best Effort */ ++ TC_CL, /* 4 CL TC_CL Controlled Load */ ++ TC_CL, /* 5 VI TC_CL Controlled Load */ ++ TC_VO, /* 6 VO TC_VO Voice */ ++ TC_VO /* 7 NC TC_VO Voice */ ++}; ++ ++uint32 priq_selector[] = { ++ [0x0] = TC_NONE, [0x1] = TC_BK, [0x2] = TC_BE, [0x3] = TC_BE, ++ [0x4] = TC_CL, [0x5] = TC_CL, [0x6] = TC_CL, [0x7] = TC_CL, ++ [0x8] = TC_VO, [0x9] = TC_VO, [0xa] = TC_VO, [0xb] = TC_VO, ++ [0xc] = TC_VO, [0xd] = TC_VO, [0xe] = TC_VO, [0xf] = TC_VO ++}; ++ ++/* find the chip opsvec for this chip */ ++struct chops* ++etc_chipmatch(uint vendor, uint device) ++{ ++#ifdef CFG_GMAC ++ { ++ extern struct chops bcmgmac_et_chops; ++ ++ if (bcmgmac_et_chops.id(vendor, device)) ++ return (&bcmgmac_et_chops); ++ } ++#endif /* CFG_GMAC */ ++ return (NULL); ++} ++ ++void* ++etc_attach(void *et, uint vendor, uint device, uint unit, void *osh, void *regsva) ++{ ++ etc_info_t *etc; ++ char *var; ++ ++ ET_TRACE(("et%d: etc_attach: vendor 0x%x device 0x%x\n", unit, vendor, device)); ++ ++ /* some code depends on packed structures */ ++ ASSERT(sizeof(struct ether_addr) == ETHER_ADDR_LEN); ++ ASSERT(sizeof(struct ether_header) == ETHER_HDR_LEN); ++ ++ /* allocate etc_info_t state structure */ ++ if ((etc = (etc_info_t*) MALLOC(osh, sizeof(etc_info_t))) == NULL) { ++ ET_ERROR(("et%d: etc_attach: out of memory, malloced %d bytes\n", unit, ++ MALLOCED(osh))); ++ return (NULL); ++ } ++ bzero((char*)etc, sizeof(etc_info_t)); ++ ++ etc->et = et; ++ etc->unit = unit; ++ etc->osh = osh; ++ etc->vendorid = (uint16) vendor; ++ etc->deviceid = (uint16) device; ++ etc->forcespeed = etc_gmac_speed(unit); ++ etc->linkstate = FALSE; ++ etc->mdio_init_time = 5; /* number of seconds to wait before release mdio bus */ ++ var = getvar(NULL, "eth_init_time"); ++ if (var) ++ etc->mdio_init_time = bcm_strtoul(var, NULL, 0); ++ printk("%s() mdio_init_time = %d\n", __FUNCTION__, etc->mdio_init_time); ++ ethupmask |= 1<unit; ++ ethupetcptr[unit] = etc; ++ ++#ifdef PKTC ++ /* initialize default pktc values */ ++ etc->pktcbnd = MAX(PKTCBND, RXBND); ++#endif ++ ++ /* set chip opsvec */ ++ etc->chops = etc_chipmatch(vendor, device); ++ ASSERT(etc->chops); ++ ++ /* chip attach */ ++ if ((etc->ch = (*etc->chops->attach)(etc, osh, regsva)) == NULL) { ++ ET_ERROR(("et%d: chipattach error\n", unit)); ++ goto fail; ++ } ++ ++ return ((void*)etc); ++ ++fail: ++ etc_detach(etc); ++ return (NULL); ++} ++ ++void ++etc_detach(etc_info_t *etc) ++{ ++ if (etc == NULL) ++ return; ++ ++ /* free chip private state */ ++ if (etc->ch) { ++ (*etc->chops->detach)(etc->ch); ++ etc->chops = etc->ch = NULL; ++ } ++ ++ MFREE(etc->osh, etc, sizeof(etc_info_t)); ++} ++ ++void ++etc_reset(etc_info_t *etc) ++{ ++ ET_TRACE(("et%d: etc_reset\n", etc->unit)); ++ ++ etc->reset++; ++ ++ /* reset the chip */ ++ (*etc->chops->reset)(etc->ch); ++ ++ /* free any posted tx packets */ ++ (*etc->chops->txreclaim)(etc->ch, TRUE); ++ ++#ifdef DMA ++ /* free any posted rx packets */ ++ (*etc->chops->rxreclaim)(etc->ch); ++#endif /* DMA */ ++} ++ ++void ++etc_init(etc_info_t *etc, uint options) ++{ ++ ET_TRACE(("et%d: etc_init\n", etc->unit)); ++ ++ ASSERT(etc->pioactive == NULL); ++ ASSERT(!ETHER_ISNULLADDR(&etc->cur_etheraddr)); ++ ASSERT(!ETHER_ISMULTI(&etc->cur_etheraddr)); ++ ++ /* init the chip */ ++ (*etc->chops->init)(etc->ch, options); ++ /* init the PM change mode and linkstate */ ++ etc->pm_modechange = FALSE; ++} ++ ++/* mark interface up */ ++void ++etc_up(etc_info_t *etc) ++{ ++ etc->up = TRUE; ++ ++ /* enable the port phy */ ++ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 1); ++ ++ et_init(etc->et, ET_INIT_FULL | ET_INIT_INTRON); ++} ++ ++/* mark interface down */ ++uint ++etc_down(etc_info_t *etc, int reset) ++{ ++ uint callback; ++ ++ callback = 0; ++ ++ ET_FLAG_DOWN(etc); ++ ++ /* disable the port phy */ ++ (*etc->chops->phyenable)(etc->ch, etc->unit, etc->phyaddr, 0); ++ ++ if (reset) ++ et_reset(etc->et); ++ ++ /* suppress link state changes during power management mode changes */ ++ if (etc->linkstate) { ++ etc->linkstate = FALSE; ++ if (!etc->pm_modechange) ++ et_link_down(etc->et); ++ } ++ ++ return (callback); ++} ++ ++/* common iovar handler. return 0=ok, -1=error */ ++int ++etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg) ++{ ++ int error; ++ uint *vecarg; ++#if defined(ETROBO) && !defined(_CFE_) ++ int i; ++ robo_info_t *robo = etc->robo; ++#endif /* ETROBO && _CFE_ */ ++ ++ error = 0; ++ vecarg = (uint *)arg; ++ ET_TRACE(("et%d: etc_iovar: cmd 0x%x\n", etc->unit, cmd)); ++ ++ switch (cmd) { ++#if defined(ETROBO) && !defined(_CFE_) ++ case IOV_ET_POWER_SAVE_MODE: ++ if (set) ++ error = robo_power_save_mode_set(robo, vecarg[1], vecarg[0]); ++ else { ++ /* get power save mode of all the phys */ ++ if (vecarg[0] == MAX_NO_PHYS) { ++ for (i = 0; i < MAX_NO_PHYS; i++) ++ vecarg[i] = robo_power_save_mode_get(robo, i); ++ break; ++ } ++ ++ /* get power save mode of the phy */ ++ error = robo_power_save_mode_get(robo, vecarg[0]); ++ if (error != -1) { ++ vecarg[1] = error; ++ error = 0; ++ } ++ } ++ break; ++ ++ case IOV_ET_ROBO_DEVID: ++ error = -1; ++ ++ if (robo != NULL) { ++ *vecarg = robo->devid; ++ error = 0; ++ } ++ break; ++#endif /* ETROBO && !_CFE_ */ ++#ifdef BCMDBG ++ case IOV_ET_CLEAR_DUMP: ++ if (set) { ++ uint size = ((char *)(&etc->rxbadlen) - (char *)(&etc->txframe)); ++ ++ bzero((char *)&etc->txframe, size + sizeof(etc->rxbadlen)); ++ (*etc->chops->dumpmib)(etc->ch, NULL, TRUE); ++ error = 0; ++ } ++ break; ++#endif /* BCMDBG */ ++ case IOV_PKTC: ++ if (set) ++ etc->pktc = *vecarg; ++ else ++ *vecarg = (uint)etc->pktc; ++ break; ++ ++ case IOV_PKTCBND: ++ if (set) ++ etc->pktcbnd = MAX(*vecarg, 32); ++ else ++ *vecarg = etc->pktcbnd; ++ break; ++ ++ case IOV_COUNTERS: ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ etc_dumpetc(etc, &b); ++ } ++ break; ++ ++#ifdef HNDCTF ++ case IOV_DUMP_CTF: ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ et_dump_ctf(etc->et, &b); ++ } ++ break; ++#endif /* HNDCTF */ ++ ++ default: ++ error = -1; ++ } ++ ++ return (error); ++} ++ ++/* common ioctl handler. return: 0=ok, -1=error */ ++int ++etc_ioctl(etc_info_t *etc, int cmd, void *arg) ++{ ++ int error; ++ int val; ++ int *vec = (int*)arg; ++ ++ error = 0; ++ ++ val = arg ? *(int*)arg : 0; ++ ++ ET_TRACE(("et%d: etc_ioctl: cmd 0x%x\n", etc->unit, cmd)); ++ ++ switch (cmd) { ++ case ETCUP: ++ et_up(etc->et); ++ break; ++ ++ case ETCDOWN: ++ et_down(etc->et, TRUE); ++ break; ++ ++ case ETCLOOP: ++ etc_loopback(etc, val); ++ break; ++ ++ case ETCDUMP: ++ if (et_msg_level & 0x10000) ++ bcmdumplog((char *)arg, IOCBUFSZ); ++ else ++ { ++ struct bcmstrbuf b; ++ bcm_binit(&b, (char*)arg, IOCBUFSZ); ++ et_dump(etc->et, &b); ++ } ++ break; ++ ++ case ETCSETMSGLEVEL: ++ et_msg_level = val; ++ break; ++ ++ case ETCPROMISC: ++ etc_promisc(etc, val); ++ break; ++ ++ case ETCQOS: ++ etc_qos(etc, val); ++ break; ++ ++ case ETCSPEED: ++ if (vec) { ++ if (vec[0] == ET_1000FULL) { ++ etc->speed = 1000; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_1000HALF) { ++ etc->speed = 1000; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_100FULL) { ++ etc->speed = 100; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_100HALF) { ++ etc->speed = 100; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_10FULL) { ++ etc->speed = 10; ++ etc->duplex = 1; ++ } else if (vec[0] == ET_10HALF) { ++ etc->speed = 10; ++ etc->duplex = 0; ++ } else if (vec[0] == ET_AUTO) ++ ; ++ else ++ goto err; ++ ++ etc->forcespeed = vec[0]; ++ ++ /* explicitly reset the phy */ ++ (*etc->chops->phyreset)(etc->ch, etc->phyaddr); ++ ++ /* request restart autonegotiation if we're reverting to adv mode */ ++ etc->advertise = etc->advertise2 = 0; ++ if (etc->forcespeed == ET_AUTO) { ++ if (vec[1] & ADVERTISED_10baseT_Half) ++ etc->advertise |= ADV_10HALF; ++ if (vec[1] & ADVERTISED_10baseT_Full) ++ etc->advertise |= ADV_10FULL; ++ if (vec[1] & ADVERTISED_100baseT_Half) ++ etc->advertise |= ADV_100HALF; ++ if (vec[1] & ADVERTISED_100baseT_Full) ++ etc->advertise |= ADV_100FULL; ++ if (vec[1] & ADVERTISED_1000baseT_Full) ++ etc->advertise2 |= ADV_1000FULL; ++ etc->needautoneg = TRUE; ++ } else { ++ etc->needautoneg = FALSE; ++ } ++ et_init(etc->et, ET_INIT_INTRON); ++ } ++ break; ++ ++ case ETCPHYRD: ++ if (vec) { ++ vec[1] = (*etc->chops->phyrd)(etc->ch, etc->phyaddr, vec[0]); ++ ET_TRACE(("etc_ioctl: ETCPHYRD of reg 0x%x => 0x%x\n", vec[0], vec[1])); ++ } ++ break; ++ ++ case ETCPHYRD2: ++ if (vec) { ++ uint phyaddr, reg; ++ phyaddr = vec[0] >> 16; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ if (phyaddr < MAXEPHY) { ++#else ++ if (1) { ++#endif ++ reg = vec[0] & 0xffff; ++ vec[1] = (*etc->chops->phyrd)(etc->ch, phyaddr, reg); ++ ET_TRACE(("etc_ioctl: ETCPHYRD2 of phy 0x%x, reg 0x%x => 0x%x\n", ++ phyaddr, reg, vec[1])); ++ } ++ } ++ break; ++ ++ case ETCPHYWR: ++ if (vec) { ++ ET_TRACE(("etc_ioctl: ETCPHYWR to reg 0x%x <= 0x%x\n", vec[0], vec[1])); ++ (*etc->chops->phywr)(etc->ch, etc->phyaddr, vec[0], (uint16)vec[1]); ++ } ++ break; ++ ++ case ETCPHYWR2: ++ if (vec) { ++ uint phyaddr, reg; ++ phyaddr = vec[0] >> 16; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ if (phyaddr < MAXEPHY) { ++#else ++ if (1) { ++#endif ++ reg = vec[0] & 0xffff; ++ (*etc->chops->phywr)(etc->ch, phyaddr, reg, (uint16)vec[1]); ++ ET_TRACE(("etc_ioctl: ETCPHYWR2 to phy 0x%x, reg 0x%x <= 0x%x\n", ++ phyaddr, reg, vec[1])); ++ } ++ } ++ break; ++ ++#ifdef ETROBO ++ case ETCROBORD: ++ if (etc->robo && vec) { ++ uint page, reg; ++ uint16 val; ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++ ++ page = vec[0] >> 16; ++ reg = vec[0] & 0xffff; ++ val = -1; ++ robo->ops->read_reg(etc->robo, page, reg, &val, 2); ++ vec[1] = val; ++ ET_TRACE(("etc_ioctl: ETCROBORD of page 0x%x, reg 0x%x => 0x%x\n", ++ page, reg, val)); ++ } ++ break; ++ ++ case ETCROBOWR: ++ if (etc->robo && vec) { ++ uint page, reg; ++ uint16 val; ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++ ++ page = vec[0] >> 16; ++ reg = vec[0] & 0xffff; ++ val = vec[1]; ++ robo->ops->write_reg(etc->robo, page, vec[0], &val, 2); ++ ET_TRACE(("etc_ioctl: ETCROBOWR to page 0x%x, reg 0x%x <= 0x%x\n", ++ page, reg, val)); ++ } ++ break; ++#endif /* ETROBO */ ++ ++ ++ default: ++ err: ++ error = -1; ++ } ++ ++ return (error); ++} ++ ++/* called once per second */ ++void ++etc_watchdog(etc_info_t *etc) ++{ ++ uint16 status; ++ uint16 lpa; ++#if defined(ETROBO) ++ robo_info_t *robo = (robo_info_t *)etc->robo; ++#endif ++#if defined(ETROBO) && !defined(_CFE_) ++ static uint32 sleep_timer = PWRSAVE_SLEEP_TIME, wake_timer; ++#endif /* ETROBO && !_CFE_ */ ++ uint16 phyaddrflag=0; ++ ++ etc->now++; ++ ++#if defined(ETROBO) ++ /* BCM53125 EEE IOP WAR for some other vendor's wrong EEE implementation. */ ++ if (robo) ++ robo_watchdog(robo); ++#endif ++ ++#if defined(ETROBO) && !defined(_CFE_) ++ /* Every PWRSAVE_WAKE_TIME sec the phys that are in manual mode ++ * is taken out of that mode and link status is checked after ++ * PWRSAVE_SLEEP_TIME sec to see if any of the links is up ++ * to take that port is taken out of the manual power save mode ++ */ ++ if (robo) { ++ if (ROBO_IS_PWRSAVE_MANUAL(robo)) { ++ if (etc->now == sleep_timer) { ++ robo_power_save_toggle(robo, FALSE); ++ wake_timer = sleep_timer + PWRSAVE_WAKE_TIME; ++ } else if (etc->now == wake_timer) { ++ robo_power_save_toggle(robo, TRUE); ++ sleep_timer = wake_timer + PWRSAVE_SLEEP_TIME; ++ } ++ } ++ ++ /* Apply the auto configuration from the nvram variable in the beginning */ ++ if ((etc->now == PWRSAVE_WAKE_TIME) && ROBO_IS_PWRSAVE_AUTO(robo)) { ++ robo_power_save_mode_update(robo); ++ } ++ } ++#endif /* ETROBO && !_CFE_ */ ++ ++ /* no local phy registers */ ++ if (etc->phyaddr == EPHY_NOREG) { ++ etc->linkstate = TRUE; ++ etc->duplex = 1; ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ return; ++ } ++ ++ if (etc->up && etc->linkstate) { ++ if (!(ethup & 1<unit)) ++ printf("et%d Interface up\n", etc->unit); ++ ethup |= 1<unit; ++ } ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#if defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) ++ if ( !gmac_has_mdio_access()) { ++ /* we can't monitor link so force link up */ ++ /* if GMAC does not have access to MDIO then exit */ ++ if (!etc->linkstate) { ++ etc->linkstate = TRUE; ++ etc->duplex = 1; ++ etc->speed = 1000; ++ } ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ if (!et_is_link_up(etc->et)) { ++ printf("%s can't access PHY, forcing link up\n", __FUNCTION__); ++ et_link_up(etc->et); ++ } ++ return; ++ } ++#endif /* defined(CONFIG_IPROC_SDK_MGT_PORT_HANDOFF) */ ++ /* access external phy */ ++ phyaddrflag = 0; ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++ ++ status = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 1); ++ /* check for bad mdio read */ ++ if (status == 0xffff) { ++ ET_ERROR(("et%d: etc_watchdog: bad mdio read: phyaddr %d mdcport %d\n", ++ etc->unit, etc->phyaddr, etc->mdcport)); ++ return; ++ } ++ ++ if (etc->forcespeed == ET_AUTO) { ++ uint16 adv, adv2 = 0, status2 = 0, estatus; ++ ++ adv = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 4); ++ lpa = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 5); ++ ++ /* read extended status register. if we are 1000BASE-T ++ * capable then get our advertised capabilities and the ++ * link partner capabilities from 1000BASE-T control and ++ * status registers. ++ */ ++ estatus = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 15); ++ if ((estatus != 0xffff) && (estatus & EST_1000TFULL)) { ++ /* read 1000BASE-T control and status registers */ ++ adv2 = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 9); ++ status2 = (*etc->chops->phyrd)(etc->ch, phyaddrflag+etc->phyaddr, 10); ++ } ++ ++ /* update current speed and duplex */ ++ if ((adv2 & ADV_1000FULL) && (status2 & LPA_1000FULL)) { ++ etc->speed = 1000; ++ etc->duplex = 1; ++ } else if ((adv2 & ADV_1000HALF) && (status2 & LPA_1000HALF)) { ++ etc->speed = 1000; ++ etc->duplex = 0; ++ } else if ((adv & ADV_100FULL) && (lpa & LPA_100FULL)) { ++ etc->speed = 100; ++ etc->duplex = 1; ++ } else if ((adv & ADV_100HALF) && (lpa & LPA_100HALF)) { ++ etc->speed = 100; ++ etc->duplex = 0; ++ } else if ((adv & ADV_10FULL) && (lpa & LPA_10FULL)) { ++ etc->speed = 10; ++ etc->duplex = 1; ++ } else { ++ etc->speed = 10; ++ etc->duplex = 0; ++ } ++ } ++ ++ /* monitor link state */ ++ if (!etc->linkstate && (status & STAT_LINK)) { ++ etc->linkstate = TRUE; ++ if (etc->pm_modechange) ++ etc->pm_modechange = FALSE; ++ else { ++ et_link_up(etc->et); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ (*etc->chops->forcespddpx)(etc->ch); ++#endif /* (!defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ } ++ } else if (etc->linkstate && !(status & STAT_LINK)) { ++ etc->linkstate = FALSE; ++ if (!etc->pm_modechange) ++ et_link_down(etc->et); ++ } ++ ++ /* keep emac txcontrol duplex bit consistent with current phy duplex */ ++ (*etc->chops->duplexupd)(etc->ch); ++ ++ /* check for remote fault error */ ++ if (status & STAT_REMFAULT) { ++ ET_ERROR(("et%d: remote fault\n", etc->unit)); ++ } ++ ++ /* check for jabber error */ ++ if (status & STAT_JAB) { ++ ET_ERROR(("et%d: jabber\n", etc->unit)); ++ } ++ ++ /* ++ * Read chip mib counters occationally before the 16bit ones can wrap. ++ * We don't use the high-rate mib counters. ++ */ ++ if ((etc->now % 30) == 0) ++ (*etc->chops->statsupd)(etc->ch); ++} ++ ++static void ++etc_loopback(etc_info_t *etc, int on) ++{ ++ ET_TRACE(("et%d: etc_loopback: %d\n", etc->unit, on)); ++ ++ etc->loopbk = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_promisc(etc_info_t *etc, uint on) ++{ ++ ET_TRACE(("et%d: etc_promisc: %d\n", etc->unit, on)); ++ ++ etc->promisc = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_qos(etc_info_t *etc, uint on) ++{ ++ ET_TRACE(("et%d: etc_qos: %d\n", etc->unit, on)); ++ ++ etc->qos = (bool) on; ++ et_init(etc->et, ET_INIT_INTRON); ++} ++ ++void ++etc_dump(etc_info_t *etc, struct bcmstrbuf *b) ++{ ++ etc_dumpetc(etc, b); ++ (*etc->chops->dump)(etc->ch, b); ++} ++ ++static void ++etc_dumpetc(etc_info_t *etc, struct bcmstrbuf *b) ++{ ++ char perm[32], cur[32]; ++ uint i; ++ ++ bcm_bprintf(b, "etc 0x%x et 0x%x unit %d msglevel %d speed/duplex %d%s\n", ++ (ulong)etc, (ulong)etc->et, etc->unit, et_msg_level, ++ etc->speed, (etc->duplex ? "full": "half")); ++ bcm_bprintf(b, "up %d promisc %d loopbk %d forcespeed %d advertise 0x%x " ++ "advertise2 0x%x needautoneg %d\n", ++ etc->up, etc->promisc, etc->loopbk, etc->forcespeed, ++ etc->advertise, etc->advertise2, etc->needautoneg); ++ bcm_bprintf(b, "piomode %d pioactive 0x%x nmulticast %d allmulti %d qos %d\n", ++ etc->piomode, (ulong)etc->pioactive, etc->nmulticast, etc->allmulti, etc->qos); ++ bcm_bprintf(b, "vendor 0x%x device 0x%x rev %d coreunit %d phyaddr %d mdcport %d\n", ++ etc->vendorid, etc->deviceid, etc->chiprev, ++ etc->coreunit, etc->phyaddr, etc->mdcport); ++ ++ bcm_bprintf(b, "perm_etheraddr %s cur_etheraddr %s\n", ++ bcm_ether_ntoa(&etc->perm_etheraddr, perm), ++ bcm_ether_ntoa(&etc->cur_etheraddr, cur)); ++ ++ if (etc->nmulticast) { ++ bcm_bprintf(b, "multicast: "); ++ for (i = 0; i < etc->nmulticast; i++) ++ bcm_bprintf(b, "%s ", bcm_ether_ntoa(&etc->multicast[i], cur)); ++ bcm_bprintf(b, "\n"); ++ } ++ ++ bcm_bprintf(b, "linkstate %d\n", etc->linkstate); ++ bcm_bprintf(b, "\n"); ++ ++ /* refresh stat counters */ ++ (*etc->chops->statsupd)(etc->ch); ++ ++ /* summary stat counter line */ ++ /* use sw frame and byte counters -- hw mib counters wrap too quickly */ ++ bcm_bprintf(b, "txframe %d txbyte %d txerror %d rxframe %d rxbyte %d rxerror %d\n", ++ etc->txframe, etc->txbyte, etc->txerror, ++ etc->rxframe, etc->rxbyte, etc->rxerror); ++ ++ /* transmit & receive stat counters */ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ (*etc->chops->dumpmib)(etc->ch, b, FALSE); ++ ++ bcm_bprintf(b, "txnobuf %d reset %d dmade %d dmada %d dmape %d\n", ++ etc->txnobuf, etc->reset, etc->dmade, etc->dmada, etc->dmape); ++ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ bcm_bprintf(b, "rxnobuf %d rxdmauflo %d rxoflo %d rxbadlen %d " ++ "rxgiants %d rxoflodiscards %d\n", ++ etc->rxnobuf, etc->rxdmauflo, etc->rxoflo, etc->rxbadlen, ++ etc->rxgiants, etc->rxoflodiscards); ++ ++ bcm_bprintf(b, "chained %d chainedsz1 %d unchained %d maxchainsz %d currchainsz %d\n", ++ etc->chained, etc->chainedsz1, etc->unchained, etc->maxchainsz, ++ etc->currchainsz); ++ ++ bcm_bprintf(b, "\n"); ++} ++ ++uint ++etc_totlen(etc_info_t *etc, void *p) ++{ ++ uint total; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(etc->osh, p)) ++ total += PKTLEN(etc->osh, p); ++ return (total); ++} ++ ++#ifdef BCMDBG ++void ++etc_prhdr(char *msg, struct ether_header *eh, uint len, int unit) ++{ ++ char da[32], sa[32]; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("et%d: %s: ", unit, msg); ++ else ++ printf("et%d: ", unit); ++ ++ printf("dst %s src %s type 0x%04X len %d\n", ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_dhost, da), ++ bcm_ether_ntoa((struct ether_addr *)eh->ether_shost, sa), ++ ntoh16(eh->ether_type), ++ len); ++} ++void ++etc_prhex(char *msg, uchar *buf, uint nbytes, int unit) ++{ ++ if (msg && (msg[0] != '\0')) ++ printf("et%d: %s:\n", unit, msg); ++ else ++ printf("et%d:\n", unit); ++ ++ prhex(NULL, buf, nbytes); ++} ++#endif /* BCMDBG */ ++ ++ ++#ifdef ETROBO ++extern void robo_dump_mib(robo_info_t *robo); ++extern void robo_reset_mib(robo_info_t *robo); ++#endif ++extern void etc_chip_mib(etc_info_t *etc); ++void ++etc_robomib(etc_info_t *etc) ++{ ++#ifdef ETROBO ++ if (etc->robo) { ++ robo_dump_mib(etc->robo); ++ robo_reset_mib(etc->robo); ++ } ++#endif ++ ++ etc_chip_mib(etc); ++} ++ ++int ++etc_gmac_speed(int gmac) ++{ ++ char name[16], *speed; ++ sprintf(name, "et%dspeed", gmac); ++ ++ speed = nvram_get(name); ++ if (speed == NULL) { ++ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); ++ return ET_AUTO; ++ } ++ ++ if (!strcmp(speed, "2500")) { ++ printf("%s specifing GMAC%d speed: 2500\n", __FUNCTION__, gmac); ++ return ET_2500FULL; ++ } ++ else if (!strcmp(speed, "1000")) { ++ printf("%s specifing GMAC%d speed: 1000\n", __FUNCTION__, gmac); ++ return ET_1000FULL; ++ } ++ else if (!strcmp(speed, "100")) { ++ printf("%s specifing GMAC%d speed: 100\n", __FUNCTION__, gmac); ++ return ET_100FULL; ++ } ++ else if (!strcmp(speed, "10")) { ++ printf("%s specifing GMAC%d speed: 10\n", __FUNCTION__, gmac); ++ return ET_10FULL; ++ } ++ ++ printf("%s default GMAC%d speed: auto\n", __FUNCTION__, gmac); ++ return ET_AUTO; ++} +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etc.h b/drivers/bcmdrivers/gmac/src/et/sys/etc.h +new file mode 100755 +index 0000000..c31ce8a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etc.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Common [OS-independent] header file for ++ * Broadcom BCM47XX 10/100Mbps Ethernet Device Driver ++ * ++ * $Id: etc.h 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#ifndef _etc_h_ ++#define _etc_h_ ++ ++#include ++ ++#define MAXMULTILIST 32 ++ ++#ifndef ch_t ++#define ch_t void ++#endif ++ ++#if defined(CONFIG_MACH_NS) ++#define NUMTXQ 4 ++#else ++#define NUMTXQ 1 ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ++#define TXREC_THR 8 ++ ++#if defined(__ECOS) ++#define IOCBUFSZ 4096 ++#elif defined(__linux__) ++#define IOCBUFSZ 16384 ++#else ++#define IOCBUFSZ 4096 ++#endif ++ ++struct etc_info; /* forward declaration */ ++struct bcmstrbuf; /* forward declaration */ ++ ++/* each chip type supports a set of chip-type-specific ops */ ++struct chops { ++ bool (*id)(uint vendor, uint device); /* return true if match */ ++ void *(*attach)(struct etc_info *etc, void *dev, void *regs); ++ void (*detach)(ch_t *ch); /* free chip private state */ ++ void (*reset)(ch_t *ch); /* chip reset */ ++ void (*init)(ch_t *ch, uint options); /* chip init */ ++ bool (*tx)(ch_t *ch, void *p); /* transmit frame */ ++ void *(*rx)(ch_t *ch); /* receive frame */ ++ void (*rxfill)(ch_t *ch); /* post dma rx buffers */ ++ int (*getintrevents)(ch_t *ch, bool in_isr); /* return intr events */ ++ bool (*errors)(ch_t *ch); /* handle chip errors */ ++ void (*intrson)(ch_t *ch); /* enable chip interrupts */ ++ void (*intrsoff)(ch_t *ch); /* disable chip interrupts */ ++ void (*txreclaim)(ch_t *ch, bool all); /* reclaim transmit resources */ ++ void (*rxreclaim)(ch_t *ch); /* reclaim receive resources */ ++ void (*statsupd)(ch_t *ch); /* update sw stat counters */ ++ void (*dumpmib)(ch_t *ch, struct bcmstrbuf *, bool clear); /* get sw mib counters */ ++ void (*enablepme)(ch_t *ch); /* enable PME */ ++ void (*disablepme)(ch_t *ch); /* disable PME */ ++ void (*phyreset)(ch_t *ch, uint phyaddr); /* reset phy */ ++ uint16 (*phyrd)(ch_t *ch, uint phyaddr, uint reg); /* read phy register */ ++ void (*phywr)(ch_t *ch, uint phyaddr, uint reg, uint16 val); /* write phy register */ ++ void (*dump)(ch_t *ch, struct bcmstrbuf *b); /* debugging output */ ++ void (*longname)(ch_t *ch, char *buf, uint bufsize); /* return descriptive name */ ++ void (*duplexupd)(ch_t *ch); /* keep mac duplex consistent */ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ void (*forcespddpx)(ch_t *ch); /* force the speed and duplex */ ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ void (*phyenable)(ch_t *ch, uint eth_num, uint phyaddr, int enable); /* enable phy */ ++}; ++ ++/* ++ * "Common" os-independent software state structure. ++ */ ++typedef struct etc_info { ++#ifdef GMAC3 ++ bool gmac_fwd; /* gmac forwarding */ ++#endif /* GMAC3 */ ++ void *et; /* pointer to os-specific private state */ ++ uint unit; /* device instance number */ ++ void *osh; /* pointer to os handler */ ++ bool pktc; /* packet chaining enabled or not */ ++ int pktcbnd; /* max # of packets to chain */ ++ void *mib; /* pointer to s/w maintained mib counters */ ++ bool up; /* interface up and running */ ++ bool promisc; /* promiscuous destination address */ ++ bool qos; /* QoS priority determination on rx */ ++ bool loopbk; /* loopback override mode */ ++ ++ int forcespeed; /* disable autonegotiation and force speed/duplex */ ++ uint advertise; /* control speed/duplex advertised caps */ ++ uint advertise2; /* control gige speed/duplex advertised caps */ ++ bool needautoneg; /* request restart autonegotiation */ ++ int speed; /* current speed: 10, 100 */ ++ int duplex; /* current duplex: 0=half, 1=full */ ++ ++ bool piomode; /* enable programmed io (!dma) */ ++ void *pioactive; /* points to pio packet being transmitted */ ++ volatile uint *txavail[NUMTXQ]; /* dma: # tx descriptors available */ ++ ++ uint16 vendorid; /* pci function vendor id */ ++ uint16 deviceid; /* pci function device id */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint coreid; /* core id */ ++ uint corerev; /* core revision */ ++ ++ bool nicmode; /* is this core using its own pci i/f */ ++ ++ struct chops *chops; /* pointer to chip-specific opsvec */ ++ void *ch; /* pointer to chip-specific state */ ++ void *robo; /* optional robo private data */ ++ ++ uint txq_state; /* tx queues state bits */ ++ uint coreunit; /* sb chips: chip enet instance # */ ++ uint phyaddr; /* sb chips: mdio 5-bit phy address */ ++ uint mdcport; /* sb chips: which mii to use (enet core #) to access phy */ ++ ++ struct ether_addr cur_etheraddr; /* our local ethernet address */ ++ struct ether_addr perm_etheraddr; /* original sprom local ethernet address */ ++ ++ struct ether_addr multicast[MAXMULTILIST]; ++ uint nmulticast; ++ bool allmulti; /* enable all multicasts */ ++ ++ bool linkstate; /* link integrity state */ ++ bool pm_modechange; /* true if mode change is to due pm */ ++ ++ uint32 now; /* elapsed seconds */ ++ ++ uint32 boardflags; /* board flags */ ++ uint32 txrec_thresh; /* # of tx frames after which reclaim is done */ ++ ++ uint32 mdio_init_time; /* # of seconds to wait before release mdio bus */ ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ bool rl_enabled; /* enable rate limiting logic */ ++ struct timer_list rl_timer; /* one second ratelimiting timer */ ++ bool rl_set; /* indicate the timer is set or not */ ++ uint32 rl_stopping_all_packets; ++ uint32 rl_stopping_broadcasts; ++ uint32 rl_dropped_all_packets; ++ uint32 rl_dropped_bc_packets; ++ uint32 rl_dropped_packets; ++ uint32 rl_prior_jiffies; ++#endif /* GMAC_RATE_LIMITING */ ++ ++ /* sw-maintained stat counters */ ++ uint32 txframes[NUMTXQ]; /* transmitted frames on each tx fifo */ ++ uint32 txframe; /* transmitted frames */ ++ uint32 txbyte; /* transmitted bytes */ ++ uint32 rxframe; /* received frames */ ++ uint32 rxbyte; /* received bytes */ ++ uint32 txerror; /* total tx errors */ ++ uint32 txnobuf; /* tx out-of-buffer errors */ ++ uint32 rxerror; /* total rx errors */ ++ uint32 rxgiants; /* total rx giant frames */ ++ uint32 rxnobuf; /* rx out-of-buffer errors */ ++ uint32 reset; /* reset count */ ++ uint32 dmade; /* pci descriptor errors */ ++ uint32 dmada; /* pci data errors */ ++ uint32 dmape; /* descriptor protocol error */ ++ uint32 rxdmauflo; /* receive descriptor underflow */ ++ uint32 rxoflo; /* receive fifo overflow */ ++ uint32 txuflo; /* transmit fifo underflow */ ++ uint32 rxoflodiscards; /* frames discarded during rx fifo overflow */ ++ uint32 rxbadlen; /* 802.3 len field != read length */ ++ uint32 chained; /* number of frames chained */ ++ uint32 chainedsz1; /* number of chain size 1 frames */ ++ uint32 unchained; /* number of frames not chained */ ++ uint32 maxchainsz; /* max chain size so far */ ++ uint32 currchainsz; /* current chain size */ ++ /* my counters */ ++ uint32 txfrm; /* tx frames */ ++ uint32 txfrmdropped; /* tx dropped frames */ ++ uint32 txqlen; ++ uint32 txqstop; ++ uint32 txdmafull; ++ uint32 txmaxlen; ++ uint32 txsgpkt; ++ uint32 rxquota; ++ uint32 rxdmastopped; ++} etc_info_t; ++ ++/* interrupt event bitvec */ ++#define INTR_TX 0x1 ++#define INTR_RX 0x2 ++#define INTR_ERROR 0x4 ++#define INTR_TO 0x8 ++#define INTR_NEW 0x10 ++ ++/* forcespeed values */ ++#define ET_AUTO -1 ++#define ET_10HALF 0 ++#define ET_10FULL 1 ++#define ET_100HALF 2 ++#define ET_100FULL 3 ++#define ET_1000HALF 4 ++#define ET_1000FULL 5 ++#define ET_2500FULL 6 /* 2.5Gigabit */ ++ ++/* init options */ ++#define ET_INIT_FULL 0x1 ++#define ET_INIT_INTRON 0x2 ++ ++/* Specific init options for et_init */ ++#define ET_INIT_DEF_OPTIONS (ET_INIT_FULL | ET_INIT_INTRON) ++#define ET_INIT_INTROFF (ET_INIT_FULL) ++#define ET_INIT_PARTIAL (0) ++ ++/* macro to safely clear the UP flag */ ++#define ET_FLAG_DOWN(x) (*(x)->chops->intrsoff)((x)->ch); \ ++ (x)->up = FALSE; ++ ++/* ++ * Least-common denominator rxbuf start-of-data offset: ++ * Must be >= size of largest rxhdr ++ * Must be 2-mod-4 aligned so IP is 0-mod-4 ++ */ ++#define HWRXOFF 30 ++ ++#define TC_BK 0 /* background traffic class */ ++#define TC_BE 1 /* best effort traffic class */ ++#define TC_CL 2 /* controlled load traffic class */ ++#define TC_VO 3 /* voice traffic class */ ++#define TC_NONE -1 /* traffic class none */ ++ ++#define RX_Q0 0 /* receive DMA queue */ ++#define NUMRXQ 1 /* gmac has one rx queue */ ++ ++#define TX_Q0 TC_BK /* DMA txq 0 */ ++#define TX_Q1 TC_BE /* DMA txq 1 */ ++#define TX_Q2 TC_CL /* DMA txq 2 */ ++#define TX_Q3 TC_VO /* DMA txq 3 */ ++ ++static inline uint32 ++etc_up2tc(uint32 up) ++{ ++ extern uint32 up2tc[]; ++ ++ return (up2tc[up]); ++} ++ ++static inline uint32 ++etc_priq(uint32 txq_state) ++{ ++ extern uint32 priq_selector[]; ++ ++ return (priq_selector[txq_state]); ++} ++ ++/* rx header flags bits */ ++#define RXH_FLAGS(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ ((((bcmgmacrxh_t *)(rxh))->flags) & htol16(GRXF_CRC | GRXF_OVF | GRXF_OVERSIZE)) : \ ++ ((((bcmenetrxh_t *)(rxh))->flags) & htol16(RXF_NO | RXF_RXER | RXF_CRC | RXF_OV))) ++ ++#define RXH_OVERSIZE(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVERSIZE) : FALSE) ++ ++#define RXH_PT(etc, rxh) (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_PT_MASK) ++ ++#define RXH_CRC(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_CRC) : \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_CRC)) ++ ++#define RXH_OVF(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmgmacrxh_t *)(rxh))->flags) & GRXF_OVF) : \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_OV)) ++ ++#define RXH_RXER(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_RXER)) ++ ++#define RXH_NO(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ FALSE : (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & RXF_NO)) ++ ++/* Used for fa+ error determination */ ++#define RXH_CTFERROR(etc, rxh) (((etc)->coreid == GMAC_CORE_ID) ? \ ++ (ltoh16(((bcmenetrxh_t *)(rxh))->flags) & (GRXF_CTFERR | GRXF_CRC | GRXF_OVF)) : FALSE) ++ ++#ifdef CFG_GMAC ++#define ET_GMAC(etc) ((etc)->coreid == GMAC_CORE_ID) ++#else ++#define ET_GMAC(etc) (0) ++#endif /* CFG_GMAC */ ++ ++/* exported prototypes */ ++extern struct chops *etc_chipmatch(uint vendor, uint device); ++extern void *etc_attach(void *et, uint vendor, uint device, uint unit, void *dev, void *regsva); ++extern void etc_detach(etc_info_t *etc); ++extern void etc_reset(etc_info_t *etc); ++extern void etc_init(etc_info_t *etc, uint options); ++extern void etc_up(etc_info_t *etc); ++extern uint etc_down(etc_info_t *etc, int reset); ++extern int etc_ioctl(etc_info_t *etc, int cmd, void *arg); ++extern int etc_iovar(etc_info_t *etc, uint cmd, uint set, void *arg); ++extern void etc_promisc(etc_info_t *etc, uint on); ++extern void etc_qos(etc_info_t *etc, uint on); ++extern void etc_dump(etc_info_t *etc, struct bcmstrbuf *b); ++extern void etc_watchdog(etc_info_t *etc); ++extern uint etc_totlen(etc_info_t *etc, void *p); ++extern void etc_robomib(etc_info_t *etc); ++ ++#endif /* _etc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c +new file mode 100755 +index 0000000..eff478e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.c +@@ -0,0 +1,2567 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Gigabit Ethernet MAC (Unimac) core. ++ * This file implements the chip-specific routines for the GMAC core. ++ * ++ * $Id: etcgmac.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* for et_phyxx() routines */ ++#include ++#include ++#include ++#include ++ ++#ifdef ETROBO ++#include ++#endif /* ETROBO */ ++#ifdef GMAC3 ++#include /* GMAC3 */ ++#endif /* GMAC3 */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "mach/socregs_ing_open.h" ++#endif ++#if defined(CONFIG_MACH_KT2) ++#include "mach/socregs_ing_open.h" ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#include "bcmiproc_serdes.h" ++#include "bcmiproc_phy5461s.h" ++#endif ++#if defined(CONFIG_MACH_HR2) ++#include "bcmiproc_phy5221.h" ++#endif ++#if defined(CONFIG_MACH_NSP) ++#include ++#include "bcmiproc_robo_serdes.h" ++#endif ++ ++struct bcmgmac; /* forward declaration */ ++#define ch_t struct bcmgmac ++#include ++ ++extern int nvram_env_gmac_name(int gmac, char *name); ++ ++#ifdef ETROBO ++extern void robo_reset_mib(robo_info_t *robo); ++extern void robo_dump_mib(robo_info_t *robo); ++#endif ++ ++/* private chip state */ ++struct bcmgmac { ++ void *et; /* pointer to et private state */ ++ etc_info_t *etc; /* pointer to etc public state */ ++ ++ gmac_commonregs_t *regscomm; /* pointer to GMAC COMMON registers */ ++ gmacregs_t *regs; /* pointer to chip registers */ ++ osl_t *osh; /* os handle */ ++ ++ void *etphy; /* pointer to et for shared mdc/mdio contortion */ ++ ++ uint32 intstatus; /* saved interrupt condition bits */ ++ uint32 intmask; /* current software interrupt mask */ ++ uint32 def_intmask; /* default interrupt mask */ ++ ++ hnddma_t *di[NUMTXQ]; /* dma engine software state */ ++ ++ bool mibgood; /* true once mib registers have been cleared */ ++ gmacmib_t mib; /* mib statistic counters */ ++ si_t *sih; /* si utils handle */ ++ ++ char *vars; /* sprom name=value */ ++ uint vars_size; ++ ++ void *adm; /* optional admtek private data */ ++ mcfilter_t mf; /* multicast filter */ ++}; ++ ++/* local prototypes */ ++static bool chipid(uint vendor, uint device); ++static void *chipattach(etc_info_t *etc, void *osh, void *regsva); ++static void chipdetach(ch_t *ch); ++static void chipreset(ch_t *ch); ++static void chipinit(ch_t *ch, uint options); ++static bool chiptx(ch_t *ch, void *p); ++static void *chiprx(ch_t *ch); ++static void chiprxfill(ch_t *ch); ++static int chipgetintrevents(ch_t *ch, bool in_isr); ++static bool chiperrors(ch_t *ch); ++static void chipintrson(ch_t *ch); ++static void chipintrsoff(ch_t *ch); ++static void chiptxreclaim(ch_t *ch, bool all); ++static void chiprxreclaim(ch_t *ch); ++static void chipstatsupd(ch_t *ch); ++static void chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear); ++static void chipenablepme(ch_t *ch); ++static void chipdisablepme(ch_t *ch); ++static void chipphyreset(ch_t *ch, uint phyaddr); ++static uint16 chipphyrd(ch_t *ch, uint phyaddr, uint reg); ++static void chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v); ++static void chipdump(ch_t *ch, struct bcmstrbuf *b); ++static void chiplongname(ch_t *ch, char *buf, uint bufsize); ++static void chipduplexupd(ch_t *ch); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++static void chipforcespddpx(ch_t *ch); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++static void chipphyinit(ch_t *ch, uint phyaddr); ++static void chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v); ++static void chipphyforce(ch_t *ch, uint phyaddr); ++static void chipphyadvertise(ch_t *ch, uint phyaddr); ++static void chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable); ++static void chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b); ++static void gmac_mf_cleanup(ch_t *ch); ++static int gmac_speed(ch_t *ch, uint32 speed); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void gmac_serdes_init(ch_t *ch); ++#endif ++static void gmac_miiconfig(ch_t *ch); ++ ++struct chops bcmgmac_et_chops = { ++ chipid, ++ chipattach, ++ chipdetach, ++ chipreset, ++ chipinit, ++ chiptx, ++ chiprx, ++ chiprxfill, ++ chipgetintrevents, ++ chiperrors, ++ chipintrson, ++ chipintrsoff, ++ chiptxreclaim, ++ chiprxreclaim, ++ chipstatsupd, ++ chipdumpmib, ++ chipenablepme, ++ chipdisablepme, ++ chipphyreset, ++ chipphyrd, ++ chipphywr, ++ chipdump, ++ chiplongname, ++ chipduplexupd, ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++ chipforcespddpx, ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ chipphyenable ++}; ++ ++static uint devices[] = { ++ BCM47XX_GMAC_ID, ++ BCM4716_CHIP_ID, ++ BCM4748_CHIP_ID, ++ BCM53010_CHIP_ID, ++ BCM56150_CHIP_ID, ++ BCM56340_CHIP_ID, ++ BCM53020_CHIP_ID, ++ BCM56450_CHIP_ID, ++ 0x0000 ++}; ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void *wrapaddr = 0; ++void gmac_set_amac_mdio(int en) ++{ ++ u32 tmp; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL; ++ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL; ++#else ++ u32 mdio_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL; ++ u32 ctrl_sel= IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL; ++#endif ++ u32 iproc_mdio_sel= IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL; ++ ++ if (en) { ++ /* Get register base address */ ++ wrapaddr = ioremap(IPROC_WRAP_MISC_CONTROL, 0x10); ++ //printf("%s IPROC_WRAP_MISC_CONTROL(0x%x) remaps to 0x%x\n", __FUNCTION__, IPROC_WRAP_MISC_CONTROL, (u32)wrapaddr); ++ } ++ ++ tmp = ioread32(wrapaddr); ++ //printf("%s read (0x%x) from IPROC_WRAP_MISC_CONTROL(0x%x)\n", __FUNCTION__, tmp, (u32)wrapaddr); ++ if (en) { ++ /* set bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL, ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL & ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL ++ so AMAC can access the Serdes and Phy */ ++ tmp |= ((1 << mdio_sel) | (1 << ctrl_sel) | (1 << iproc_mdio_sel)); ++ } else { ++ /* clear bits IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL & ++ IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL ++ so CMIC can access the Serdes and Phy */ ++ tmp &= ~((1 << mdio_sel) | (1 << iproc_mdio_sel)); ++ } ++ //printf("%s write 0x%x to IPROC_WRAP_MISC_CONTROL(0x%x)\n", __FUNCTION__, tmp, (u32)wrapaddr); ++ iowrite32(tmp, wrapaddr); ++ ++ if (!en) { ++ /* unmap register base address */ ++ //printf("%s unmap(0x%x)\n", __FUNCTION__, (u32)wrapaddr); ++ iounmap(wrapaddr); ++ wrapaddr=0; ++ } ++} ++ ++ ++int gmac_has_mdio_access(void) ++{ ++ u32 tmp; ++ u32 regmsk = (1 << IPROC_WRAP_MISC_CONTROL__IPROC_MDIO_SEL); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_MDIO_SEL) | ++ (1 << IPROC_WRAP_MISC_CONTROL__QUAD_SERDES_CTRL_SEL)); ++#else ++ regmsk |= ((1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_MDIO_SEL) | ++ (1 << IPROC_WRAP_MISC_CONTROL__UNICORE_SERDES_CTRL_SEL)); ++#endif ++ ++ if (wrapaddr==0) { ++ /* if no wrapaddr then no access */ ++ return 0; ++ } ++ ++ tmp = ioread32(wrapaddr); ++ tmp &= ~regmsk; ++ if (tmp == regmsk) { ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/* This api will determine if this unit specified is the last interface. */ ++bool gmac_last_interface(int unit) ++{ ++ char name[128]; ++ int idx; ++ ++ /* if interface 2 or greater then must be last */ ++ if (unit>=2) ++ return true; ++ ++ /* Look to see if there is a next interface specified */ ++ for (idx=unit+1; idx<=2; idx++) { ++ nvram_env_gmac_name(idx, name); ++ if (getvar(NULL, name) != NULL) { ++ /* there is a next interface */ ++ return false; ++ } ++ } ++ /* no other interfaces */ ++ return true; ++} ++ ++ ++static bool ++chipid(uint vendor, uint device) ++{ ++ int i; ++ ++ if (vendor != VENDOR_BROADCOM) { ++ ET_ERROR(("%s ERROR: NOT a BROADCOM Vendor ID (0x%x)\n", __FUNCTION__, vendor)); ++ return (FALSE); ++ } ++ ++ for (i = 0; devices[i]; i++) { ++ if (device == devices[i]) ++ return (TRUE); ++ } ++ ++ ET_ERROR(("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device)); ++ printk("%s ERROR: UNKNOWN Device ID (0x%x)\n", __FUNCTION__, device); ++ return (FALSE); ++} ++ ++static void * ++chipattach(etc_info_t *etc, void *osh, void *regsva) ++{ ++ ch_t *ch; ++ gmacregs_t *regs; ++ uint i; ++ char name[16]; ++ char *var; ++ uint boardflags, boardtype; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ uint reset; ++#endif ++#ifdef ETROBO ++ char *pet; ++ int initsw=0; ++#endif ++ ++ ET_TRACE(("et%d: chipattach: regsva 0x%lx\n", etc->unit, (ulong)regsva)); ++ ++ if ((ch = (ch_t *)MALLOC(osh, sizeof(ch_t))) == NULL) { ++ ET_ERROR(("et%d: chipattach: out of memory, malloced %d bytes\n", etc->unit, ++ MALLOCED(osh))); ++ return (NULL); ++ } ++ bzero((char *)ch, sizeof(ch_t)); ++ ++ ch->etc = etc; ++ ch->et = etc->et; ++ ch->osh = osh; ++ ++ /* store the pointer to the sw mib */ ++ etc->mib = (void *)&ch->mib; ++ ++ /* get si handle */ ++ if ((ch->sih = si_attach(etc->deviceid, ch->osh, regsva, PCI_BUS, NULL, &ch->vars, ++ &ch->vars_size)) == NULL) { ++ ET_ERROR(("et%d: chipattach: si_attach error\n", etc->unit)); ++ goto fail; ++ } ++ ++ if ((etc->corerev = si_corerev(ch->sih)) == GMAC_4706B0_CORE_REV && ++ (ch->regscomm = (gmac_commonregs_t *)si_setcore(ch->sih, ++ GMAC_COMMON_4706_CORE_ID, 0)) == NULL) { ++ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC common\n", etc->unit)); ++ goto fail; ++ } ++ ++ if ((regs = (gmacregs_t *)si_setcore(ch->sih, GMAC_CORE_ID, etc->unit)) == NULL) { ++ ET_ERROR(("et%d: chipattach: Could not setcore to GMAC\n", etc->unit)); ++ goto fail; ++ } ++ ++ ch->regs = regs; ++ etc->chip = ch->sih->chip; ++ etc->chiprev = ch->sih->chiprev; ++ etc->coreid = si_coreid(ch->sih); ++ etc->nicmode = !(ch->sih->bustype == SI_BUS); ++ etc->coreunit = si_coreunit(ch->sih); ++#ifdef GMAC3 ++ etc->gmac_fwd = FALSE; /* GMAC3 */ ++#endif /* GMAC3 */ ++ etc->boardflags = getintvar(ch->vars, "boardflags"); ++ ++ boardflags = etc->boardflags; ++ boardtype = ch->sih->boardtype; ++ ++#ifdef PKTC ++ etc->pktc = (getintvar(ch->vars, "pktc_disable") == 0); ++#endif ++ ++ /* get our local ether addr */ ++ nvram_env_gmac_name(etc->coreunit, name); ++ var = getvar(ch->vars, name); ++ if (var == NULL) { ++ ET_ERROR(("et%d: chipattach: getvar(%s) not found\n", etc->unit, name)); ++ goto fail; ++ } ++ bcm_ether_atoe(var, &etc->perm_etheraddr); ++ ++#ifdef GMAC3 ++ /* ++ * Select GMAC mode of operation: ++ * If a valid MAC address is present, it operates as an Ethernet Network ++ * interface, otherwise it operates as a forwarding GMAC interface. ++ */ ++ //if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) ++ if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { ++ etc->gmac_fwd = TRUE; ++ printk("%s GMAC forward enabled\n", __FUNCTION__); ++ } ++#else /* !GMAC3 */ ++ if (ETHER_ISNULLADDR(&etc->perm_etheraddr)) { ++ ET_ERROR(("et%d: chipattach: invalid format: %s=%s\n", etc->unit, name, var)); ++ goto fail; ++ } ++#endif /* !GMAC3 */ ++ ++ bcopy((char *)&etc->perm_etheraddr, (char *)&etc->cur_etheraddr, ETHER_ADDR_LEN); ++ ++ ++ /* ++ * Too much can go wrong in scanning MDC/MDIO playing "whos my phy?" . ++ * Instead, explicitly require the environment var "etphyaddr=". ++ */ ++ ++ /* get our phyaddr value */ ++ sprintf(name, "et%dphyaddr", etc->coreunit); ++ var = getvar(NULL, name); ++ if (var == NULL) { ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ etc->phyaddr = EPHY_NOREG; ++#else ++ etc->phyaddr = etc->unit+1; ++#endif ++ ET_ERROR(("et%d: chipattach: getvar(%s) not found set to %d\n", etc->unit, name, etc->phyaddr)); ++ } else { ++ etc->phyaddr = bcm_atoi(var) & EPHY_MASK; ++ } ++ printf("et%d: chipattach: phyaddr(0x%x)\n", etc->unit, etc->phyaddr); ++ ++ /* nvram says no phy is present */ ++ if (etc->phyaddr == EPHY_NONE) { ++ ET_ERROR(("et%d: chipattach: phy not present\n", etc->unit)); ++ goto fail; ++ } ++ ++ /* reset the gmac core */ ++ chipreset(ch); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (wrapaddr == 0) { ++ /* flip switch so AMAC can access serdes */ ++ gmac_set_amac_mdio(1); ++ } ++ ++ if (etc->unit == 0) { ++ void *amacidmaddr; ++ uint32 tmp; ++ ++ /* Get register base address */ ++ amacidmaddr = ioremap(AMAC_IDM0_IO_CONTROL_DIRECT, 0x10); ++ tmp = ioread32(amacidmaddr); ++ ++ //printf("%s read AMAC_IDM0_IO_CONTROL_DIRECT: 0x%x\n", __FUNCTION__, tmp); ++ tmp &= ~(1<unit == 1) { ++ void *amacidmaddr; ++ uint32 tmp; ++ ++ /* Get register base address */ ++ amacidmaddr = ioremap(AMAC_IDM1_IO_CONTROL_DIRECT, 0x10); ++ tmp = ioread32(amacidmaddr); ++ ++ //printf("%s read AMAC_IDM1_IO_CONTROL_DIRECT: 0x%x\n", __FUNCTION__, tmp); ++ tmp &= ~(1<=1000) { ++ printf("%s ERROR: PLL failed to lock\n", __FUNCTION__); ++ } ++ /* CRU_LCPLL2_CONTROL0 post_resetb=1 */ ++ tmp = ioread32(lcplladdr); ++ tmp |= (1<coreunit); ++ ++ /* allocate dma resources for txqs */ ++ /* TX: TC_BK, RX: RX_Q0 */ ++ ch->di[0] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q0), ++ DMAREG(ch, DMA_RX, RX_Q0), ++ NTXD, NRXD, RXBUFSZ, -1, NRXBUFPOST, HWRXOFF, ++ &et_msg_level); ++ ++#if defined(CONFIG_MACH_NS) ++ /* TX: TC_BE, RX: UNUSED */ ++ ch->di[1] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q1), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++ ++ /* TX: TC_CL, RX: UNUSED */ ++ ch->di[2] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q2), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++ ++ /* TX: TC_VO, RX: UNUSED */ ++ ch->di[3] = dma_attach(osh, name, ch->sih, ++ DMAREG(ch, DMA_TX, TX_Q3), ++ NULL /* rxq unused */, ++ NTXD, 0, 0, -1, 0, 0, &et_msg_level); ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] == NULL) { ++ ET_ERROR(("et%d: chipattach: dma_attach failed\n", etc->unit)); ++ goto fail; ++ } ++ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] != NULL) ++ etc->txavail[i] = (uint *)&ch->di[i]->txavail; ++ ++ /* set default sofware intmask */ ++ sprintf(name, "et%d_no_txint", etc->coreunit); ++ if (getintvar(ch->vars, name)) { ++ /* if no_txint variable is non-zero we disable tx interrupts. ++ * we do the tx buffer reclaim once every few frames. ++ */ ++ ch->def_intmask = (DEF_INTMASK & ~(I_XI0 | I_XI1 | I_XI2 | I_XI3)); ++ etc->txrec_thresh = (((NTXD >> 2) > TXREC_THR) ? TXREC_THR - 1 : 1); ++ } else ++ ch->def_intmask = DEF_INTMASK; ++ ++ ch->intmask = ch->def_intmask; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ /* reset the external phy */ ++ if ((reset = getgpiopin(ch->vars, "ephy_reset", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ reset = 1 << reset; ++ ++ /* Keep RESET low for 2 us */ ++ si_gpioout(ch->sih, reset, 0, GPIO_DRV_PRIORITY); ++ si_gpioouten(ch->sih, reset, reset, GPIO_DRV_PRIORITY); ++ OSL_DELAY(2); ++ ++ /* Keep RESET high for at least 2 us */ ++ si_gpioout(ch->sih, reset, reset, GPIO_DRV_PRIORITY); ++ OSL_DELAY(2); ++ ++ /* if external phy is present enable auto-negotation and ++ * advertise full capabilities as default config. ++ */ ++ ASSERT(etc->phyaddr != EPHY_NOREG); ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ etc->advertise2 = ADV_1000FULL; ++ } ++#endif ++ ++ /* reset phy: reset it once now */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (ch->etc->unit == 0) { ++ serdes_reset_core(ch->etc->unit, etc->phyaddr); ++ } ++#endif ++ ++ chipphyreset(ch, etc->phyaddr); ++ ++#ifdef ETROBO ++ /* ++ * Broadcom Robo ethernet switch. ++ */ ++ pet = getvar(NULL, "swgmacet"); ++ sprintf(name, "et%d", etc->coreunit); ++ if (pet) { ++ if (bcmp(pet, name, strlen(pet)) == 0) ++ initsw = 1; ++ } ++ ++ if ((boardflags & BFL_ENETROBO) && initsw) { ++ ET_TRACE(("et%d: chipattach: Calling robo attach\n", etc->unit)); ++ printk("et%d: chipattach: Calling robo attach\n", etc->unit); ++ ++ /* Attach to the switch */ ++ if (!(etc->robo = bcm_robo_attach(ch->sih, ch, ch->vars, ++ (miird_f)bcmgmac_et_chops.phyrd, ++ (miiwr_f)bcmgmac_et_chops.phywr))) { ++ ET_ERROR(("et%d: chipattach: robo_attach failed\n", etc->unit)); ++ goto fail; ++ } ++ if (etc->switch_mode) { ++ printf("et%d: %s: bringing up robo switch\n", ch->etc->unit, __FUNCTION__); ++ /* Enable the switch and set it to a known good state */ ++ if (bcm_robo_enable_device(etc->robo)) { ++ ET_ERROR(("et%d: chipattach: robo_enable_device failed\n", etc->unit)); ++ goto fail; ++ } ++ /* Configure the switch to do VLAN */ ++ if ((boardflags & BFL_ENETVLAN) && ++ bcm_robo_config_vlan(etc->robo, etc->perm_etheraddr.octet)) { ++ ET_ERROR(("et%d: chipattach: robo_config_vlan failed\n", etc->unit)); ++ goto fail; ++ } ++ /* Enable switching/forwarding */ ++ if (bcm_robo_enable_switch(etc->robo)) { ++ ET_ERROR(("et%d: chipattach: robo_enable_switch failed\n", etc->unit)); ++ goto fail; ++ } ++ robo_reset_mib(etc->robo); ++ } ++ } ++#endif /* ETROBO */ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ if (gmac_last_interface(etc->unit)) { ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(etc->unit, 3); ++ serdes_start_pll(etc->unit, 1); ++ } ++ ++ if (etc->forcespeed == ET_AUTO) { ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ etc->advertise2 = ADV_1000FULL; ++ } ++#endif ++#if defined(CONFIG_MACH_HR2) ++ if (etc->forcespeed == ET_AUTO) { ++ etc->needautoneg = TRUE; ++ etc->advertise = (ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ } ++#endif ++ return ((void *) ch); ++ ++fail: ++ chipdetach(ch); ++ return (NULL); ++} ++ ++static void ++chipdetach(ch_t *ch) ++{ ++ int32 i; ++ ++ ET_TRACE(("et%d: chipdetach\n", ch->etc->unit)); ++ ++ if (ch == NULL) ++ return; ++ ++#ifdef ETROBO ++ /* free robo state */ ++ if (ch->etc->robo) ++ bcm_robo_detach(ch->etc->robo); ++#endif /* ETROBO */ ++ ++ /* free dma state */ ++ for (i = 0; i < NUMTXQ; i++) ++ if (ch->di[i] != NULL) { ++ dma_detach(ch->di[i]); ++ ch->di[i] = NULL; ++ } ++ ++ /* put the core back into reset */ ++ if (ch->sih) ++ si_core_disable(ch->sih, 0); ++ ++ if (ch->etc) ++ if (ch->etc->mib) ++ ch->etc->mib = NULL; ++ ++ /* free si handle */ ++ if (ch->sih) { ++ si_detach(ch->sih); ++ ch->sih = NULL; ++ } ++ ++ /* free vars */ ++ if (ch->vars) ++ MFREE(ch->osh, ch->vars, ch->vars_size); ++ ++ /* free chip private state */ ++ MFREE(ch->osh, ch, sizeof(ch_t)); ++} ++ ++static void ++chiplongname(ch_t *ch, char *buf, uint bufsize) ++{ ++ char *s; ++ ++ switch (ch->etc->deviceid) { ++ case BCM53010_CHIP_ID: ++ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM53020_CHIP_ID: ++ s = "Broadcom BCM5302x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM56150_CHIP_ID: ++ s = "Broadcom BCM5615x 10/100 Mbps Ethernet Controller"; ++ break; ++ case BCM56340_CHIP_ID: ++ s = "Broadcom BCM5634x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM56450_CHIP_ID: ++ s = "Broadcom BCM5645x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ case BCM47XX_GMAC_ID: ++ case BCM4716_CHIP_ID: ++ case BCM4748_CHIP_ID: ++ default: ++ s = "Broadcom BCM5301x 10/100/1000 Mbps Ethernet Controller"; ++ break; ++ } ++ ++ strncpy(buf, s, bufsize); ++ buf[bufsize - 1] = '\0'; ++} ++ ++#ifdef ETROBO ++extern void robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b); ++#endif ++ ++static void ++chipdump(ch_t *ch, struct bcmstrbuf *b) ++{ ++ /* int32 i; */ ++ ++ bcm_bprintf(b, "regs 0x%lx etphy 0x%lx ch->intstatus 0x%x intmask 0x%x\n", ++ (ulong)ch->regs, (ulong)ch->etphy, ch->intstatus, ch->intmask); ++ bcm_bprintf(b, "\n"); ++ ++ ++ /* registers */ ++ chipdumpregs(ch, ch->regs, b); ++ bcm_bprintf(b, "\n"); ++ ++ /* switch registers */ ++#ifdef ETROBO ++ if (ch->etc->robo) { ++ robo_dump_regs(ch->etc->robo, b); ++ robo_bprintf_mib(ch->etc->robo, b); ++ } ++ ++#endif /* ETROBO */ ++} ++ ++ ++#define PRREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->name)) ++#define PRMIBREG(name) bcm_bprintf(b, #name " 0x%x ", R_REG(ch->osh, ®s->mib.name)) ++ ++static void ++chipdumpregs(ch_t *ch, gmacregs_t *regs, struct bcmstrbuf *b) ++{ ++ uint phyaddr; ++ ++ phyaddr = ch->etc->phyaddr; ++ ++ PRREG(devcontrol); PRREG(devstatus); ++ bcm_bprintf(b, "\n"); ++ PRREG(biststatus); ++ bcm_bprintf(b, "\n"); ++ PRREG(intstatus); PRREG(intmask); PRREG(gptimer); ++ bcm_bprintf(b, "\n"); ++ PRREG(intrecvlazy); ++ bcm_bprintf(b, "\n"); ++ PRREG(flowctlthresh); PRREG(wrrthresh); PRREG(gmac_idle_cnt_thresh); ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRREG(phyaccess); PRREG(phycontrol); ++ bcm_bprintf(b, "\n"); ++ } ++ PRREG(txqctl); PRREG(rxqctl); ++ bcm_bprintf(b, "\n"); ++ PRREG(gpioselect); PRREG(gpio_output_en); ++ bcm_bprintf(b, "\n"); ++ PRREG(clk_ctl_st); PRREG(pwrctl); ++ bcm_bprintf(b, "\n"); ++ ++ /* unimac registers */ ++ PRREG(hdbkpctl); ++ bcm_bprintf(b, "\n"); ++ PRREG(cmdcfg); ++ bcm_bprintf(b, "\n"); ++ PRREG(macaddrhigh); PRREG(macaddrlow); ++ bcm_bprintf(b, "\n"); ++ PRREG(rxmaxlength); PRREG(pausequanta); PRREG(macmode); ++ bcm_bprintf(b, "\n"); ++ PRREG(outertag); PRREG(innertag); PRREG(txipg); PRREG(pausectl); ++ bcm_bprintf(b, "\n"); ++ PRREG(txflush); PRREG(rxstatus); PRREG(txstatus); ++ bcm_bprintf(b, "\n"); ++ ++ /* mib registers */ ++ PRMIBREG(tx_good_octets); PRMIBREG(tx_good_pkts); PRMIBREG(tx_octets); PRMIBREG(tx_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_broadcast_pkts); PRMIBREG(tx_multicast_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_jabber_pkts); PRMIBREG(tx_oversize_pkts); PRMIBREG(tx_fragment_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_underruns); PRMIBREG(tx_total_cols); PRMIBREG(tx_single_cols); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(tx_multiple_cols); PRMIBREG(tx_excessive_cols); PRMIBREG(tx_late_cols); ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(tx_defered); PRMIBREG(tx_carrier_lost); PRMIBREG(tx_pause_pkts); ++ bcm_bprintf(b, "\n"); ++ } ++ ++ PRMIBREG(rx_good_octets); PRMIBREG(rx_good_pkts); PRMIBREG(rx_octets); PRMIBREG(rx_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_broadcast_pkts); PRMIBREG(rx_multicast_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_jabber_pkts); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(rx_oversize_pkts); PRMIBREG(rx_fragment_pkts); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_missed_pkts); PRMIBREG(rx_crc_align_errs); PRMIBREG(rx_undersize); ++ } ++ bcm_bprintf(b, "\n"); ++ if (ch->etc->corerev != GMAC_4706B0_CORE_REV) { ++ PRMIBREG(rx_crc_errs); PRMIBREG(rx_align_errs); PRMIBREG(rx_symbol_errs); ++ bcm_bprintf(b, "\n"); ++ PRMIBREG(rx_pause_pkts); PRMIBREG(rx_nonpause_pkts); ++ bcm_bprintf(b, "\n"); ++ } ++ if (phyaddr != EPHY_NOREG) { ++ /* print a few interesting phy registers */ ++ bcm_bprintf(b, "phy0 0x%x phy1 0x%x phy2 0x%x phy3 0x%x\n", ++ chipphyrd(ch, phyaddr, 0), ++ chipphyrd(ch, phyaddr, 1), ++ chipphyrd(ch, phyaddr, 2), ++ chipphyrd(ch, phyaddr, 3)); ++ bcm_bprintf(b, "phy4 0x%x phy5 0x%x phy24 0x%x phy25 0x%x\n", ++ chipphyrd(ch, phyaddr, 4), ++ chipphyrd(ch, phyaddr, 5), ++ chipphyrd(ch, phyaddr, 24), ++ chipphyrd(ch, phyaddr, 25)); ++ } ++ ++} ++ ++static void ++gmac_clearmib(ch_t *ch) ++{ ++ volatile uint32 *ptr; ++ ++ if (ch->etc->corerev == GMAC_4706B0_CORE_REV) ++ return; ++ ++ /* enable clear on read */ ++ OR_REG(ch->osh, &ch->regs->devcontrol, DC_MROR); ++ ++ for (ptr = &ch->regs->mib.tx_good_octets; ptr <= &ch->regs->mib.rx_uni_pkts; ptr++) { ++ (void)R_REG(ch->osh, ptr); ++ if (ptr == &ch->regs->mib.tx_q3_octets_high) ++ ptr++; ++ } ++ ++ return; ++} ++ ++static void ++gmac_init_reset(ch_t *ch) ++{ ++ OR_REG(ch->osh, &ch->regs->cmdcfg, CC_SR); ++ OSL_DELAY(GMAC_RESET_DELAY); ++} ++ ++static void ++gmac_clear_reset(ch_t *ch) ++{ ++ AND_REG(ch->osh, &ch->regs->cmdcfg, ~CC_SR); ++ OSL_DELAY(GMAC_RESET_DELAY); ++} ++ ++static void ++gmac_reset(ch_t *ch) ++{ ++ uint32 ocmdcfg, cmdcfg; ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* initialize default config */ ++ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | ++ CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | CC_PAD_EN | CC_PF); ++ cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= (CC_AE | CC_OT | CC_OR); ++#endif ++ ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ cmdcfg |= 0xc; ++#endif ++ ++ if (cmdcfg != ocmdcfg) ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static void ++gmac_promisc(ch_t *ch, bool mode) ++{ ++ uint32 cmdcfg; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* enable or disable promiscuous mode */ ++ if (mode) ++ cmdcfg |= CC_PROM; ++ else ++ cmdcfg &= ~CC_PROM; ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static int ++gmac_speed(ch_t *ch, uint32 speed) ++{ ++ uint32 cmdcfg; ++ uint32 hd_ena = 0; ++ ++ switch (speed) { ++ case ET_10HALF: ++ hd_ena = CC_HD; ++ /* FALLTHRU */ ++ ++ case ET_10FULL: ++ speed = 0; ++ break; ++ ++ case ET_100HALF: ++ hd_ena = CC_HD; ++ /* FALLTHRU */ ++ ++ case ET_100FULL: ++ speed = 1; ++ break; ++ ++ case ET_1000FULL: ++ speed = 2; ++ break; ++ ++ case ET_1000HALF: ++ ET_ERROR(("et%d: gmac_speed: supports 1000 mbps full duplex only\n", ++ ch->etc->unit)); ++ return (FAILURE); ++ ++ case ET_2500FULL: ++ speed = 3; ++ break; ++ ++ default: ++ ET_ERROR(("et%d: gmac_speed: speed %d not supported\n", ++ ch->etc->unit, speed)); ++ return (FAILURE); ++ } ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* set the speed */ ++ cmdcfg &= ~(CC_ES_MASK | CC_HD); ++ cmdcfg |= ((speed << CC_ES_SHIFT) | hd_ena); ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= CC_AE; ++#endif ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ return (SUCCESS); ++} ++ ++static void ++gmac_macloopback(ch_t *ch, bool on) ++{ ++ uint32 ocmdcfg, cmdcfg; ++ ++ ocmdcfg = cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* set/clear the mac loopback mode */ ++ if (on) ++ cmdcfg |= CC_ML; ++ else ++ cmdcfg &= ~CC_ML; ++ ++ if (cmdcfg != ocmdcfg) ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++static int ++gmac_loopback(ch_t *ch, uint32 mode) ++{ ++ switch (mode) { ++ case LOOPBACK_MODE_DMA: ++ /* to enable loopback for any channel set the loopback ++ * enable bit in xmt0control register. ++ */ ++ dma_fifoloopbackenable(ch->di[TX_Q0]); ++ break; ++ ++ case LOOPBACK_MODE_MAC: ++ gmac_macloopback(ch, TRUE); ++ break; ++ ++ case LOOPBACK_MODE_NONE: ++ gmac_macloopback(ch, FALSE); ++ break; ++ ++ default: ++ ET_ERROR(("et%d: gmac_loopaback: Unknown loopback mode %d\n", ++ ch->etc->unit, mode)); ++ return (FAILURE); ++ } ++ ++ return (SUCCESS); ++} ++ ++static void ++gmac_enable(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ gmacregs_t *regs; ++ ++ regs = ch->regs; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ cmdcfg |= CC_SR; ++ ++ /* first deassert rx_ena and tx_ena while in reset */ ++ cmdcfg &= ~(CC_RE | CC_TE); ++ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ /* enable the mac transmit and receive paths now */ ++ OSL_DELAY(2); ++ cmdcfg &= ~CC_SR; ++ cmdcfg |= (CC_RE | CC_TE); ++ ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++/* #if 1 */ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ cmdcfg |= 0xc; ++#endif ++ ++ /* assert rx_ena and tx_ena when out of reset to enable the mac */ ++ W_REG(ch->osh, ®s->cmdcfg, cmdcfg); ++ ++ /* request ht clock */ ++ OR_REG(ch->osh, ®s->clk_ctl_st, CS_FH); ++ ++ return; ++} ++ ++static void ++gmac_txflowcontrol(ch_t *ch, bool on) ++{ ++ uint32 cmdcfg; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* put the mac in reset */ ++ gmac_init_reset(ch); ++ ++ /* to enable tx flow control clear the rx pause ignore bit */ ++ if (on) ++ cmdcfg &= ~CC_RPI; ++ else ++ cmdcfg |= CC_RPI; ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++static void ++gmac_serdes_init(ch_t *ch) ++{ ++ uint32_t sdctl, sdstat0, sdstat1; ++ gmacregs_t *regs; ++ ++ regs = ch->regs; ++ ++ ET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); ++ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); ++ //printf("et%d: %s read sdstat0(0x%x); sdstat1(0x%x)\n", ch->etc->unit, __FUNCTION__, sdstat0, sdstat1); ++ ++ /* ++ * Bring up both digital and analog clocks ++ * ++ * NOTE: Many MAC registers are not accessible until the PLL is locked. ++ * An S-Channel timeout will occur before that. ++ */ ++ ++ sdctl = 0; ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ sdctl |= (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL|SC_REFSEL_VAL|SC_REF_TERM_SEL_MASK); ++#else ++ sdctl |= (SC_TX1G_FIFO_RST_VAL|SC_FORCE_SPD_STRAP_VAL|SC_REF_TERM_SEL_MASK); ++#endif /* (defined(CONFIG_MACH_HX4) */ ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_IDDQ_MASK|SC_PWR_DOWN_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl &= ~(SC_IDDQ_MASK|SC_PWR_DOWN_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ /* Bring hardware out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_HW_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ /* Bring MDIOREGS out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_MDIOREGS_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ /* Bring PLL out of reset */ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdctl |= (SC_RSTB_PLL_MASK); ++ //printf("et%d: %s write sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ W_REG(ch->osh, &ch->regs->serdes_ctl, sdctl); ++ ++ udelay(1000); ++ ++ sdctl = R_REG(ch->osh, &ch->regs->serdes_ctl); ++ //printf("et%d: %s read sdctl(0x%x)\n", ch->etc->unit, __FUNCTION__, sdctl); ++ sdstat0 = R_REG(ch->osh, &ch->regs->serdes_status0); ++ sdstat1 = R_REG(ch->osh, &ch->regs->serdes_status1); ++ //printf("et%d: %s read sdstat0(0x%x); sdstat1(0x%x)\n", ch->etc->unit, __FUNCTION__, sdstat0, sdstat1); ++ ++ return; ++} ++#endif ++ ++static void ++gmac_miiconfig(ch_t *ch) ++{ ++ /* BCM53010 GMAC DevStatus register has different definition of "Interface Mode" ++ * Bit 12:8 "interface_mode" This field is programmed through IDM control bits [6:2] ++ * ++ * Bit 0 : SOURCE_SYNC_MODE_EN - If set, Rx line clock input will be used by Unimac for ++ * sampling data.If this is reset, PLL reference clock (Clock 250 or Clk 125 based ++ * on CLK_250_SEL) will be used as receive side line clock. ++ * Bit 1 : DEST_SYNC_MODE_EN - If this is reset, PLL reference clock input (Clock 250 or ++ * Clk 125 based on CLK_250_SEL) will be used as transmit line clock. ++ * If this is set, TX line clock input (from external switch/PHY) is used as ++ * transmit line clock. ++ * Bit 2 : TX_CLK_OUT_INVERT_EN - If set, this will invert the TX clock out of AMAC. ++ * Bit 3 : DIRECT_GMII_MODE - If direct gmii is set to 0, then only 25 MHz clock needs to ++ * be fed at 25MHz reference clock input, for both 10/100 Mbps speeds. ++ * Unimac will internally divide the clock to 2.5 MHz for 10 Mbps speed ++ * Bit 4 : CLK_250_SEL - When set, this selects 250Mhz reference clock input and hence ++ * Unimac line rate will be 2G. ++ * If reset, this selects 125MHz reference clock input. ++ */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ if (ch->etc->forcespeed == ET_AUTO) ++#if defined(CONFIG_MACH_HR2) ++ gmac_speed(ch, ET_100FULL); ++#elif (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ /*2G_ENABLED: Enable Unimac at 2G mode */ ++ gmac_speed(ch, ET_2500FULL); ++#else ++ gmac_speed(ch, ET_1000FULL); ++#endif ++ else ++ gmac_speed(ch, ch->etc->forcespeed); ++ } ++} ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++void ++gmac_serdes_asym_mode(etc_info_t *etcptrs[]) ++{ ++ etc_info_t *etc; ++ ++ etc = etcptrs[0]; ++ ++ /* initialize serdes */ ++ gmac_serdes_init(etc->ch); ++ serdes_reset_core(etc->unit, etc->phyaddr); ++ ++ /* initialize lane 0 */ ++ //printk("et%d %s() phyaddr=%d, speed=%d, dpx=%d\n", etc->unit, __FUNCTION__, etc->phyaddr, etc->speed, etc->duplex); ++ serdes_set_asym_mode(etc->unit, etc->phyaddr); ++ serdes_init(etc->unit, etc->phyaddr); ++ serdes_speeddpx_set(etc->unit, etc->phyaddr, etc->speed, etc->duplex); ++ /* initialize lane 1 */ ++ etc = etcptrs[1]; ++ if (etc->linkstate) { ++ //printk("et%d %s() phyaddr=%d, speed=%d, dpx=%d\n", etc->unit, __FUNCTION__, etc->phyaddr, etc->speed, etc->duplex); ++ serdes_set_asym_mode(etc->unit, etc->phyaddr); ++ serdes_init(etc->unit, etc->phyaddr); ++ serdes_speeddpx_set(etc->unit, etc->phyaddr, etc->speed, etc->duplex); ++ } ++ ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(etc->unit, 3); ++ ++ /* start PLL */ ++ serdes_start_pll(etc->unit, 1); ++} ++#endif /* (!defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++static void ++chipreset(ch_t *ch) ++{ ++ gmacregs_t *regs; ++ uint32 i, sflags, flagbits = 0; ++ ++ ET_TRACE(("et%d: chipreset\n", ch->etc->unit)); ++ ++ regs = ch->regs; ++ ++ if (!si_iscoreup(ch->sih)) { ++ /* power on reset: reset the enet core */ ++ goto chipinreset; ++ } ++ ++ /* Northstar, reset other three GMAC cores if needed */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ int ns_gmac; ++ for (ns_gmac = 0; ns_gmac < IPROC_NUM_GMACS; ns_gmac++) { ++ /* As northstar requirement, we have to reset all GAMCs before accessing them. ++ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. ++ * then the other three GAMC didn't reset. ++ * We do it here. ++ */ ++ si_setcore(ch->sih, GMAC_CORE_ID, ns_gmac); ++ if (!si_iscoreup(ch->sih)) { ++ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, ns_gmac)); ++ si_core_reset(ch->sih, flagbits, 0); ++ } ++ } ++ si_setcore(ch->sih, GMAC_CORE_ID, 0); ++ } ++ ++ /* update software counters before resetting the chip */ ++ if (ch->mibgood) ++ chipstatsupd(ch); ++ ++ /* reset the tx dma engines */ ++ for (i = 0; i < NUMTXQ; i++) { ++ if (ch->di[i]) { ++ ET_TRACE(("et%d: resetting tx dma%d\n", ch->etc->unit, i)); ++ dma_txreset(ch->di[i]); ++ } ++ } ++ ++ /* set gmac into loopback mode to ensure no rx traffic */ ++ gmac_loopback(ch, LOOPBACK_MODE_MAC); ++ OSL_DELAY(1); ++ ++ /* reset the rx dma engine */ ++ if (ch->di[RX_Q0]) { ++ ET_TRACE(("et%d: resetting rx dma\n", ch->etc->unit)); ++ dma_rxreset(ch->di[RX_Q0]); ++ } ++ ++ /* clear the multicast filter table */ ++ gmac_mf_cleanup(ch); ++ ++chipinreset: ++ sflags = si_core_sflags(ch->sih, 0, 0); ++ if (sflags & SISF_SW_ATTACHED) { ++ ET_TRACE(("et%d: internal switch attached\n", ch->etc->unit)); ++ flagbits = SICF_SWCLKE; ++ if (!ch->etc->robo) { ++ ET_TRACE(("et%d: reseting switch\n", ch->etc->unit)); ++ flagbits |= SICF_SWRST; ++ } ++ } ++ ++ /* reset all GMAC cores */ ++ if (IS_IPROC_CHIP_ID(CHIPID(ch->sih->chip))) { ++ int ns_gmac; ++ for (ns_gmac = 0; ns_gmac < IPROC_NUM_GMACS; ns_gmac++) { ++ /* As northstar requirement, we have to reset all GAMCs before accessing them. ++ * et_probe() call pci_enable_device() for etx and do si_core_reset for GAMCx only. ++ * then the other three GAMC didn't reset. ++ * We do it here. ++ */ ++ si_setcore(ch->sih, GMAC_CORE_ID, ns_gmac); ++ if (!si_iscoreup(ch->sih)) { ++ ET_TRACE(("et%d: reset NorthStar GMAC[%d] core\n", ch->etc->unit, ns_gmac)); ++ si_core_reset(ch->sih, flagbits, 0); ++ } ++ } ++ si_setcore(ch->sih, GMAC_CORE_ID, 0); ++ } ++ ++ if ((sflags & SISF_SW_ATTACHED) && (!ch->etc->robo)) { ++ ET_TRACE(("et%d: taking switch out of reset\n", ch->etc->unit)); ++ si_core_cflags(ch->sih, SICF_SWRST, 0); ++ } ++ ++ /* reset gmac */ ++ gmac_reset(ch); ++ ++ /* clear mib */ ++ gmac_clearmib(ch); ++ ch->mibgood = TRUE; ++ ++ /* set mdc_transition_en */ ++ OR_REG(ch->osh, ®s->phycontrol, PC_MTE); ++ ++ /* Read the devstatus to figure out the configuration mode of ++ * the interface. Set the speed to 100 if the switch interface ++ * is mii/rmii. ++ */ ++ gmac_miiconfig(ch); ++ ++// /* gmac doesn't have internal phy */ ++// chipphyinit(ch, ch->etc->phyaddr); ++ ++ /* clear persistent sw intstatus */ ++ ch->intstatus = 0; ++} ++ ++/* ++ * Lookup a multicast address in the filter hash table. ++ */ ++static int ++gmac_mf_lkup(ch_t *ch, struct ether_addr *mcaddr) ++{ ++ mflist_t *ptr; ++ ++ /* find the multicast address */ ++ for (ptr = ch->mf.bucket[GMAC_MCADDR_HASH(mcaddr)]; ptr != NULL; ptr = ptr->next) { ++ if (!ETHER_MCADDR_CMP(&ptr->mc_addr, mcaddr)) ++ return (SUCCESS); ++ } ++ ++ return (FAILURE); ++} ++ ++/* ++ * Add a multicast address to the filter hash table. ++ */ ++static int ++gmac_mf_add(ch_t *ch, struct ether_addr *mcaddr) ++{ ++ uint32 hash; ++ mflist_t *entry; ++#ifdef BCMDBG ++ char mac[ETHER_ADDR_STR_LEN]; ++#endif /* BCMDBG */ ++ ++ /* add multicast addresses only */ ++ if (!ETHER_ISMULTI(mcaddr)) { ++ ET_ERROR(("et%d: adding invalid multicast address %s\n", ++ ch->etc->unit, bcm_ether_ntoa(mcaddr, mac))); ++ return (FAILURE); ++ } ++ ++ /* discard duplicate add requests */ ++ if (gmac_mf_lkup(ch, mcaddr) == SUCCESS) { ++ ET_ERROR(("et%d: adding duplicate mcast filter entry\n", ch->etc->unit)); ++ return (FAILURE); ++ } ++ ++ /* allocate memory for list entry */ ++ entry = MALLOC(ch->osh, sizeof(mflist_t)); ++ if (entry == NULL) { ++ ET_ERROR(("et%d: out of memory allocating mcast filter entry\n", ch->etc->unit)); ++ return (FAILURE); ++ } ++ ++ /* add the entry to the hash bucket */ ++ ether_copy(mcaddr, &entry->mc_addr); ++ hash = GMAC_MCADDR_HASH(mcaddr); ++ entry->next = ch->mf.bucket[hash]; ++ ch->mf.bucket[hash] = entry; ++ ++ return (SUCCESS); ++} ++ ++/* ++ * Cleanup the multicast filter hash table. ++ */ ++static void ++gmac_mf_cleanup(ch_t *ch) ++{ ++ mflist_t *ptr, *tmp; ++ int32 i; ++ ++ for (i = 0; i < GMAC_HASHT_SIZE; i++) { ++ ptr = ch->mf.bucket[i]; ++ while (ptr) { ++ tmp = ptr; ++ ptr = ptr->next; ++ MFREE(ch->osh, tmp, sizeof(mflist_t)); ++ } ++ ch->mf.bucket[i] = NULL; ++ } ++} ++ ++/* ++ * Initialize all the chip registers. If dma mode, init tx and rx dma engines ++ * but leave the devcontrol tx and rx (fifos) disabled. ++ */ ++static void ++chipinit(ch_t *ch, uint options) ++{ ++ etc_info_t *etc; ++ gmacregs_t *regs; ++ uint idx; ++ uint i; ++#ifdef CONFIG_BCM_CUSTOM_RECVFILE_MAX_PERF ++ uint bp_clk; ++ uint32_t fpi = 8; ++#endif ++ ++ regs = ch->regs; ++ etc = ch->etc; ++ idx = 0; ++ ++ ET_TRACE(("et%d: chipinit\n", etc->unit)); ++ ++#ifdef CONFIG_BCM_CUSTOM_RECVFILE_MAX_PERF ++ /* enable rx lazy interrupt. set frame count and timeout */ ++ bp_clk = si_clock(ch->sih) / 1000000; ++ W_REG(ch->osh, ®s->intrecvlazy, (fpi << IRL_FC_SHIFT) | (48 * bp_clk)); ++#else ++ /* enable one rx interrupt per received frame */ ++ W_REG(ch->osh, ®s->intrecvlazy, (1 << IRL_FC_SHIFT)); ++#endif ++ ++ /* enable 802.3x tx flow control (honor received PAUSE frames) */ ++ gmac_txflowcontrol(ch, TRUE); ++ ++ /* enable/disable promiscuous mode */ ++ gmac_promisc(ch, etc->promisc); ++ ++ /* set our local address */ ++ W_REG(ch->osh, ®s->macaddrhigh, ++ hton32(*(uint32 *)&etc->cur_etheraddr.octet[0])); ++ W_REG(ch->osh, ®s->macaddrlow, ++ hton16(*(uint16 *)&etc->cur_etheraddr.octet[4])); ++ ++ if (!etc->promisc) { ++ /* gmac doesn't have a cam, hence do the multicast address filtering ++ * in the software ++ */ ++ /* allmulti or a list of discrete multicast addresses */ ++ if (!etc->allmulti && etc->nmulticast) ++ for (i = 0; i < etc->nmulticast; i++) ++ (void)gmac_mf_add(ch, &etc->multicast[i]); ++ } ++ ++ /* optionally enable mac-level loopback */ ++ if (etc->loopbk) ++ gmac_loopback(ch, LOOPBACK_MODE_MAC); ++ else ++ gmac_loopback(ch, LOOPBACK_MODE_NONE); ++ ++ /* set max frame lengths - account for possible vlan tag */ ++ W_REG(ch->osh, ®s->rxmaxlength, BCM_ETHER_MAX_LEN); ++ ++ /* ++ * Optionally, disable phy autonegotiation and force our speed/duplex ++ * or constrain our advertised capabilities. ++ */ ++ if (etc->forcespeed != ET_AUTO) { ++ gmac_speed(ch, etc->forcespeed); ++ chipphyforce(ch, etc->phyaddr); ++ } else if (etc->advertise && etc->needautoneg) ++ chipphyadvertise(ch, etc->phyaddr); ++ ++ /* enable the overflow continue feature and disable parity */ ++ dma_ctrlflags(ch->di[0], DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */, ++ DMA_CTRL_ROC /* value */); ++ ++ if (options & ET_INIT_FULL) { ++ /* initialize the tx and rx dma channels */ ++ for (i = 0; i < NUMTXQ; i++) ++ dma_txinit(ch->di[i]); ++ dma_rxinit(ch->di[RX_Q0]); ++ ++ /* post dma receive buffers */ ++ dma_rxfill(ch->di[RX_Q0]); ++ ++ /* lastly, enable interrupts */ ++ if (options & ET_INIT_INTRON) ++ et_intrson(etc->et); ++ } ++ else ++ dma_rxenable(ch->di[RX_Q0]); ++ ++ /* turn on the emac */ ++ gmac_enable(ch); ++} ++ ++/* dma transmit */ ++static bool BCMFASTPATH ++chiptx(ch_t *ch, void *p0) ++{ ++ int error, len; ++ uint32 q = TX_Q0; ++ ++ ET_TRACE(("et%d: chiptx\n", ch->etc->unit)); ++ ET_LOG("et%d: chiptx", ch->etc->unit, 0); ++ ++ len = PKTLEN(ch->osh, p0); ++ ++ /* check tx max length */ ++ if (len > BCM_ETHER_MAX_LEN) { ++ ET_ERROR(("et%d: chiptx: max frame length exceeded\n", ++ ch->etc->unit)); ++ PKTFREE(ch->osh, p0, TRUE); ++ return FALSE; ++ } ++ ++ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) ++ PKTSETLEN(ch->osh, p0, GMAC_MIN_FRAMESIZE); ++ ++#if defined(CONFIG_MACH_NS) ++ /* queue the packet based on its priority */ ++#ifdef GMAC3 ++ //q = (ch->etc->txQId++) % NUMTXQ; ++ //q = ch->etc->unit; ++ if (DEV_FWDER(ch->etc)) { ++ q = TX_Q0; ++ } else { ++ if (ch->etc->qos) ++ q = etc_up2tc(PKTPRIO(p0)); ++ else ++ q = TX_Q0; ++ } ++#else /* !GMAC3 */ ++ if (ch->etc->qos) ++ q = etc_up2tc(PKTPRIO(p0)); ++#endif /* !GMAC3 */ ++#endif /* defined(CONFIG_MACH_NS) */ ++ ++ ASSERT(q < NUMTXQ); ++ ++ /* if tx completion intr is disabled then do the reclaim ++ * once every few frames transmitted. ++ */ ++ if ((ch->etc->txframes[q] & ch->etc->txrec_thresh) == 1) ++ dma_txreclaim(ch->di[q], HNDDMA_RANGE_TRANSMITTED); ++ ++ error = dma_txfast(ch->di[q], p0, TRUE); ++ ++ if (error) { ++ ET_ERROR(("et%d: chiptx: out of txds\n", ch->etc->unit)); ++ ch->etc->txnobuf++; ++ return FALSE; ++ } ++ ++ ch->etc->txframes[q]++; ++ ++ if ((len < GMAC_MIN_FRAMESIZE) && (ch->etc->corerev == 0)) { ++ if (skb_is_nonlinear((struct sk_buff*)p0)) ++ printk("Modified nonlinear skb (et_ctf_pipeline_loopback) - not calling skb_trim\n"); ++ else ++ /* set back the orig length */ ++ PKTSETLEN(ch->osh, p0, len); ++ } ++ ++ return TRUE; ++} ++ ++/* reclaim completed transmit descriptors and packets */ ++static void BCMFASTPATH ++chiptxreclaim(ch_t *ch, bool forceall) ++{ ++ int32 i; ++ ++ ET_TRACE(("et%d: chiptxreclaim\n", ch->etc->unit)); ++ ++ for (i = 0; i < NUMTXQ; i++) { ++ dma_txreclaim(ch->di[i], forceall ? HNDDMA_RANGE_ALL : HNDDMA_RANGE_TRANSMITTED); ++ ch->intstatus &= ~(I_XI0 << i); ++ } ++} ++ ++/* dma receive: returns a pointer to the next frame received, or NULL if there are no more */ ++static void * BCMFASTPATH ++chiprx(ch_t *ch) ++{ ++ void *p; ++ struct ether_addr *da; ++ ++ ET_TRACE(("et%d: chiprx\n", ch->etc->unit)); ++ ET_LOG("et%d: chiprx", ch->etc->unit, 0); ++ ++ if (dma_rxstopped(ch->di[RX_Q0])) { ++ ch->etc->rxdmastopped++; ++ } ++ ++ /* gmac doesn't have a cam to do address filtering. so we implement ++ * the multicast address filtering here. ++ */ ++ while ((p = dma_rx(ch->di[RX_Q0])) != NULL) { ++ /* check for overflow error packet */ ++ if (RXH_FLAGS(ch->etc, PKTDATA(ch->osh, p)) & GRXF_OVF) { ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rxoflodiscards++; ++ continue; ++ } ++ ++#ifdef GMAC_RATE_LIMITING ++ /* rate limiting */ ++ //printf("et%d: chiprx RXH_PT(0x%x)\n", ch->etc->unit, RXH_PT(ch->etc, PKTDATA(ch->osh, p))); ++ if (ch->etc->rl_stopping_broadcasts) { ++ /* check if broadcast packet */ ++ if (RXH_PT(ch->etc, PKTDATA(ch->osh, p)) == 2) { ++ /* broadcast packet */ ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rl_dropped_bc_packets++; ++ ch->etc->rl_dropped_packets++; ++ continue; ++ } ++ } else if (ch->etc->rl_stopping_all_packets) { ++ PKTFREE(ch->osh, p, FALSE); ++ ch->etc->rl_dropped_all_packets++; ++ ch->etc->rl_dropped_packets++; ++ continue; ++ } ++#endif /* GMAC_RATE_LIMITING */ ++ ++ if (ch->etc->allmulti) { ++ return (p); ++ } ++ else { ++ /* skip the rx header */ ++ PKTPULL(ch->osh, p, HWRXOFF); ++ ++ /* do filtering only for multicast packets when allmulti is false */ ++ da = (struct ether_addr *)PKTDATA(ch->osh, p); ++ if (!ETHER_ISMULTI(da) || ++ (gmac_mf_lkup(ch, da) == SUCCESS) || ETHER_ISBCAST(da)) { ++ PKTPUSH(ch->osh, p, HWRXOFF); ++ return (p); ++ } ++ PKTFREE(ch->osh, p, FALSE); ++ } ++ } ++ ++ ch->intstatus &= ~I_RI; ++ ++ /* post more rx buffers since we consumed a few */ ++ dma_rxfill(ch->di[RX_Q0]); ++ ++ return (NULL); ++} ++ ++/* reclaim completed dma receive descriptors and packets */ ++static void ++chiprxreclaim(ch_t *ch) ++{ ++ ET_TRACE(("et%d: chiprxreclaim\n", ch->etc->unit)); ++ dma_rxreclaim(ch->di[RX_Q0]); ++ ch->intstatus &= ~I_RI; ++} ++ ++/* allocate and post dma receive buffers */ ++static void BCMFASTPATH ++chiprxfill(ch_t *ch) ++{ ++ ET_TRACE(("et%d: chiprxfill\n", ch->etc->unit)); ++ ET_LOG("et%d: chiprxfill", ch->etc->unit, 0); ++ dma_rxfill(ch->di[RX_Q0]); ++} ++ ++ ++/* get current and pending interrupt events */ ++static int BCMFASTPATH ++chipgetintrevents(ch_t *ch, bool in_isr) ++{ ++ uint32 intstatus; ++ int events; ++ ++ events = 0; ++ ++ /* read the interrupt status register */ ++ intstatus = R_REG(ch->osh, &ch->regs->intstatus); ++ ++ /* defer unsolicited interrupts */ ++ intstatus &= (in_isr ? ch->intmask : ch->def_intmask); ++ ++ if (intstatus != 0) ++ events = INTR_NEW; ++ ++ /* or new bits into persistent intstatus */ ++ intstatus = (ch->intstatus |= intstatus); ++ ++ /* return if no events */ ++ if (intstatus == 0) ++ return (0); ++ ++ /*check_errs(ch);*/ ++ ++ /* convert chip-specific intstatus bits into generic intr event bits */ ++ if (intstatus & I_RI) ++ events |= INTR_RX; ++ if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) ++ events |= INTR_TX; ++ if (intstatus & I_ERRORS) ++ events |= INTR_ERROR; ++ ++ return (events); ++} ++ ++/* enable chip interrupts */ ++static void BCMFASTPATH ++chipintrson(ch_t *ch) ++{ ++ ch->intmask = ch->def_intmask; ++ W_REG(ch->osh, &ch->regs->intmask, ch->intmask); ++} ++ ++/* disable chip interrupts */ ++static void BCMFASTPATH ++chipintrsoff(ch_t *ch) ++{ ++ /* disable further interrupts from gmac */ ++ W_REG(ch->osh, &ch->regs->intmask, 0); ++ (void) R_REG(ch->osh, &ch->regs->intmask); /* sync readback */ ++ ch->intmask = 0; ++ ++ /* clear the interrupt conditions */ ++ W_REG(ch->osh, &ch->regs->intstatus, ch->intstatus); ++} ++ ++/* return true of caller should re-initialize, otherwise false */ ++static bool BCMFASTPATH ++chiperrors(ch_t *ch) ++{ ++ uint32 intstatus; ++ etc_info_t *etc; ++ ++ etc = ch->etc; ++ ++ intstatus = ch->intstatus; ++ ch->intstatus &= ~(I_ERRORS); ++ ++ ET_TRACE(("et%d: chiperrors: intstatus 0x%x\n", etc->unit, intstatus)); ++ ++ if (intstatus & I_PDEE) { ++ ET_ERROR(("et%d: descriptor error\n", etc->unit)); ++ etc->dmade++; ++ } ++ ++ if (intstatus & I_PDE) { ++ ET_ERROR(("et%d: data error\n", etc->unit)); ++ etc->dmada++; ++ } ++ ++ if (intstatus & I_DE) { ++ ET_ERROR(("et%d: descriptor protocol error\n", etc->unit)); ++ etc->dmape++; ++ } ++ ++ if (intstatus & I_RDU) { ++ ET_ERROR(("et%d: receive descriptor underflow\n", etc->unit)); ++ etc->rxdmauflo++; ++ } ++ ++ if (intstatus & I_RFO) { ++ ET_TRACE(("et%d: receive fifo overflow\n", etc->unit)); ++ etc->rxoflo++; ++ } ++ ++ if (intstatus & I_XFU) { ++ ET_ERROR(("et%d: transmit fifo underflow\n", etc->unit)); ++ etc->txuflo++; ++ } ++ ++ /* if overflows or decriptors underflow, don't report it ++ * as an error and provoque a reset ++ */ ++ if (intstatus & ~(I_RDU | I_RFO) & I_ERRORS) ++ return (TRUE); ++ ++ return (FALSE); ++} ++ ++static void ++chipstatsupd(ch_t *ch) ++{ ++ etc_info_t *etc; ++ gmacregs_t *regs; ++ volatile uint32 *s; ++ uint32 *d; ++ ++ etc = ch->etc; ++ regs = ch->regs; ++ ++ /* read the mib counters and update the driver maintained software ++ * counters. ++ */ ++ if (etc->corerev != GMAC_4706B0_CORE_REV) { ++ OR_REG(ch->osh, ®s->devcontrol, DC_MROR); ++ for (s = ®s->mib.tx_good_octets, d = &ch->mib.tx_good_octets; ++ s <= ®s->mib.rx_uni_pkts; s++, d++) { ++ *d += R_REG(ch->osh, s); ++ if (s == &ch->regs->mib.tx_q3_octets_high) { ++ s++; ++ d++; ++ } ++ } ++ } ++ ++ ++ /* ++ * Aggregate transmit and receive errors that probably resulted ++ * in the loss of a frame are computed on the fly. ++ * ++ * We seem to get lots of tx_carrier_lost errors when flipping ++ * speed modes so don't count these as tx errors. ++ * ++ * Arbitrarily lump the non-specific dma errors as tx errors. ++ */ ++ etc->txerror = ch->mib.tx_jabber_pkts + ch->mib.tx_oversize_pkts ++ + ch->mib.tx_underruns + ch->mib.tx_excessive_cols ++ + ch->mib.tx_late_cols + etc->txnobuf + etc->dmade ++ + etc->dmada + etc->dmape + etc->txuflo; ++ etc->rxerror = ch->mib.rx_jabber_pkts + ch->mib.rx_oversize_pkts ++ + ch->mib.rx_missed_pkts + ch->mib.rx_crc_align_errs ++ + ch->mib.rx_undersize + ch->mib.rx_crc_errs ++ + ch->mib.rx_align_errs + ch->mib.rx_symbol_errs ++ + etc->rxnobuf + etc->rxdmauflo + etc->rxoflo + etc->rxbadlen; ++ etc->rxgiants = (ch->di[RX_Q0])->rxgiants; ++} ++ ++static void ++chipdumpmib(ch_t *ch, struct bcmstrbuf *b, bool clear) ++{ ++ gmacmib_t *m; ++ ++ m = &ch->mib; ++ ++ if (clear) { ++ bzero((char *)m, sizeof(gmacmib_t)); ++ return; ++ } ++ ++ bcm_bprintf(b, "tx_broadcast_pkts %d tx_multicast_pkts %d tx_jabber_pkts %d " ++ "tx_oversize_pkts %d\n", ++ m->tx_broadcast_pkts, m->tx_multicast_pkts, ++ m->tx_jabber_pkts, ++ m->tx_oversize_pkts); ++ bcm_bprintf(b, "tx_fragment_pkts %d tx_underruns %d\n", ++ m->tx_fragment_pkts, m->tx_underruns); ++ bcm_bprintf(b, "tx_total_cols %d tx_single_cols %d tx_multiple_cols %d " ++ "tx_excessive_cols %d\n", ++ m->tx_total_cols, m->tx_single_cols, m->tx_multiple_cols, ++ m->tx_excessive_cols); ++ bcm_bprintf(b, "tx_late_cols %d tx_defered %d tx_carrier_lost %d tx_pause_pkts %d\n", ++ m->tx_late_cols, m->tx_defered, m->tx_carrier_lost, ++ m->tx_pause_pkts); ++ ++ /* receive stat counters */ ++ /* hardware mib pkt and octet counters wrap too quickly to be useful */ ++ bcm_bprintf(b, "rx_broadcast_pkts %d rx_multicast_pkts %d rx_jabber_pkts %d " ++ "rx_oversize_pkts %d\n", ++ m->rx_broadcast_pkts, m->rx_multicast_pkts, ++ m->rx_jabber_pkts, m->rx_oversize_pkts); ++ bcm_bprintf(b, "rx_fragment_pkts %d rx_missed_pkts %d rx_crc_align_errs %d " ++ "rx_undersize %d\n", ++ m->rx_fragment_pkts, m->rx_missed_pkts, ++ m->rx_crc_align_errs, m->rx_undersize); ++ bcm_bprintf(b, "rx_crc_errs %d rx_align_errs %d rx_symbol_errs %d\n", ++ m->rx_crc_errs, m->rx_align_errs, m->rx_symbol_errs); ++ bcm_bprintf(b, "rx_pause_pkts %d rx_nonpause_pkts %d\n", ++ m->rx_pause_pkts, m->rx_nonpause_pkts); ++} ++ ++void ++etc_chip_mib(etc_info_t *etc) ++{ ++ uint32 *d; ++ ch_t *ch = (ch_t*)etc->ch; ++ ++ chipstatsupd(ch); ++ printk("et%d: txframe:0x%x, txbyte:0x%x txerror:0x%x\n", ch->etc->unit, ++ ch->etc->txframe, ch->etc->txbyte, ch->etc->txerror); ++ printk("et%d: rxframe:0x%x, rxbyte:0x%x rxerror:0x%x\n", ch->etc->unit, ++ ch->etc->rxframe, ch->etc->rxbyte, ch->etc->rxerror); ++ printk("et%d: RXDMA: ctrl(0x%x), ptr(0x%x), addrl(0x%x), addrh(0x%x) st0(0x%x), st1(0x%x)\n", ++ ch->etc->unit, ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.control), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.ptr), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.addrlow), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.addrhigh), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status0), ++ R_REG(ch->osh, &ch->regs->dmaregs[0].dmarcv.status1)); ++ ++ /* clear counters */ ++ for (d = &ch->mib.tx_good_octets; d <= &ch->mib.rx_uni_pkts; d++) { ++ *d = 0; ++ if (d == &ch->mib.tx_q3_octets_high) { ++ d++; ++ } ++ } ++} ++ ++static void ++chipenablepme(ch_t *ch) ++{ ++ return; ++} ++ ++static void ++chipdisablepme(ch_t *ch) ++{ ++ return; ++} ++ ++static void ++chipduplexupd(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ int32 duplex, speed; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* check if duplex mode changed */ ++ if (ch->etc->duplex && (cmdcfg & CC_HD)) ++ duplex = 0; ++ else if (!ch->etc->duplex && ((cmdcfg & CC_HD) == 0)) ++ duplex = CC_HD; ++ else ++ duplex = -1; ++ ++ /* check if the speed changed */ ++ speed = ((cmdcfg & CC_ES_MASK) >> CC_ES_SHIFT); ++ if ((ch->etc->speed == 1000) && (speed != 2)) ++ speed = 2; ++ else if ((ch->etc->speed == 100) && (speed != 1)) ++ speed = 1; ++ else if ((ch->etc->speed == 10) && (speed != 0)) ++ speed = 0; ++ else ++ speed = -1; ++ ++ /* no duplex or speed change required */ ++ if ((speed == -1) && (duplex == -1)) { ++ return; ++ } ++ ++ /* update the speed */ ++ if (speed != -1) { ++ cmdcfg &= ~CC_ES_MASK; ++ cmdcfg |= (speed << CC_ES_SHIFT); ++ } ++ ++ /* update the duplex mode */ ++ if (duplex != -1) { ++ cmdcfg &= ~CC_HD; ++ cmdcfg |= duplex; ++ } ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ cmdcfg |= CC_AE; ++#endif ++ ++ ET_TRACE(("chipduplexupd: updating speed & duplex %x\n", cmdcfg)); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++} ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++static void ++chipforcespddpx(ch_t *ch) ++{ ++ uint32 cmdcfg; ++ int32 duplex=0, speed; ++ ++ cmdcfg = R_REG(ch->osh, &ch->regs->cmdcfg); ++ ++ /* set duplex */ ++ if (!ch->etc->duplex) ++ duplex = CC_HD; ++ ++ /* set speed */ ++ if (ch->etc->speed == 10) ++ speed = 0; ++ else if (ch->etc->speed == 100) ++ speed = 1; ++ else ++ speed = 2; ++ ++ /* update the speed */ ++ cmdcfg &= ~CC_ES_MASK; ++ cmdcfg |= (speed << CC_ES_SHIFT); ++ ++ /* update the duplex mode */ ++ cmdcfg &= ~CC_HD; ++ cmdcfg |= duplex; ++ ++ ET_TRACE(("chipforcespddpx: forcing speed & duplex %x\n", cmdcfg)); ++ ++ /* put mac in reset */ ++ gmac_init_reset(ch); ++ ++ W_REG(ch->osh, &ch->regs->cmdcfg, cmdcfg); ++ ++ /* bring mac out of reset */ ++ gmac_clear_reset(ch); ++ ++ if (ch->etc->up) { ++ serdes_speeddpx_set(ch->etc->unit, ch->etc->phyaddr, ch->etc->speed, ch->etc->duplex); ++ } ++} ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++ ++static uint16 ++chipphyrd(ch_t *ch, uint phyaddr, uint reg) ++{ ++ uint32 tmp = 0xffffffff; ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ gmacregs_t *regs; ++ uint32 *phycontrol_addr, *phyaccess_addr; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ASSERT(reg < MAXPHYREG); ++ ++ regs = ch->regs; ++ ++ phycontrol_addr = (uint32 *)®s->phycontrol; ++ phyaccess_addr = (uint32 *)®s->phyaccess; ++ ++ /* issue the read */ ++ tmp = R_REG(ch->osh, phycontrol_addr); ++ tmp &= ~0x1f; ++ tmp |= phyaddr; ++ W_REG(ch->osh, phycontrol_addr, tmp); ++ W_REG(ch->osh, phyaccess_addr, ++ (PA_START | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT))); ++ ++ /* wait for it to complete */ ++ SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000); ++ tmp = R_REG(ch->osh, phyaccess_addr); ++ if (tmp & PA_START) { ++ ET_ERROR(("et%d: chipphyrd: did not complete\n", ch->etc->unit)); ++ tmp = 0xffff; ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ uint32 addr, int_bus, bank, flags; ++ uint16 tmp16; ++ ++ addr = phyaddr&0xf; ++ int_bus = phyaddr&0xf0; ++ bank = (phyaddr&0x1f00)>>8; ++ flags = (phyaddr&0x10000)?SOC_PHY_REG_1000X:0; ++ ++ if (int_bus) { ++ /* internal serdes */ ++ tmp = serdes_rd_reg(ch->etc->unit, addr, reg); ++ } else { ++ /* external phy */ ++ phy5461_rd_reg(ch->etc->unit, addr, flags, bank, reg, &tmp16); ++ tmp = tmp16; ++ } ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ uint32 addr, bank; ++ uint16 tmp16; ++ ++ addr = phyaddr&0xf; ++ bank = (phyaddr&0x1f00)>>8; ++ ++ phy5221_rd_reg(ch->etc->unit, addr, bank, reg, &tmp16); ++ tmp = tmp16; ++#endif /* defined(CONFIG_MACH_HR2) */ ++ ++ return (tmp & PA_DATA_MASK); ++} ++ ++static void ++chipphywr(ch_t *ch, uint phyaddr, uint reg, uint16 v) ++{ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ uint32 tmp; ++ gmacregs_t *regs; ++ uint32 *phycontrol_addr, *phyaccess_addr; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ASSERT(reg < MAXPHYREG); ++ ++ regs = ch->regs; ++ ++ phycontrol_addr = (uint32 *)®s->phycontrol; ++ phyaccess_addr = (uint32 *)®s->phyaccess; ++ ++ /* clear mdioint bit of intstatus first */ ++ tmp = R_REG(ch->osh, phycontrol_addr); ++ tmp &= ~0x1f; ++ tmp |= phyaddr; ++ W_REG(ch->osh, phycontrol_addr, tmp); ++ W_REG(ch->osh, ®s->intstatus, I_MDIO); ++ ASSERT((R_REG(ch->osh, ®s->intstatus) & I_MDIO) == 0); ++ ++ /* issue the write */ ++ W_REG(ch->osh, phyaccess_addr, ++ (PA_START | PA_WRITE | (phyaddr << PA_ADDR_SHIFT) | (reg << PA_REG_SHIFT) | v)); ++ ++ /* wait for it to complete */ ++ SPINWAIT((R_REG(ch->osh, phyaccess_addr) & PA_START), 1000); ++ if (R_REG(ch->osh, phyaccess_addr) & PA_START) { ++ ET_ERROR(("et%d: chipphywr: did not complete\n", ch->etc->unit)); ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ uint32 addr, int_bus, bank, flags; ++ ++ addr = phyaddr&0xf; ++ int_bus = phyaddr&0xf0; ++ bank = (phyaddr&0x1f00)>>8; ++ flags = (phyaddr&0x10000)?SOC_PHY_REG_1000X:0; ++ ++ if (int_bus) { ++ /* internal serdes */ ++ serdes_wr_reg(ch->etc->unit, addr, reg, v); ++ } else { ++ /* external phy */ ++ phy5461_wr_reg(ch->etc->unit, addr, flags, bank, reg, &v); ++ } ++#endif ++#if defined(CONFIG_MACH_HR2) ++ uint32 addr, bank; ++ ++ addr = phyaddr&0xf; ++ bank = (phyaddr&0x1f00)>>8; ++ ++ phy5221_wr_reg(ch->etc->unit, addr, bank, reg, &v); ++ ++#endif /* defined(CONFIG_MACH_HR2) */ ++} ++ ++static void ++chipphyor(ch_t *ch, uint phyaddr, uint reg, uint16 v) ++{ ++ uint16 tmp; ++ ++ tmp = chipphyrd(ch, phyaddr, reg); ++ tmp |= v; ++ chipphywr(ch, phyaddr, reg, tmp); ++} ++ ++static void ++chipphyreset(ch_t *ch, uint phyaddr) ++{ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ ET_TRACE(("et%d: chipphyreset: phyaddr %d\n", ch->etc->unit, phyaddr)); ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++#endif /* (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) */ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++ serdes_reset(ch->etc->unit, phyaddr); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ chipphywr(ch, phyaddr, 0, CTL_RESET); ++ OSL_DELAY(100); ++ if (chipphyrd(ch, phyaddr, 0) & CTL_RESET) { ++ ET_ERROR(("et%d: chipphyreset: reset not complete\n", ch->etc->unit)); ++ } ++#endif /* defined(CONFIG_MACH_HR2) */ ++ ++ chipphyinit(ch, phyaddr); ++} ++ ++static void ++chipphyinit(ch_t *ch, uint phyaddr) ++{ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ ET_TRACE(("et%d: chipphyinit: phyaddr %d\n", ch->etc->unit, phyaddr)); ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ phy5461_init(ch->etc->unit, phyaddr); ++ serdes_init(ch->etc->unit, phyaddr); ++ if (gmac_last_interface(ch->etc->unit)) { ++ /* must init all serdes lanes, init port 49 (phy 3) */ ++ serdes_init(ch->etc->unit, 3); ++ serdes_start_pll(ch->etc->unit, 1); ++ } ++#elif defined(CONFIG_MACH_HR2) ++ phy5221_init(ch->etc->unit, phyaddr); ++#endif ++ ++} ++ ++static void ++chipphyforce(ch_t *ch, uint phyaddr) ++{ ++ etc_info_t *etc; ++ uint16 ctl; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ etc = ch->etc; ++ ++ if (etc->forcespeed == ET_AUTO) ++ return; ++ ++ ET_TRACE(("et%d: chipphyforce: phyaddr %d speed %d\n", ++ ch->etc->unit, phyaddr, etc->forcespeed)); ++ ++ ctl = chipphyrd(ch, phyaddr, 0); ++ ctl &= ~(CTL_SPEED | CTL_SPEED_MSB | CTL_ANENAB | CTL_DUPLEX); ++ ++ switch (etc->forcespeed) { ++ case ET_10HALF: ++ break; ++ ++ case ET_10FULL: ++ ctl |= CTL_DUPLEX; ++ break; ++ ++ case ET_100HALF: ++ ctl |= CTL_SPEED_100; ++ break; ++ ++ case ET_100FULL: ++ ctl |= (CTL_SPEED_100 | CTL_DUPLEX); ++ break; ++ ++ case ET_1000FULL: ++ ctl |= (CTL_SPEED_1000 | CTL_DUPLEX); ++ break; ++ } ++ ++ chipphywr(ch, phyaddr, 0, ctl); ++} ++ ++/* set selected capability bits in autonegotiation advertisement */ ++static void ++chipphyadvertise(ch_t *ch, uint phyaddr) ++{ ++ etc_info_t *etc; ++ uint16 adv, adv2; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ etc = ch->etc; ++ ++ if ((etc->forcespeed != ET_AUTO) || !etc->needautoneg) ++ return; ++ ++ ASSERT(etc->advertise); ++ ++ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d advertise %x\n", ++ ch->etc->unit, phyaddr, etc->advertise)); ++ ++ /* reset our advertised capabilitity bits */ ++ adv = chipphyrd(ch, phyaddr, 4); ++ adv &= ~(ADV_100FULL | ADV_100HALF | ADV_10FULL | ADV_10HALF); ++ adv |= etc->advertise; ++ adv |= ADV_PAUSE; ++ chipphywr(ch, phyaddr, 4, adv); ++ ++ adv2 = chipphyrd(ch, phyaddr, 9); ++ adv2 &= ~(ADV_1000FULL | ADV_1000HALF); ++ adv2 |= etc->advertise2; ++ chipphywr(ch, phyaddr, 9, adv2); ++ ++ ET_TRACE(("et%d: chipphyadvertise: phyaddr %d adv %x adv2 %x phyad0 %x\n", ++ ch->etc->unit, phyaddr, adv, adv2, chipphyrd(ch, phyaddr, 0))); ++ ++ /* restart autonegotiation */ ++ chipphyor(ch, phyaddr, 0, CTL_RESTART); ++ etc->needautoneg = FALSE; ++} ++ ++static void ++chipphyenable(ch_t *ch, uint eth_num, uint phyaddr, int enable) ++{ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ phy5461_enable_set(eth_num, phyaddr, enable); ++#endif /* (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) */ ++#if defined(CONFIG_MACH_HR2) ++ phy5221_enable_set(eth_num, phyaddr, enable); ++#endif /* defined(CONFIG_MACH_HR2) */ ++} ++ ++#ifdef GMAC_RATE_LIMITING ++void ++etc_check_rate_limiting(etc_info_t *etc, void *pch) ++{ ++ ch_t *ch = (ch_t*)pch; ++ uint32 timediff, bc_pkt_count, all_pkt_count; ++ ++ timediff = ((long)jiffies - (long)(etc->rl_prior_jiffies)); ++ if ((timediff>>5) != 0) { ++ /* 32 or more jiffies have gone by; see if we're seeing too ++ many packets */ ++ if ((timediff>>5) == 1) { ++ /* 32-63 jiffies elapsed */ ++ bc_pkt_count = R_REG(ch->osh, &ch->regs->mib.rx_broadcast_pkts); ++ all_pkt_count = R_REG(ch->osh, &ch->regs->mib.rx_good_pkts); ++ /* account for the dropped broadcast packets */ ++ all_pkt_count -= etc->rl_dropped_bc_packets; ++ ++ if (((bc_pkt_count>>10) != 0) && !(etc->rl_stopping_broadcasts)) { ++ /* 1K or more broadcast packets have arrived in 32-63 jiffies; try to throttle back the incoming packets */ ++ etc->rl_stopping_broadcasts = 1; ++ printf("et%d: %s: stopping broadcasts bc_pkt_count(0x%x)\n", ++ etc->unit, __FUNCTION__, bc_pkt_count); ++ if (!timer_pending(&etc->rl_timer)) { ++ etc->rl_timer.expires = jiffies + HZ; ++ add_timer(&etc->rl_timer); ++ etc->rl_set=TRUE; ++ } ++ } ++ } ++ etc->rl_prior_jiffies = jiffies; ++ } ++} ++#endif /* GMAC_RATE_LIMITING */ +diff --git a/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h +new file mode 100755 +index 0000000..395de4b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/et/sys/etcgmac.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Gigabit Ethernet MAC defines. ++ * ++ * $Id: etcgmac.h 267700 2011-06-19 15:41:07Z $ ++ */ ++#ifndef _etcgmac_h_ ++#define _etcgmac_h_ ++ ++/* chip interrupt bit error summary */ ++#define I_ERRORS (I_PDEE | I_PDE | I_DE | I_RDU | I_RFO | I_XFU) ++#define DEF_INTMASK (I_XI0 | I_XI1 | I_XI2 | I_XI3 | I_RI | I_ERRORS) ++ ++#define GMAC_RESET_DELAY 2 ++ ++#define GMAC_MIN_FRAMESIZE 17 /* gmac can only send frames of ++ * size above 17 octetes. ++ */ ++ ++#define LOOPBACK_MODE_DMA 0 /* loopback the packet at the DMA engine */ ++#define LOOPBACK_MODE_MAC 1 /* loopback the packet at MAC */ ++#define LOOPBACK_MODE_NONE 2 /* no Loopback */ ++ ++#define DMAREG(ch, dir, qnum) ((dir == DMA_TX) ? \ ++ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmaxmt) : \ ++ (void *)(uintptr)&(ch->regs->dmaregs[qnum].dmarcv)) ++ ++/* ++ * Add multicast address to the list. Multicast address are maintained as ++ * hash table with chaining. ++ */ ++typedef struct mclist { ++ struct ether_addr mc_addr; /* multicast address to allow */ ++ struct mclist *next; /* next entry */ ++} mflist_t; ++ ++#define GMAC_HASHT_SIZE 16 /* hash table size */ ++#define GMAC_MCADDR_HASH(m) ((((uint8 *)(m))[3] + ((uint8 *)(m))[4] + \ ++ ((uint8 *)(m))[5]) & (GMAC_HASHT_SIZE - 1)) ++ ++#define ETHER_MCADDR_CMP(x, y) ((((uint16 *)(x))[0] ^ ((uint16 *)(y))[0]) | \ ++ (((uint16 *)(x))[1] ^ ((uint16 *)(y))[1]) | \ ++ (((uint16 *)(x))[2] ^ ((uint16 *)(y))[2])) ++ ++#define SUCCESS 0 ++#define FAILURE -1 ++ ++typedef struct mcfilter { ++ /* hash table for multicast filtering */ ++ mflist_t *bucket[GMAC_HASHT_SIZE]; ++} mcfilter_t; ++ ++extern uint32 find_priq(uint32 pri_map); ++ ++#endif /* _etcgmac_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/Makefile b/drivers/bcmdrivers/gmac/src/include/Makefile +new file mode 100755 +index 0000000..42b3b68 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/Makefile +@@ -0,0 +1,53 @@ ++#!/bin/bash ++# ++# This script serves following purpose: ++# ++# 1. It generates native version information by querying ++# automerger maintained database to see where src/include ++# came from ++# 2. For select components, as listed in compvers.sh ++# it generates component version files ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: Makefile 241686 2011-02-19 00:22:45Z $ ++# ++ ++SRCBASE := .. ++ ++TARGETS := epivers.h ++ ++ifdef VERBOSE ++export VERBOSE ++endif ++ ++all release: epivers compvers ++ ++# Generate epivers.h for native branch version ++epivers: ++ bash epivers.sh ++ ++# Generate epivers.h for native branch version ++compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "Generating component versions, if any"; \ ++ bash compvers.sh; \ ++ else \ ++ echo "Skipping component version generation"; \ ++ fi ++ ++# Generate epivers.h for native branch version ++clean_compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "bash compvers.sh clean"; \ ++ bash compvers.sh clean; \ ++ else \ ++ echo "Skipping component version clean"; \ ++ fi ++ ++clean: ++ rm -f $(TARGETS) *.prev ++ ++clean_all: clean clean_compvers ++ ++.PHONY: all release clean epivers compvers clean_compvers +diff --git a/drivers/bcmdrivers/gmac/src/include/aidmp.h b/drivers/bcmdrivers/gmac/src/include/aidmp.h +new file mode 100755 +index 0000000..a8fe0bc +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/aidmp.h +@@ -0,0 +1,383 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom AMBA Interconnect definitions. ++ * ++ * $Id: aidmp.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _AIDMP_H ++#define _AIDMP_H ++ ++/* Manufacturer Ids */ ++#define MFGID_ARM 0x43b ++#define MFGID_BRCM 0x4bf ++#define MFGID_MIPS 0x4a7 ++ ++/* Component Classes */ ++#define CC_SIM 0 ++#define CC_EROM 1 ++#define CC_CORESIGHT 9 ++#define CC_VERIF 0xb ++#define CC_OPTIMO 0xd ++#define CC_GEN 0xe ++#define CC_PRIMECELL 0xf ++ ++/* Enumeration ROM registers */ ++#define ER_EROMENTRY 0x000 ++#define ER_REMAPCONTROL 0xe00 ++#define ER_REMAPSELECT 0xe04 ++#define ER_MASTERSELECT 0xe10 ++#define ER_ITCR 0xf00 ++#define ER_ITIP 0xf04 ++ ++/* Erom entries */ ++#define ER_TAG 0xe ++#define ER_TAG1 0x6 ++#define ER_VALID 1 ++#define ER_CI 0 ++#define ER_MP 2 ++#define ER_ADD 4 ++#define ER_END 0xe ++#define ER_BAD 0xffffffff ++ ++/* EROM CompIdentA */ ++#define CIA_MFG_MASK 0xfff00000 ++#define CIA_MFG_SHIFT 20 ++#define CIA_CID_MASK 0x000fff00 ++#define CIA_CID_SHIFT 8 ++#define CIA_CCL_MASK 0x000000f0 ++#define CIA_CCL_SHIFT 4 ++ ++/* EROM CompIdentB */ ++#define CIB_REV_MASK 0xff000000 ++#define CIB_REV_SHIFT 24 ++#define CIB_NSW_MASK 0x00f80000 ++#define CIB_NSW_SHIFT 19 ++#define CIB_NMW_MASK 0x0007c000 ++#define CIB_NMW_SHIFT 14 ++#define CIB_NSP_MASK 0x00003e00 ++#define CIB_NSP_SHIFT 9 ++#define CIB_NMP_MASK 0x000001f0 ++#define CIB_NMP_SHIFT 4 ++ ++/* EROM MasterPortDesc */ ++#define MPD_MUI_MASK 0x0000ff00 ++#define MPD_MUI_SHIFT 8 ++#define MPD_MP_MASK 0x000000f0 ++#define MPD_MP_SHIFT 4 ++ ++/* EROM AddrDesc */ ++#define AD_ADDR_MASK 0xfffff000 ++#define AD_SP_MASK 0x00000f00 ++#define AD_SP_SHIFT 8 ++#define AD_ST_MASK 0x000000c0 ++#define AD_ST_SHIFT 6 ++#define AD_ST_SLAVE 0x00000000 ++#define AD_ST_BRIDGE 0x00000040 ++#define AD_ST_SWRAP 0x00000080 ++#define AD_ST_MWRAP 0x000000c0 ++#define AD_SZ_MASK 0x00000030 ++#define AD_SZ_SHIFT 4 ++#define AD_SZ_4K 0x00000000 ++#define AD_SZ_8K 0x00000010 ++#define AD_SZ_16K 0x00000020 ++#define AD_SZ_SZD 0x00000030 ++#define AD_AG32 0x00000008 ++#define AD_ADDR_ALIGN 0x00000fff ++#define AD_SZ_BASE 0x00001000 /* 4KB */ ++ ++/* EROM SizeDesc */ ++#define SD_SZ_MASK 0xfffff000 ++#define SD_SG32 0x00000008 ++#define SD_SZ_ALIGN 0x00000fff ++ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _aidmp { ++ uint32 oobselina30; /* 0x000 */ ++ uint32 oobselina74; /* 0x004 */ ++ uint32 PAD[6]; ++ uint32 oobselinb30; /* 0x020 */ ++ uint32 oobselinb74; /* 0x024 */ ++ uint32 PAD[6]; ++ uint32 oobselinc30; /* 0x040 */ ++ uint32 oobselinc74; /* 0x044 */ ++ uint32 PAD[6]; ++ uint32 oobselind30; /* 0x060 */ ++ uint32 oobselind74; /* 0x064 */ ++ uint32 PAD[38]; ++ uint32 oobselouta30; /* 0x100 */ ++ uint32 oobselouta74; /* 0x104 */ ++ uint32 PAD[6]; ++ uint32 oobseloutb30; /* 0x120 */ ++ uint32 oobseloutb74; /* 0x124 */ ++ uint32 PAD[6]; ++ uint32 oobseloutc30; /* 0x140 */ ++ uint32 oobseloutc74; /* 0x144 */ ++ uint32 PAD[6]; ++ uint32 oobseloutd30; /* 0x160 */ ++ uint32 oobseloutd74; /* 0x164 */ ++ uint32 PAD[38]; ++ uint32 oobsynca; /* 0x200 */ ++ uint32 oobseloutaen; /* 0x204 */ ++ uint32 PAD[6]; ++ uint32 oobsyncb; /* 0x220 */ ++ uint32 oobseloutben; /* 0x224 */ ++ uint32 PAD[6]; ++ uint32 oobsyncc; /* 0x240 */ ++ uint32 oobseloutcen; /* 0x244 */ ++ uint32 PAD[6]; ++ uint32 oobsyncd; /* 0x260 */ ++ uint32 oobseloutden; /* 0x264 */ ++ uint32 PAD[38]; ++ uint32 oobaextwidth; /* 0x300 */ ++ uint32 oobainwidth; /* 0x304 */ ++ uint32 oobaoutwidth; /* 0x308 */ ++ uint32 PAD[5]; ++ uint32 oobbextwidth; /* 0x320 */ ++ uint32 oobbinwidth; /* 0x324 */ ++ uint32 oobboutwidth; /* 0x328 */ ++ uint32 PAD[5]; ++ uint32 oobcextwidth; /* 0x340 */ ++ uint32 oobcinwidth; /* 0x344 */ ++ uint32 oobcoutwidth; /* 0x348 */ ++ uint32 PAD[5]; ++ uint32 oobdextwidth; /* 0x360 */ ++ uint32 oobdinwidth; /* 0x364 */ ++ uint32 oobdoutwidth; /* 0x368 */ ++ uint32 PAD[37]; ++ uint32 ioctrlset; /* 0x400 */ ++ uint32 ioctrlclear; /* 0x404 */ ++ uint32 ioctrl; /* 0x408 */ ++ uint32 PAD[61]; ++ uint32 iostatus; /* 0x500 */ ++ uint32 PAD[127]; ++ uint32 ioctrlwidth; /* 0x700 */ ++ uint32 iostatuswidth; /* 0x704 */ ++ uint32 PAD[62]; ++ uint32 resetctrl; /* 0x800 */ ++ uint32 resetstatus; /* 0x804 */ ++ uint32 resetreadid; /* 0x808 */ ++ uint32 resetwriteid; /* 0x80c */ ++ uint32 PAD[60]; ++ uint32 errlogctrl; /* 0x900 */ ++ uint32 errlogdone; /* 0x904 */ ++ uint32 errlogstatus; /* 0x908 */ ++ uint32 errlogaddrlo; /* 0x90c */ ++ uint32 errlogaddrhi; /* 0x910 */ ++ uint32 errlogid; /* 0x914 */ ++ uint32 errloguser; /* 0x918 */ ++ uint32 errlogflags; /* 0x91c */ ++ uint32 PAD[56]; ++ uint32 intstatus; /* 0xa00 */ ++ uint32 PAD[255]; ++ uint32 config; /* 0xe00 */ ++ uint32 PAD[63]; ++ uint32 itcr; /* 0xf00 */ ++ uint32 PAD[3]; ++ uint32 itipooba; /* 0xf10 */ ++ uint32 itipoobb; /* 0xf14 */ ++ uint32 itipoobc; /* 0xf18 */ ++ uint32 itipoobd; /* 0xf1c */ ++ uint32 PAD[4]; ++ uint32 itipoobaout; /* 0xf30 */ ++ uint32 itipoobbout; /* 0xf34 */ ++ uint32 itipoobcout; /* 0xf38 */ ++ uint32 itipoobdout; /* 0xf3c */ ++ uint32 PAD[4]; ++ uint32 itopooba; /* 0xf50 */ ++ uint32 itopoobb; /* 0xf54 */ ++ uint32 itopoobc; /* 0xf58 */ ++ uint32 itopoobd; /* 0xf5c */ ++ uint32 PAD[4]; ++ uint32 itopoobain; /* 0xf70 */ ++ uint32 itopoobbin; /* 0xf74 */ ++ uint32 itopoobcin; /* 0xf78 */ ++ uint32 itopoobdin; /* 0xf7c */ ++ uint32 PAD[4]; ++ uint32 itopreset; /* 0xf90 */ ++ uint32 PAD[15]; ++ uint32 peripherialid4; /* 0xfd0 */ ++ uint32 peripherialid5; /* 0xfd4 */ ++ uint32 peripherialid6; /* 0xfd8 */ ++ uint32 peripherialid7; /* 0xfdc */ ++ uint32 peripherialid0; /* 0xfe0 */ ++ uint32 peripherialid1; /* 0xfe4 */ ++ uint32 peripherialid2; /* 0xfe8 */ ++ uint32 peripherialid3; /* 0xfec */ ++ uint32 componentid0; /* 0xff0 */ ++ uint32 componentid1; /* 0xff4 */ ++ uint32 componentid2; /* 0xff8 */ ++ uint32 componentid3; /* 0xffc */ ++} aidmp_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Out-of-band Router registers */ ++#define OOB_BUSCONFIG 0x020 ++#define OOB_STATUSA 0x100 ++#define OOB_STATUSB 0x104 ++#define OOB_STATUSC 0x108 ++#define OOB_STATUSD 0x10c ++#define OOB_ENABLEA0 0x200 ++#define OOB_ENABLEA1 0x204 ++#define OOB_ENABLEA2 0x208 ++#define OOB_ENABLEA3 0x20c ++#define OOB_ENABLEB0 0x280 ++#define OOB_ENABLEB1 0x284 ++#define OOB_ENABLEB2 0x288 ++#define OOB_ENABLEB3 0x28c ++#define OOB_ENABLEC0 0x300 ++#define OOB_ENABLEC1 0x304 ++#define OOB_ENABLEC2 0x308 ++#define OOB_ENABLEC3 0x30c ++#define OOB_ENABLED0 0x380 ++#define OOB_ENABLED1 0x384 ++#define OOB_ENABLED2 0x388 ++#define OOB_ENABLED3 0x38c ++#define OOB_ITCR 0xf00 ++#define OOB_ITIPOOBA 0xf10 ++#define OOB_ITIPOOBB 0xf14 ++#define OOB_ITIPOOBC 0xf18 ++#define OOB_ITIPOOBD 0xf1c ++#define OOB_ITOPOOBA 0xf30 ++#define OOB_ITOPOOBB 0xf34 ++#define OOB_ITOPOOBC 0xf38 ++#define OOB_ITOPOOBD 0xf3c ++ ++/* DMP wrapper registers */ ++#define AI_OOBSELINA30 0x000 ++#define AI_OOBSELINA74 0x004 ++#define AI_OOBSELINB30 0x020 ++#define AI_OOBSELINB74 0x024 ++#define AI_OOBSELINC30 0x040 ++#define AI_OOBSELINC74 0x044 ++#define AI_OOBSELIND30 0x060 ++#define AI_OOBSELIND74 0x064 ++#define AI_OOBSELOUTA30 0x100 ++#define AI_OOBSELOUTA74 0x104 ++#define AI_OOBSELOUTB30 0x120 ++#define AI_OOBSELOUTB74 0x124 ++#define AI_OOBSELOUTC30 0x140 ++#define AI_OOBSELOUTC74 0x144 ++#define AI_OOBSELOUTD30 0x160 ++#define AI_OOBSELOUTD74 0x164 ++#define AI_OOBSYNCA 0x200 ++#define AI_OOBSELOUTAEN 0x204 ++#define AI_OOBSYNCB 0x220 ++#define AI_OOBSELOUTBEN 0x224 ++#define AI_OOBSYNCC 0x240 ++#define AI_OOBSELOUTCEN 0x244 ++#define AI_OOBSYNCD 0x260 ++#define AI_OOBSELOUTDEN 0x264 ++#define AI_OOBAEXTWIDTH 0x300 ++#define AI_OOBAINWIDTH 0x304 ++#define AI_OOBAOUTWIDTH 0x308 ++#define AI_OOBBEXTWIDTH 0x320 ++#define AI_OOBBINWIDTH 0x324 ++#define AI_OOBBOUTWIDTH 0x328 ++#define AI_OOBCEXTWIDTH 0x340 ++#define AI_OOBCINWIDTH 0x344 ++#define AI_OOBCOUTWIDTH 0x348 ++#define AI_OOBDEXTWIDTH 0x360 ++#define AI_OOBDINWIDTH 0x364 ++#define AI_OOBDOUTWIDTH 0x368 ++ ++#if defined(IL_BIGENDIAN) && defined(BCMHND74K) ++/* Selective swapped defines for those registers we need in ++ * big-endian code. ++ */ ++#define AI_IOCTRLSET 0x404 ++#define AI_IOCTRLCLEAR 0x400 ++#define AI_IOCTRL 0x40c ++#define AI_IOSTATUS 0x504 ++#define AI_RESETCTRL 0x804 ++#define AI_RESETSTATUS 0x800 ++ ++#else /* !IL_BIGENDIAN || !BCMHND74K */ ++ ++#define AI_IOCTRLSET 0x400 ++#define AI_IOCTRLCLEAR 0x404 ++#define AI_IOCTRL 0x408 ++#define AI_IOSTATUS 0x500 ++#define AI_RESETCTRL 0x800 ++#define AI_RESETSTATUS 0x804 ++ ++#endif /* IL_BIGENDIAN && BCMHND74K */ ++ ++#define AI_IOCTRLWIDTH 0x700 ++#define AI_IOSTATUSWIDTH 0x704 ++ ++#define AI_RESETREADID 0x808 ++#define AI_RESETWRITEID 0x80c ++#define AI_ERRLOGCTRL 0xa00 ++#define AI_ERRLOGDONE 0xa04 ++#define AI_ERRLOGSTATUS 0xa08 ++#define AI_ERRLOGADDRLO 0xa0c ++#define AI_ERRLOGADDRHI 0xa10 ++#define AI_ERRLOGID 0xa14 ++#define AI_ERRLOGUSER 0xa18 ++#define AI_ERRLOGFLAGS 0xa1c ++#define AI_INTSTATUS 0xa00 ++#define AI_CONFIG 0xe00 ++#define AI_ITCR 0xf00 ++#define AI_ITIPOOBA 0xf10 ++#define AI_ITIPOOBB 0xf14 ++#define AI_ITIPOOBC 0xf18 ++#define AI_ITIPOOBD 0xf1c ++#define AI_ITIPOOBAOUT 0xf30 ++#define AI_ITIPOOBBOUT 0xf34 ++#define AI_ITIPOOBCOUT 0xf38 ++#define AI_ITIPOOBDOUT 0xf3c ++#define AI_ITOPOOBA 0xf50 ++#define AI_ITOPOOBB 0xf54 ++#define AI_ITOPOOBC 0xf58 ++#define AI_ITOPOOBD 0xf5c ++#define AI_ITOPOOBAIN 0xf70 ++#define AI_ITOPOOBBIN 0xf74 ++#define AI_ITOPOOBCIN 0xf78 ++#define AI_ITOPOOBDIN 0xf7c ++#define AI_ITOPRESET 0xf90 ++#define AI_PERIPHERIALID4 0xfd0 ++#define AI_PERIPHERIALID5 0xfd4 ++#define AI_PERIPHERIALID6 0xfd8 ++#define AI_PERIPHERIALID7 0xfdc ++#define AI_PERIPHERIALID0 0xfe0 ++#define AI_PERIPHERIALID1 0xfe4 ++#define AI_PERIPHERIALID2 0xfe8 ++#define AI_PERIPHERIALID3 0xfec ++#define AI_COMPONENTID0 0xff0 ++#define AI_COMPONENTID1 0xff4 ++#define AI_COMPONENTID2 0xff8 ++#define AI_COMPONENTID3 0xffc ++ ++/* resetctrl */ ++#define AIRC_RESET 1 ++ ++/* config */ ++#define AICFG_OOB 0x00000020 ++#define AICFG_IOS 0x00000010 ++#define AICFG_IOC 0x00000008 ++#define AICFG_TO 0x00000004 ++#define AICFG_ERRL 0x00000002 ++#define AICFG_RST 0x00000001 ++ ++/* bit defines for AI_OOBSELOUTB74 reg */ ++#define OOB_SEL_OUTEN_B_5 15 ++#define OOB_SEL_OUTEN_B_6 23 ++ ++#endif /* _AIDMP_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/arminc.h b/drivers/bcmdrivers/gmac/src/include/arminc.h +new file mode 100755 +index 0000000..a0f2401 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/arminc.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND Run Time Environment for standalone ARM programs. ++ * ++ * $Id: arminc.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _ARMINC_H ++#define _ARMINC_H ++ ++ ++/* ARM defines */ ++ ++#ifdef _LANGUAGE_ASSEMBLY ++ ++/* ++ * LEAF - declare leaf routine ++ */ ++#define LEAF(function) \ ++ .section .text.function, "ax"; \ ++ .global function; \ ++ .func function; \ ++function: ++ ++#define THUMBLEAF(function) \ ++ .section .text.function, "ax"; \ ++ .global function; \ ++ .func function; \ ++ .thumb; \ ++ .thumb_func; \ ++function: ++ ++/* ++ * END - mark end of function ++ */ ++#define END(function) \ ++ .ltorg; \ ++ .endfunc; \ ++ .size function, . - function ++ ++#define DW(var, val) \ ++ .global var; \ ++ .type var, %object; \ ++ .size var, 4; \ ++ .align 2; \ ++var: .word val ++ ++ ++#define _ULCAST_ ++ ++#else ++ ++/* ++ * The following macros are especially useful for __asm__ ++ * inline assembler. ++ */ ++#ifndef __STR ++#define __STR(x) #x ++#endif ++#ifndef STR ++#define STR(x) __STR(x) ++#endif ++ ++#define _ULCAST_ (unsigned long) ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++ ++#if defined(__ARM_ARCH_7M__) /* Cortex-M3 */ ++ ++/* Data Watchpoint and Trigger */ ++#define CM3_DWT_CTRL 0xe0001000 ++#define CM3_DWT_CYCCNT 0xe0001004 ++#define CM3_DWT_CPICNT 0xe0001008 ++#define CM3_DWT_EXCCNT 0xe000100c ++#define CM3_DWT_SLEEPCNT 0xe0001010 ++#define CM3_DWT_LSUCNT 0xe0001014 ++#define CM3_DWT_FOLDCNT 0xe0001018 ++#define CM3_DWT_COMP0 0xe0001020 ++#define CM3_DWT_MASK0 0xe0001024 ++#define CM3_DWT_FUNCTION0 0xe0001028 ++#define CM3_DWT_COMP1 0xe0001030 ++#define CM3_DWT_MASK1 0xe0001034 ++#define CM3_DWT_FUNCTION1 0xe0001038 ++#define CM3_DWT_COMP2 0xe0001040 ++#define CM3_DWT_MASK2 0xe0001044 ++#define CM3_DWT_FUNCTION2 0xe0001048 ++#define CM3_DWT_COMP3 0xe0001050 ++#define CM3_DWT_MASK3 0xe0001054 ++#define CM3_DWT_FUNCTION3 0xe0001058 ++ ++#define CM3_DWT_FUNCTION_DISAB 0 ++#define CM3_DWT_FUNCTION_WP_PCMATCH 4 ++#define CM3_DWT_FUNCTION_WP_READ 5 ++#define CM3_DWT_FUNCTION_WP_WRITE 6 ++#define CM3_DWT_FUNCTION_WP_RDWR 7 ++ ++#define CM3_NVIC_IC_TYPE 0xe000e004 /* Interrupt Control Type Reg */ ++#define CM3_NVIC_TICK_CSR 0xe000e010 /* SysTick Control and Status Reg */ ++#define CM3_NVIC_TICK_CSR_COUNTFLAG 0x10000 ++#define CM3_NVIC_TICK_CSR_CLKSOURCE 0x4 /* Set for core clock, 0 for ext ref */ ++#define CM3_NVIC_TICK_CSR_TICKINT 0x2 /* Set for intr on count going 1 => 0 */ ++#define CM3_NVIC_TICK_CSR_ENABLE 0x1 ++#define CM3_NVIC_TICK_RLDVAL 0xe000e014 /* SysTick Reload Value Reg */ ++#define CM3_NVIC_TICK_CURVAL 0xe000e018 /* SysTick Current Value Reg */ ++#define CM3_NVIC_TICK_CALVAL 0xe000e01c /* SysTick Calibration Value Reg */ ++ ++/* Interrupt enable/disable register */ ++#define CM3_NVIC_IRQ_SET_EN0 0xe000e100 /* Irq 0 to 31 Set Enable Reg */ ++#define CM3_NVIC_IRQ_SET_EN(n) (0xe000e100 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_CLR_EN0 0xe000e180 /* Irq 0 to 31 Clear Enable Reg [...] */ ++#define CM3_NVIC_IRQ_CLR_EN(n) (0xe000e180 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_SET_PND0 0xe000e200 /* Irq 0 to 31 Set Pending Reg [...] */ ++#define CM3_NVIC_IRQ_SET_PND(n) (0xe000e200 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_CLR_PND0 0xe000e280 /* Irq 0 to 31 Clear Pending Reg [...] */ ++#define CM3_NVIC_IRQ_CLR_PND(n) (0xe000e280 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_ACT_BIT0 0xe000e300 /* Irq 0 to 31 Active Bit Reg [...] */ ++#define CM3_NVIC_IRQ_ACT_BIT(n) (0xe000e300 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++#define CM3_NVIC_IRQ_PRIO0 0xe000e400 /* Irq 0 to 31 Priority Reg [...] */ ++#define CM3_NVIC_IRQ_PRIO(n) (0xe000e400 + (n) * 4) /* Irq 0-31, 32-63, ..., 224-239 */ ++ ++/* CPU control */ ++#define CM3_CPUID 0xe000ed00 ++#define CM3_INTCTLSTATE 0xe000ed04 ++#define CM3_VTOFF 0xe000ed08 /* Vector Table Offset */ ++#define CM3_SYSCTRL 0xe000ed10 ++#define CM3_CFGCTRL 0xe000ed14 ++#define CM3_CFGCTRL_UNALIGN_TRP 0x8 ++#define CM3_CFGCTRL_DIV_0_TRP 0x10 ++#define CM3_CFGCTRL_STKALIGN 0x200 ++ ++#define CM3_PFR0 0xe000ed40 ++#define CM3_PFR1 0xe000ed44 ++#define CM3_DFR0 0xe000ed48 ++#define CM3_AFR0 0xe000ed4c ++#define CM3_MMFR0 0xe000ed50 ++#define CM3_MMFR1 0xe000ed54 ++#define CM3_MMFR2 0xe000ed58 ++#define CM3_MMFR3 0xe000ed5c ++#define CM3_ISAR0 0xe000ed60 ++#define CM3_ISAR1 0xe000ed64 ++#define CM3_ISAR2 0xe000ed68 ++#define CM3_ISAR3 0xe000ed6c ++#define CM3_ISAR4 0xe000ed70 ++#define CM3_ISAR5 0xe000ed74 ++ ++#define CM3_MPUTYPE 0xe000ed90 ++#define CM3_MPUCTRL 0xe000ed94 ++#define CM3_REGNUM 0xe000ed98 ++#define CM3_REGBAR 0xe000ed9c ++#define CM3_REGASZ 0xe000eda0 ++#define CM3_AL1BAR 0xe000eda4 ++#define CM3_AL1ASZ 0xe000eda8 ++#define CM3_AL2BAR 0xe000edac ++#define CM3_AL2ASZ 0xe000edb0 ++#define CM3_AL3BAR 0xe000edb4 ++#define CM3_AL3ASZ 0xe000edb8 ++ ++#define CM3_DBG_HCSR 0xe000edf0 /* Debug Halting Control and Status Reg */ ++#define CM3_DBG_CRSR 0xe000edf4 /* Debug Core Register Selector Reg */ ++#define CM3_DBG_CRDR 0xe000edf8 /* Debug Core Register Data Reg */ ++#define CM3_DBG_EMCR 0xe000edfc /* Debug Exception and Monitor Control Reg */ ++#define CM3_DBG_EMCR_TRCENA (1U << 24) ++#define CM3_DBG_EMCR_MON_EN (1U << 16) ++ ++/* Trap types */ ++#define TR_RST 1 /* Reset */ ++#define TR_NMI 2 /* NMI */ ++#define TR_FAULT 3 /* Hard Fault */ ++#define TR_MM 4 /* Memory Management */ ++#define TR_BUS 5 /* Bus Fault */ ++#define TR_USAGE 6 /* Usage Fault */ ++#define TR_SVC 11 /* SVCall */ ++#define TR_DMON 12 /* Debug Monitor */ ++#define TR_PENDSV 14 /* PendSV */ ++#define TR_SYSTICK 15 /* SysTick */ ++#define TR_ISR 16 /* External Interrupts start here */ ++ ++#define TR_BAD 256 /* Bad trap: Not used by CM3 */ ++ ++/* Offsets of automatically saved registers from sp upon trap */ ++#define CM3_TROFF_R0 0 ++#define CM3_TROFF_R1 4 ++#define CM3_TROFF_R2 8 ++#define CM3_TROFF_R3 12 ++#define CM3_TROFF_R12 16 ++#define CM3_TROFF_LR 20 ++#define CM3_TROFF_PC 24 ++#define CM3_TROFF_xPSR 28 ++ ++#elif defined(__ARM_ARCH_7A__) /* Cortex-A9 */ ++/* Fields in cpsr */ ++#define PS_USR 0x00000010 /* Mode: User */ ++#define PS_FIQ 0x00000011 /* Mode: FIQ */ ++#define PS_IRQ 0x00000012 /* Mode: IRQ */ ++#define PS_SVC 0x00000013 /* Mode: Supervisor */ ++#define PS_ABT 0x00000017 /* Mode: Abort */ ++#define PS_UND 0x0000001b /* Mode: Undefined */ ++#define PS_SYS 0x0000001f /* Mode: System */ ++#define PS_MM 0x0000001f /* Mode bits mask */ ++#define PS_T 0x00000020 /* Thumb mode */ ++#define PS_F 0x00000040 /* FIQ disable */ ++#define PS_I 0x00000080 /* IRQ disable */ ++#define PS_A 0x00000100 /* Imprecise abort */ ++#define PS_E 0x00000200 /* Endianess */ ++#define PS_IT72 0x0000fc00 /* IT[7:2] */ ++#define PS_GE 0x000f0000 /* IT[7:2] */ ++#define PS_J 0x01000000 /* Java state */ ++#define PS_IT10 0x06000000 /* IT[1:0] */ ++#define PS_Q 0x08000000 /* Sticky overflow */ ++#define PS_V 0x10000000 /* Overflow cc */ ++#define PS_C 0x20000000 /* Carry cc */ ++#define PS_Z 0x40000000 /* Zero cc */ ++#define PS_N 0x80000000 /* Negative cc */ ++ ++/* Trap types */ ++#define TR_RST 0 /* Reset trap */ ++#define TR_UND 1 /* Indefined instruction trap */ ++#define TR_SWI 2 /* Software intrrupt */ ++#define TR_IAB 3 /* Instruction fetch abort */ ++#define TR_DAB 4 /* Data access abort */ ++#define TR_BAD 5 /* Bad trap: Not used by ARM */ ++#define TR_IRQ 6 /* Interrupt */ ++#define TR_FIQ 7 /* Fast interrupt */ ++ ++/* ++ * Memory segments (32bit kernel mode addresses) ++ */ ++#define PHYSADDR_MASK 0xffffffff ++ ++/* ++ * Map an address to a certain kernel segment ++ */ ++#undef PHYSADDR ++#define PHYSADDR(a) (_ULCAST_(a) & PHYSADDR_MASK) ++#else /* !__ARM_ARCH_7M__ */ ++ ++/* Fields in cpsr */ ++#define PS_USR 0x00000010 /* Mode: User */ ++#define PS_FIQ 0x00000011 /* Mode: FIQ */ ++#define PS_IRQ 0x00000012 /* Mode: IRQ */ ++#define PS_SVC 0x00000013 /* Mode: Supervisor */ ++#define PS_ABT 0x00000017 /* Mode: Abort */ ++#define PS_UND 0x0000001b /* Mode: Undefined */ ++#define PS_SYS 0x0000001f /* Mode: System */ ++#define PS_MM 0x0000001f /* Mode bits mask */ ++#define PS_T 0x00000020 /* Thumb mode */ ++#define PS_F 0x00000040 /* FIQ disable */ ++#define PS_I 0x00000080 /* IRQ disable */ ++#define PS_A 0x00000100 /* Imprecise abort */ ++#define PS_E 0x00000200 /* Endianess */ ++#define PS_IT72 0x0000fc00 /* IT[7:2] */ ++#define PS_GE 0x000f0000 /* IT[7:2] */ ++#define PS_J 0x01000000 /* Java state */ ++#define PS_IT10 0x06000000 /* IT[1:0] */ ++#define PS_Q 0x08000000 /* Sticky overflow */ ++#define PS_V 0x10000000 /* Overflow cc */ ++#define PS_C 0x20000000 /* Carry cc */ ++#define PS_Z 0x40000000 /* Zero cc */ ++#define PS_N 0x80000000 /* Negative cc */ ++ ++/* Trap types */ ++#define TR_RST 0 /* Reset trap */ ++#define TR_UND 1 /* Indefined instruction trap */ ++#define TR_SWI 2 /* Software intrrupt */ ++#define TR_IAB 3 /* Instruction fetch abort */ ++#define TR_DAB 4 /* Data access abort */ ++#define TR_BAD 5 /* Bad trap: Not used by ARM */ ++#define TR_IRQ 6 /* Interrupt */ ++#define TR_FIQ 7 /* Fast interrupt */ ++ ++#ifdef BCMDBG_ARMRST ++#define TR_ARMRST 0xF /* Debug facility to trap Arm reset */ ++#endif ++ ++/* used to fill an overlay region with nop's */ ++#define NOP_UINT32 0x46c046c0 ++ ++ ++#define mrc(cp, a, b, n) \ ++({ \ ++ int __res; \ ++ __asm__ __volatile__("\tmrc\tp"STR(cp)", 0, %0, c"STR(a)", c"STR(b)", "STR(n) \ ++ :"=r" (__res)); \ ++ __res; \ ++}) ++ ++ ++#endif /* !__ARM_ARCH_7M__ */ ++ ++/* Pieces of a CPU Id */ ++#define CID_IMPL 0xff000000 /* Implementor: 0x41 for ARM Ltd. */ ++#define CID_VARIANT 0x00f00000 ++#define CID_ARCH 0x000f0000 ++#define CID_PART 0x0000fff0 ++#define CID_REV 0x0000000f ++#define CID_MASK (CID_IMPL | CID_ARCH | CID_PART) ++ ++#endif /* _ARMINC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h b/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h +new file mode 100755 +index 0000000..8219b8b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcm_cfg.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM common config options ++ * ++ * $Id: bcm_cfg.h 294399 2011-11-07 03:31:22Z $ ++ */ ++ ++#ifndef _bcm_cfg_h_ ++#define _bcm_cfg_h_ ++#if defined(__NetBSD__) || defined(__FreeBSD__) ++#if defined(_KERNEL) ++#include ++#endif /* defined(_KERNEL) */ ++#endif /* defined(__NetBSD__) || defined(__FreeBSD__) */ ++#endif /* _bcm_cfg_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h b/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h +new file mode 100755 +index 0000000..7a1f01d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcm_mpool_pub.h +@@ -0,0 +1,355 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Memory pools library, Public interface ++ * ++ * API Overview ++ * ++ * This package provides a memory allocation subsystem based on pools of ++ * homogenous objects. ++ * ++ * Instrumentation is available for reporting memory utilization both ++ * on a per-data-structure basis and system wide. ++ * ++ * There are two main types defined in this API. ++ * ++ * pool manager: A singleton object that acts as a factory for ++ * pool allocators. It also is used for global ++ * instrumentation, such as reporting all blocks ++ * in use across all data structures. The pool manager ++ * creates and provides individual memory pools ++ * upon request to application code. ++ * ++ * memory pool: An object for allocating homogenous memory blocks. ++ * ++ * Global identifiers in this module use the following prefixes: ++ * bcm_mpm_* Memory pool manager ++ * bcm_mp_* Memory pool ++ * ++ * There are two main types of memory pools: ++ * ++ * prealloc: The contiguous memory block of objects can either be supplied ++ * by the client or malloc'ed by the memory manager. The objects are ++ * allocated out of a block of memory and freed back to the block. ++ * ++ * heap: The memory pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing statistics ++ * and instrumentation on top of the heap, without modifying the heap ++ * allocation implementation. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _BCM_MPOOL_PUB_H ++#define _BCM_MPOOL_PUB_H 1 ++ ++#include /* needed for uint16 */ ++ ++ ++/* ++************************************************************************** ++* ++* Type definitions, handles ++* ++************************************************************************** ++*/ ++ ++/* Forward declaration of OSL handle. */ ++struct osl_info; ++ ++/* Forward declaration of string buffer. */ ++struct bcmstrbuf; ++ ++/* ++ * Opaque type definition for the pool manager handle. This object is used for global ++ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and ++ * instrumentation/debugging. ++ */ ++struct bcm_mpm_mgr; ++typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; ++ ++/* ++ * Opaque type definition for an instance of a pool. This handle is used for allocating ++ * and freeing memory through the pool, as well as management/instrumentation on this ++ * specific pool. ++ */ ++struct bcm_mp_pool; ++typedef struct bcm_mp_pool *bcm_mp_pool_h; ++ ++ ++/* ++ * To make instrumentation more readable, every memory ++ * pool must have a readable name. Pool names are up to ++ * 8 bytes including '\0' termination. (7 printable characters.) ++ */ ++#define BCM_MP_NAMELEN 8 ++ ++ ++/* ++ * Type definition for pool statistics. ++ */ ++typedef struct bcm_mp_stats { ++ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ ++ unsigned int objsz; /* Object size allocated in this pool */ ++ uint16 nobj; /* Total number of objects in this pool */ ++ uint16 num_alloc; /* Number of objects currently allocated */ ++ uint16 high_water; /* Max number of allocated objects. */ ++ uint16 failed_alloc; /* Failed allocations. */ ++} bcm_mp_stats_t; ++ ++ ++/* ++************************************************************************** ++* ++* API Routines on the pool manager. ++* ++************************************************************************** ++*/ ++ ++/* ++ * bcm_mpm_init() - initialize the whole memory pool system. ++ * ++ * Parameters: ++ * osh: INPUT Operating system handle. Needed for heap memory allocation. ++ * max_pools: INPUT Maximum number of mempools supported. ++ * mgr: OUTPUT The handle is written with the new pools manager object/handle. ++ * ++ * Returns: ++ * BCME_OK Object initialized successfully. May be used. ++ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. ++ */ ++int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); ++ ++ ++/* ++ * bcm_mpm_deinit() - de-initialize the whole memory pool system. ++ * ++ * Parameters: ++ * mgr: INPUT Pointer to pool manager handle. ++ * ++ * Returns: ++ * BCME_OK Memory pool manager successfully de-initialized. ++ * other Indicated error occured during de-initialization. ++ */ ++int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); ++ ++/* ++ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The ++ * pool uses a contiguous block of pre-alloced ++ * memory. The memory block may either be provided ++ * by the client or dynamically allocated by the ++ * pool manager. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * Must be >= sizeof(void *). ++ * nobj: INPUT Maximum number of concurrently existing objects to support ++ * memstart INPUT Pointer to the memory to use, or NULL to malloc() ++ * memsize INPUT Number of bytes referenced from memstart (for error checking). ++ * Must be 0 if 'memstart' is NULL. ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, ++ unsigned int obj_sz, ++ int nobj, ++ void *memstart, ++ unsigned int memsize, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++/* ++ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory ++ * pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing ++ * statistics and instrumentation on top of the heap, ++ * without modifying the heap allocation implementation. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++ ++/* ++ * bcm_mpm_stats() - Return stats for all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * stats: OUTPUT Array of pool statistics. ++ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number ++ * of array elements copied to 'stats' on OUTPUT. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting stats. ++ * ++ */ ++int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); ++ ++ ++/* ++ * bcm_mpm_dump() - Display statistics on all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * b: OUTPUT Output buffer. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); ++ ++ ++/* ++ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to ++ * compensate for alignment requirements of the objects. ++ * This function provides the padded object size. If clients ++ * pre-allocate a memory slab for a memory pool, the ++ * padded object size should be used by the client to allocate ++ * the memory slab (in order to provide sufficent space for ++ * the maximum number of objects). ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager. ++ * obj_sz: INPUT Input object size. ++ * padded_obj_sz: OUTPUT Padded object size. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * BCME_BADARG Bad arguments. ++ * ++ */ ++int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); ++ ++ ++/* ++*************************************************************************** ++* ++* API Routines on a specific pool. ++* ++*************************************************************************** ++*/ ++ ++ ++/* ++ * bcm_mp_alloc() - Allocate a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * ++ * Returns: ++ * A pointer to the new object. NULL on error. ++ * ++ */ ++void* bcm_mp_alloc(bcm_mp_pool_h pool); ++ ++/* ++ * bcm_mp_free() - Free a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * objp: INPUT A pointer to the object to free. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during free. ++ * ++ */ ++int bcm_mp_free(bcm_mp_pool_h pool, void *objp); ++ ++/* ++ * bcm_mp_stats() - Return stats for this pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * stats: OUTPUT Pool statistics ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting statistics. ++ * ++ */ ++int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); ++ ++ ++/* ++ * bcm_mp_dump() - Dump a pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * b OUTPUT Output buffer ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); ++ ++ ++#endif /* _BCM_MPOOL_PUB_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmcdc.h b/drivers/bcmdrivers/gmac/src/include/bcmcdc.h +new file mode 100755 +index 0000000..2b99cf1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmcdc.h +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * CDC network driver ioctl/indication encoding ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * $Id: bcmcdc.h 291086 2011-10-21 01:17:24Z $ ++ */ ++#ifndef _bcmcdc_h_ ++#define _bcmcdc_h_ ++#include ++ ++typedef struct cdc_ioctl { ++ uint32 cmd; /* ioctl command value */ ++ uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ ++ uint32 flags; /* flag defns given below */ ++ uint32 status; /* status code returned from the device */ ++} cdc_ioctl_t; ++ ++/* Max valid buffer size that can be sent to the dongle */ ++#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN ++ ++/* len field is divided into input and output buffer lengths */ ++#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */ ++ /* excluding IOCTL header */ ++#define CDCL_IOC_OUTLEN_SHIFT 0 ++#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */ ++#define CDCL_IOC_INLEN_SHIFT 16 ++ ++/* CDC flag definitions */ ++#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */ ++#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ ++#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */ ++#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */ ++#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */ ++#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */ ++#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */ ++#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ ++#define CDCF_IOC_IF_SHIFT 12 ++#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */ ++#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */ ++ ++#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT) ++#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) ++ ++#define CDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)) ++#define CDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT))) ++ ++/* ++ * BDC header ++ * ++ * The BDC header is used on data packets to convey priority across USB. ++ */ ++ ++#define BDC_HEADER_LEN 4 ++ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++#define BDC_PROTO_VER 2 /* Protocol version */ ++ ++#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ ++#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ ++ ++#define BDC_FLAG__UNUSED 0x03 /* Unassigned */ ++#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ ++#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ ++ ++#define BDC_PRIORITY_MASK 0x7 ++ ++#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */ ++ /* FLOW CONTROL info only */ ++#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */ ++ ++#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the packet was received */ ++#define BDC_FLAG2_IF_SHIFT 0 ++#define BDC_FLAG2_PAD_MASK 0xf0 ++#define BDC_FLAG_PAD_MASK 0x03 ++#define BDC_FLAG2_PAD_SHIFT 2 ++#define BDC_FLAG_PAD_SHIFT 0 ++#define BDC_FLAG2_PAD_IDX 0x3c ++#define BDC_FLAG_PAD_IDX 0x03 ++#define BDC_GET_PAD_LEN(hdr) \ ++ ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \ ++ ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT))) ++#define BDC_SET_PAD_LEN(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \ ++ (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \ ++ ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \ ++ (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) ++ ++#define BDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) ++#define BDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) ++ ++struct bdc_header { ++ uint8 flags; /* Flags */ ++ uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */ ++ uint8 flags2; ++ uint8 dataOffset; /* Offset from end of BDC header to packet data, in ++ * 4-byte words. Leaves room for optional headers. ++ */ ++}; ++ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++ ++#endif /* _bcmcdc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmdefs.h b/drivers/bcmdrivers/gmac/src/include/bcmdefs.h +new file mode 100755 +index 0000000..e2b9b0e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmdefs.h +@@ -0,0 +1,336 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc system wide definitions ++ * ++ * $Id: bcmdefs.h 316696 2012-02-23 03:29:35Z $ ++ */ ++ ++#ifndef _bcmdefs_h_ ++#define _bcmdefs_h_ ++ ++/* ++ * One doesn't need to include this file explicitly, gets included automatically if ++ * typedefs.h is included. ++ */ ++ ++/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function ++ * arguments or local variables. ++ */ ++#define BCM_REFERENCE(data) ((void)(data)) ++ ++/* Compile-time assert can be used in place of ASSERT if the expression evaluates ++ * to a constant at compile time. ++ */ ++#define STATIC_ASSERT(expr) { \ ++ /* Make sure the expression is constant. */ \ ++ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \ ++ /* Make sure the expression is true. */ \ ++ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \ ++} ++ ++/* Reclaiming text and data : ++ * The following macros specify special linker sections that can be reclaimed ++ * after a system is considered 'up'. ++ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN, ++ * as in most cases, the attach function calls the detach function to clean up on error). ++ */ ++#ifdef DONGLEBUILD ++ ++extern bool bcmreclaimed; ++extern bool attach_part_reclaimed; ++ ++#define BCMATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data ++#define BCMATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn ++ ++#ifndef PREATTACH_NORECLAIM ++#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini3." #_data))) _data ++#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini3." #_fn), noinline)) _fn ++#else ++#define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data ++#define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn ++#endif ++ ++#if defined(BCMRECLAIM) ++#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini1." #_data))) _data ++#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini1." #_fn), noinline)) _fn ++#define CONST ++#else ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define CONST const ++#endif ++ ++/* Non-manufacture or internal attach function/dat */ ++#if !defined(WLTEST) ++#define BCMNMIATTACHFN(_fn) BCMATTACHFN(_fn) ++#define BCMNMIATTACHDATA(_data) BCMATTACHDATA(_data) ++#else ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#endif ++ ++#define BCMUNINITFN(_fn) _fn ++ ++#define BCMFASTPATH ++#else /* DONGLEBUILD */ ++ ++#define bcmreclaimed 0 ++#define BCMATTACHDATA(_data) _data ++#define BCMATTACHFN(_fn) _fn ++#define BCMPREATTACHDATA(_data) _data ++#define BCMPREATTACHFN(_fn) _fn ++#define BCMINITDATA(_data) _data ++#define BCMINITFN(_fn) _fn ++#define BCMUNINITFN(_fn) _fn ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#define CONST const ++#if defined(__ARM_ARCH_7A__) ++#define BCM47XX_CA9 ++#else ++#undef BCM47XX_CA9 ++#endif ++#ifndef BCMFASTPATH ++#if defined(mips) || defined(BCM47XX_CA9) ++#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) ++#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) ++#else ++#define BCMFASTPATH ++#define BCMFASTPATH_HOST ++#endif ++#endif /* BCMFASTPATH */ ++ ++#endif /* DONGLEBUILD */ ++ ++#if defined(BCMROMBUILD) ++typedef struct { ++ uint16 esiz; ++ uint16 cnt; ++ void *addr; ++} bcmromdat_patch_t; ++#endif ++ ++/* Put some library data/code into ROM to reduce RAM requirements */ ++#if defined(BCMROMBUILD) && !defined(BCMROMSYMGEN_BUILD) && !defined(BCMJMPTBL_TCAM) ++#include ++#define STATIC static ++#else /* !BCMROMBUILD */ ++#define BCMROMDATA(_data) _data ++#define BCMROMDAT_NAME(_data) _data ++#define BCMROMFN(_fn) _fn ++#define BCMROMFN_NAME(_fn) _fn ++#define STATIC static ++#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) ++#define BCMROMDAT_SIZEOF(data) sizeof(data) ++#define BCMROMDAT_APATCH(data) ++#define BCMROMDAT_SPATCH(data) ++#endif /* !BCMROMBUILD */ ++ ++/* Bus types */ ++#define SI_BUS 0 /* SOC Interconnect */ ++#define PCI_BUS 1 /* PCI target */ ++#define PCMCIA_BUS 2 /* PCMCIA target */ ++#define SDIO_BUS 3 /* SDIO target */ ++#define JTAG_BUS 4 /* JTAG */ ++#define USB_BUS 5 /* USB (does not support R/W REG) */ ++#define SPI_BUS 6 /* gSPI target */ ++#define RPC_BUS 7 /* RPC target */ ++ ++/* Allows size optimization for single-bus image */ ++#ifdef BCMBUSTYPE ++#define BUSTYPE(bus) (BCMBUSTYPE) ++#else ++#define BUSTYPE(bus) (bus) ++#endif ++ ++/* Allows size optimization for single-backplane image */ ++#ifdef BCMCHIPTYPE ++#define CHIPTYPE(bus) (BCMCHIPTYPE) ++#else ++#define CHIPTYPE(bus) (bus) ++#endif ++ ++ ++/* Allows size optimization for SPROM support */ ++#if defined(BCMSPROMBUS) ++#define SPROMBUS (BCMSPROMBUS) ++#elif defined(SI_PCMCIA_SROM) ++#define SPROMBUS (PCMCIA_BUS) ++#else ++#define SPROMBUS (PCI_BUS) ++#endif ++ ++/* Allows size optimization for single-chip image */ ++#ifdef BCMCHIPID ++#define CHIPID(chip) (BCMCHIPID) ++#else ++#define CHIPID(chip) (chip) ++#endif ++ ++#ifdef BCMCHIPREV ++#define CHIPREV(rev) (BCMCHIPREV) ++#else ++#define CHIPREV(rev) (rev) ++#endif ++ ++/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ ++#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ ++#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ ++#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ ++ ++#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ ++#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ ++#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ ++#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ ++ ++#ifdef BCMDMA64OSL ++typedef struct { ++ uint32 loaddr; ++ uint32 hiaddr; ++} dma64addr_t; ++ ++typedef dma64addr_t dmaaddr_t; ++#define PHYSADDRHI(_pa) ((_pa).hiaddr) ++#define PHYSADDRHISET(_pa, _val) \ ++ do { \ ++ (_pa).hiaddr = (_val); \ ++ } while (0) ++#define PHYSADDRLO(_pa) ((_pa).loaddr) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa).loaddr = (_val); \ ++ } while (0) ++ ++#else ++typedef unsigned long dmaaddr_t; ++#define PHYSADDRHI(_pa) (0) ++#define PHYSADDRHISET(_pa, _val) ++#define PHYSADDRLO(_pa) ((_pa)) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa) = (_val); \ ++ } while (0) ++#endif /* BCMDMA64OSL */ ++ ++/* One physical DMA segment */ ++typedef struct { ++ dmaaddr_t addr; ++ uint32 length; ++} hnddma_seg_t; ++ ++#if defined(MACOSX) ++/* In MacOS, the OS API may return large number of segments. Setting this number lower ++ * will result in failure of dma map ++ */ ++#define MAX_DMA_SEGS 8 ++#elif defined(__NetBSD__) ++/* In NetBSD we also want more segments because the lower level mbuf mapping api might ++ * allocate a large number of segments ++ */ ++#define MAX_DMA_SEGS 16 ++#else ++#define MAX_DMA_SEGS 4 ++#endif ++ ++ ++typedef struct { ++ void *oshdmah; /* Opaque handle for OSL to store its information */ ++ uint origsize; /* Size of the virtual packet */ ++ uint nsegs; ++ hnddma_seg_t segs[MAX_DMA_SEGS]; ++} hnddma_seg_map_t; ++ ++ ++/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). ++ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this value is at least as big ++ * as TXOFF. This value is used in dma_rxfill (hnddma.c). ++ */ ++ ++#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) ++/* add 40 bytes to allow for extra RPC header and info */ ++#define BCMEXTRAHDROOM 260 ++#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++#ifdef CTFMAP ++#define BCMEXTRAHDROOM 208 ++#else /* CTFMAP */ ++#define BCMEXTRAHDROOM 204 ++#endif /* CTFMAP */ ++#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#ifndef SDALIGN ++#define SDALIGN 32 ++#endif ++ ++/* Headroom required for dongle-to-host communication. Packets allocated ++ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should ++ * leave this much room in front for low-level message headers which may ++ * be needed to get across the dongle bus to the host. (These messages ++ * don't go over the network, so room for the full WL header above would ++ * be a waste.). ++*/ ++#define BCMDONGLEHDRSZ 12 ++#define BCMDONGLEPADSZ 16 ++ ++#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) ++ ++#ifdef BCMDBG ++ ++#ifndef BCMDBG_ERR ++#define BCMDBG_ERR ++#endif /* BCMDBG_ERR */ ++ ++#define BCMDBG_ASSERT ++ ++#endif /* BCMDBG */ ++ ++ ++/* Macros for doing definition and get/set of bitfields ++ * Usage example, e.g. a three-bit field (bits 4-6): ++ * #define _M BITFIELD_MASK(3) ++ * #define _S 4 ++ * ... ++ * regval = R_REG(osh, ®s->regfoo); ++ * field = GFIELD(regval, ); ++ * regval = SFIELD(regval, , 1); ++ * W_REG(osh, ®s->regfoo, regval); ++ */ ++#define BITFIELD_MASK(width) \ ++ (((unsigned)1 << (width)) - 1) ++#define GFIELD(val, field) \ ++ (((val) >> field ## _S) & field ## _M) ++#define SFIELD(val, field, bits) \ ++ (((val) & (~(field ## _M << field ## _S))) | \ ++ ((unsigned)(bits) << field ## _S)) ++ ++/* define BCMSMALL to remove misc features for memory-constrained environments */ ++#ifdef BCMSMALL ++#undef BCMSPACE ++#define bcmspace FALSE /* if (bcmspace) code is discarded */ ++#else ++#define BCMSPACE ++#define bcmspace TRUE /* if (bcmspace) code is retained */ ++#endif ++ ++/* Max. nvram variable table size */ ++#define MAXSZ_NVRAM_VARS 4096 ++ ++#ifdef EFI ++#define __attribute__(x) /* CSTYLED */ ++#endif ++ ++#endif /* _bcmdefs_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmdevs.h b/drivers/bcmdrivers/gmac/src/include/bcmdevs.h +new file mode 100755 +index 0000000..39918b9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmdevs.h +@@ -0,0 +1,862 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom device-specific manifest constants. ++ * ++ * $Id: bcmdevs.h 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#ifndef _BCMDEVS_H ++#define _BCMDEVS_H ++ ++/* PCI vendor IDs */ ++#define VENDOR_EPIGRAM 0xfeda ++#define VENDOR_BROADCOM 0x14e4 ++#define VENDOR_3COM 0x10b7 ++#define VENDOR_NETGEAR 0x1385 ++#define VENDOR_DIAMOND 0x1092 ++#define VENDOR_INTEL 0x8086 ++#define VENDOR_DELL 0x1028 ++#define VENDOR_HP 0x103c ++#define VENDOR_HP_COMPAQ 0x0e11 ++#define VENDOR_APPLE 0x106b ++#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ ++#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ ++#define VENDOR_TI 0x104c /* Texas Instruments */ ++#define VENDOR_RICOH 0x1180 /* Ricoh */ ++#define VENDOR_JMICRON 0x197b ++ ++ ++/* PCMCIA vendor IDs */ ++#define VENDOR_BROADCOM_PCMCIA 0x02d0 ++ ++/* SDIO vendor IDs */ ++#define VENDOR_BROADCOM_SDIO 0x00BF ++ ++/* DONGLE VID/PIDs */ ++#define BCM_DNGL_VID 0x0a5c ++#define BCM_DNGL_BL_PID_4328 0xbd12 ++#define BCM_DNGL_BL_PID_4322 0xbd13 ++#define BCM_DNGL_BL_PID_4319 0xbd16 ++#define BCM_DNGL_BL_PID_43236 0xbd17 ++#define BCM_DNGL_BL_PID_4332 0xbd18 ++#define BCM_DNGL_BL_PID_4330 0xbd19 ++#define BCM_DNGL_BL_PID_4334 0xbd1a ++#define BCM_DNGL_BL_PID_43239 0xbd1b ++#define BCM_DNGL_BL_PID_4324 0xbd1c ++#define BCM_DNGL_BL_PID_4360 0xbd1d ++#define BCM_DNGL_BL_PID_4335 0xbd20 ++ ++#define BCM_DNGL_BDC_PID 0x0bdc ++#define BCM_DNGL_JTAG_PID 0x4a44 ++ ++/* HW USB BLOCK [CPULESS USB] PIDs */ ++#define BCM_HWUSB_PID_43239 43239 ++ ++/* PCI Device IDs */ ++#define BCM4210_DEVICE_ID 0x1072 /* never used */ ++#define BCM4230_DEVICE_ID 0x1086 /* never used */ ++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ ++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ ++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ ++#define BCM4211_DEVICE_ID 0x4211 ++#define BCM4231_DEVICE_ID 0x4231 ++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ ++#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ ++#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ ++#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ ++#define BCM4328_D11DUAL_ID 0x4314 /* 4328/4312 802.11a/g id */ ++#define BCM4328_D11G_ID 0x4315 /* 4328/4312 802.11g id */ ++#define BCM4328_D11A_ID 0x4316 /* 4328/4312 802.11a id */ ++#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ ++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ ++#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ ++#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */ ++#define BCM4325_D11G_ID 0x431c /* 4325 802.11g id */ ++#define BCM4325_D11A_ID 0x431d /* 4325 802.11a id */ ++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ ++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ ++#define BCM4306_UART_ID 0x4322 /* 4306 uart */ ++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ ++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ ++#define BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G_ID; INF w/loose binding war */ ++#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ ++#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */ ++#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ ++#define BCM4322_D11N_ID 0x432b /* 4322 802.11n dualband device */ ++#define BCM4322_D11N2G_ID 0x432c /* 4322 802.11n 2.4GHz device */ ++#define BCM4322_D11N5G_ID 0x432d /* 4322 802.11n 5GHz device */ ++#define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */ ++#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ ++#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ ++#define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */ ++#define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */ ++#define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */ ++#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ ++#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ ++#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ ++#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ ++#define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */ ++#define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */ ++#define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */ ++#define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */ ++#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ ++#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ ++#define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */ ++#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ ++#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ ++#define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */ ++#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ ++#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ ++#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ ++#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ ++#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ ++#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ ++#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ ++#define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ ++#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ ++#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ ++#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ ++#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ ++#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ ++#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ ++#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ ++#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ ++#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ ++#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ ++#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ ++#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ ++#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ ++#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ ++#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ ++#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ ++#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ ++#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ ++#define BCM4360_D11AC_ID 0x43a0 ++#define BCM4360_D11AC2G_ID 0x43a1 ++#define BCM4360_D11AC5G_ID 0x43a2 ++#define BCM4335_D11AC_ID 0x43ae ++#define BCM4335_D11AC2G_ID 0x43af ++#define BCM4335_D11AC5G_ID 0x43b0 ++#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ ++#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ ++#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ ++ ++/* PCI Subsystem ID */ ++#define BCM943228HMB_SSID_VEN1 0x0607 ++#define BCM94313HMGBL_SSID_VEN1 0x0608 ++#define BCM94313HMG_SSID_VEN1 0x0609 ++ ++ ++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ ++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ ++#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ ++#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */ ++#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ ++#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */ ++#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ ++#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */ ++#define BCM_SPIH_ID 0x43f6 /* Synopsis SPI Host Controller */ ++#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ ++#define BCM_JTAGM2_ID 0x43f9 /* BCM alternate jtagm device id */ ++#define SDHCI_FPGA_ID 0x43fa /* Standard SDIO Host Controller FPGA */ ++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ ++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ ++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ ++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ ++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ ++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ ++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ ++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ ++#define BCM47XX_AUDIO_ID 0x4711 /* 47xx audio codec */ ++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ ++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ ++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ ++#define BCM47XX_GMAC_ID 0x4715 /* 47xx Unimac based GbE */ ++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ ++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ ++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ ++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ ++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ ++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ ++#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ ++#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ ++#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ ++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ ++#define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */ ++#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ ++#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ ++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ ++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ ++#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */ ++#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */ ++#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */ ++#define R5C822_SDIOH_ID 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */ ++#define JMICRON_SDIOH_ID 0x2381 /* JMicron Standard SDIO Host Controller */ ++ ++/* Chip IDs */ ++#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ ++#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ ++#define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */ ++#define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ ++#define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ ++#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ ++#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ ++#define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ ++#define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ ++#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ ++#define BCM4320_CHIP_ID 0x4320 /* 4320 chipcommon chipid */ ++#define BCM4321_CHIP_ID 0x4321 /* 4321 chipcommon chipid */ ++#define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */ ++#define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */ ++#define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */ ++#define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */ ++#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ ++#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ ++#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ ++#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ ++#define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */ ++#define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */ ++#define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */ ++#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ ++#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ ++#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ ++#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ ++#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ ++#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ ++#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ ++#define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ ++#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ ++#define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ ++#define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */ ++#define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */ ++#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ ++#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ ++#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ ++#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ ++#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ ++#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ ++#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ ++#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ ++#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ ++#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ ++#define BCM4335_CHIP_ID 0x4335 ++#define BCM4360_CHIP_ID 0x4360 ++#define BCM43526_CHIP_ID 0xAA06 ++#define BCM4352_CHIP_ID 0x4352 ++ ++#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ ++#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ ++#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ ++#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ ++#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ ++#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ ++#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ ++#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ ++#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ ++#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ ++#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ ++#define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */ ++#define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */ ++#define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */ ++#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ ++#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */ ++#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */ ++#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */ ++#define BCM53010_CHIP_ID 53010 /* NS chipcommon chipid */ ++#define BCM56150_CHIP_ID 56150 /* HR2 chipcommon chipid */ ++#define BCM56340_CHIP_ID 56340 /* HX4 chipcommon chipid */ ++#define BCM53020_CHIP_ID 53020 /* NSP chipcommon chipid */ ++#define BCM56450_CHIP_ID 56450 /* KT2 chipcommon chipid */ ++ ++#if defined(CONFIG_MACH_NS) ++#define BCMIPROC_CHIP_ID BCM53010_CHIP_ID ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define BCMIPROC_CHIP_ID BCM56340_CHIP_ID ++#elif defined(CONFIG_MACH_HR2) ++#define BCMIPROC_CHIP_ID BCM56150_CHIP_ID ++#elif defined(CONFIG_MACH_NSP) ++#define BCMIPROC_CHIP_ID BCM53020_CHIP_ID ++#elif defined(CONFIG_MACH_KT2) ++#define BCMIPROC_CHIP_ID BCM56450_CHIP_ID ++#endif ++ ++#define IS_BCM5301X_CHIP_ID(id) (1) ++#define IS_IPROC_CHIP_ID(id) (((id) >= 53010 && (id) <= 53019) || \ ++ ((id) >= 56150 && (id) <= 56159) || \ ++ ((id) >= 56340 && (id) <= 56349) || \ ++ ((id) >= 53020 && (id) <= 53029) || \ ++ ((id) >= 56450 && (id) <= 56459)) ++ ++/* Package IDs */ ++#define BCM4303_PKG_ID 2 /* 4303 package id */ ++#define BCM4309_PKG_ID 1 /* 4309 package id */ ++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ ++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ ++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ ++#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */ ++#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */ ++#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */ ++#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */ ++#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */ ++#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */ ++#define BCM5354E_PKG_ID 1 /* 5354E package id */ ++#define BCM4716_PKG_ID 8 /* 4716 package id */ ++#define BCM4717_PKG_ID 9 /* 4717 package id */ ++#define BCM4718_PKG_ID 10 /* 4718 package id */ ++#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */ ++#define BCM5358U_PKG_ID 8 /* 5358U package id */ ++#define BCM5358_PKG_ID 9 /* 5358 package id */ ++#define BCM47186_PKG_ID 10 /* 47186 package id */ ++#define BCM5357_PKG_ID 11 /* 5357 package id */ ++#define BCM5356U_PKG_ID 12 /* 5356U package id */ ++#define BCM53572_PKG_ID 8 /* 53572 package id */ ++#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ ++#define BCM47188_PKG_ID 9 /* 47188 package id */ ++#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ ++#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ ++#define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ ++#define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ ++#define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ ++#define BCM4706L_PKG_ID 1 /* 4706L package id */ ++ ++#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ ++#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ ++#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ ++#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ ++#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ ++#define BCM4336_WLBGA_PKG_ID 0x8 ++#define BCM4330_WLBGA_PKG_ID 0x0 ++#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ ++#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */ ++#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ ++#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ ++#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ ++#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ ++ ++#define BCM4707_PKG_ID 1 /* 4707 package id */ ++#define BCM4708_PKG_ID 2 /* 4708 package id */ ++#define BCM4709_PKG_ID 0 /* 4709 package id */ ++ ++#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ ++ ++#define BCM4335_WLCSP_PKG_ID (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */ ++#define BCM4335_FCBGA_PKG_ID (0x1) /* FCBGA PC/Embeded/Media PCIE/SDIO */ ++#define BCM4335_WLBGA_PKG_ID (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */ ++#define BCM4335_FCBGAD_PKG_ID (0x3) /* FCBGA Debug Debug/Dev All if's. */ ++#define BCM4335_PKG_MASK (0x3) ++ ++/* boardflags */ ++#define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ ++#define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ ++#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ ++#define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ ++#define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ ++#define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ ++#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ ++#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ ++#define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ ++#define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ ++#define BFL_UNUSED 0x00000200 ++#define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ ++#define BFL_FEM 0x00000800 /* Board supports the Front End Module */ ++#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ ++#define BFL_HGPA 0x00002000 /* Board has a high gain PA */ ++#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */ ++#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ ++#define BFL_NOPA 0x00010000 /* Board has no PA */ ++#define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ ++#define BFL_PAREF 0x00040000 /* Board uses the PARef LDO */ ++#define BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */ ++#define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ ++#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ ++#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ ++#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ ++#define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ ++#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ ++#define BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */ ++#define BFL_FASTPWR 0x08000000 ++#define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ ++#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ ++#define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ ++#define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ ++#define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field ++ * when this flag is set ++ */ ++#define BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */ ++ ++/* boardflags2 */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ ++#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ ++#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ ++#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ ++#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ ++#define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ ++#define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ ++#define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace ++ * BFL2_BTC3WIRE ++ */ ++#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ ++#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ ++#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ ++#define BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */ ++#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ ++#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ ++#define BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */ ++#define BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */ ++#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ ++#define BFL2_IPALVLSHIFT_3P3 0x00020000 ++#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ ++#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */ ++ /* Most drivers will turn it off without this flag */ ++ /* to save power. */ ++ ++#define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ ++#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */ ++#define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value ++ * than programmed. The exact delta is decided by ++ * driver per chip/boardtype. This can be used ++ * when tempsense qualification happens after shipment ++ */ ++#define BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */ ++#define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ ++#define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */ ++ /* ucode control of eLNA during Tx */ ++#define BFL2_4313_RADIOREG 0x10000000 ++ /* board rework */ ++#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ ++ ++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ ++#define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ ++#define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ ++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ ++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ ++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ ++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ ++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ ++#define BOARD_GPIO_12 0x1000 /* gpio 12 */ ++#define BOARD_GPIO_13 0x2000 /* gpio 13 */ ++#define BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */ ++#define BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ ++#define BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ ++#define BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ ++#define BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ ++#define BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ ++#define BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ ++ ++#define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ ++#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ ++#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ ++ ++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ ++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */ ++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */ ++ ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define MIN_SLOW_CLK 32 /* us Slow clock period */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Reference Board Types */ ++#define BU4710_BOARD 0x0400 ++#define VSIM4710_BOARD 0x0401 ++#define QT4710_BOARD 0x0402 ++ ++#define BU4309_BOARD 0x040a ++#define BCM94309CB_BOARD 0x040b ++#define BCM94309MP_BOARD 0x040c ++#define BCM4309AP_BOARD 0x040d ++ ++#define BCM94302MP_BOARD 0x040e ++ ++#define BU4306_BOARD 0x0416 ++#define BCM94306CB_BOARD 0x0417 ++#define BCM94306MP_BOARD 0x0418 ++ ++#define BCM94710D_BOARD 0x041a ++#define BCM94710R1_BOARD 0x041b ++#define BCM94710R4_BOARD 0x041c ++#define BCM94710AP_BOARD 0x041d ++ ++#define BU2050_BOARD 0x041f ++ ++#define BCM94306P50_BOARD 0x0420 ++ ++#define BCM94309G_BOARD 0x0421 ++ ++#define BU4704_BOARD 0x0423 ++#define BU4702_BOARD 0x0424 ++ ++#define BCM94306PC_BOARD 0x0425 /* pcmcia 3.3v 4306 card */ ++ ++#define MPSG4306_BOARD 0x0427 ++ ++#define BCM94702MN_BOARD 0x0428 ++ ++/* BCM4702 1U CompactPCI Board */ ++#define BCM94702CPCI_BOARD 0x0429 ++ ++/* BCM4702 with BCM95380 VLAN Router */ ++#define BCM95380RR_BOARD 0x042a ++ ++/* cb4306 with SiGe PA */ ++#define BCM94306CBSG_BOARD 0x042b ++ ++/* cb4306 with SiGe PA */ ++#define PCSG94306_BOARD 0x042d ++ ++/* bu4704 with sdram */ ++#define BU4704SD_BOARD 0x042e ++ ++/* Dual 11a/11g Router */ ++#define BCM94704AGR_BOARD 0x042f ++ ++/* 11a-only minipci */ ++#define BCM94308MP_BOARD 0x0430 ++ ++/* 4306/gprs combo */ ++#define BCM94306GPRS_BOARD 0x0432 ++ ++/* BCM5365/BCM4704 FPGA Bringup Board */ ++#define BU5365_FPGA_BOARD 0x0433 ++ ++#define BU4712_BOARD 0x0444 ++#define BU4712SD_BOARD 0x045d ++#define BU4712L_BOARD 0x045f ++ ++/* BCM4712 boards */ ++#define BCM94712AP_BOARD 0x0445 ++#define BCM94712P_BOARD 0x0446 ++ ++/* BCM4318 boards */ ++#define BU4318_BOARD 0x0447 ++#define CB4318_BOARD 0x0448 ++#define MPG4318_BOARD 0x0449 ++#define MP4318_BOARD 0x044a ++#define SD4318_BOARD 0x044b ++ ++/* BCM4313 boards */ ++#define BCM94313BU_BOARD 0x050f ++#define BCM94313HM_BOARD 0x0510 ++#define BCM94313EPA_BOARD 0x0511 ++#define BCM94313HMG_BOARD 0x051C ++ ++/* BCM63XX boards */ ++#define BCM96338_BOARD 0x6338 ++#define BCM96348_BOARD 0x6348 ++#define BCM96358_BOARD 0x6358 ++#define BCM96368_BOARD 0x6368 ++ ++/* Another mp4306 with SiGe */ ++#define BCM94306P_BOARD 0x044c ++ ++/* mp4303 */ ++#define BCM94303MP_BOARD 0x044e ++ ++/* mpsgh4306 */ ++#define BCM94306MPSGH_BOARD 0x044f ++ ++/* BRCM 4306 w/ Front End Modules */ ++#define BCM94306MPM 0x0450 ++#define BCM94306MPL 0x0453 ++ ++/* 4712agr */ ++#define BCM94712AGR_BOARD 0x0451 ++ ++/* pcmcia 4303 */ ++#define PC4303_BOARD 0x0454 ++ ++/* 5350K */ ++#define BCM95350K_BOARD 0x0455 ++ ++/* 5350R */ ++#define BCM95350R_BOARD 0x0456 ++ ++/* 4306mplna */ ++#define BCM94306MPLNA_BOARD 0x0457 ++ ++/* 4320 boards */ ++#define BU4320_BOARD 0x0458 ++#define BU4320S_BOARD 0x0459 ++#define BCM94320PH_BOARD 0x045a ++ ++/* 4306mph */ ++#define BCM94306MPH_BOARD 0x045b ++ ++/* 4306pciv */ ++#define BCM94306PCIV_BOARD 0x045c ++ ++#define BU4712SD_BOARD 0x045d ++ ++#define BCM94320PFLSH_BOARD 0x045e ++ ++#define BU4712L_BOARD 0x045f ++#define BCM94712LGR_BOARD 0x0460 ++#define BCM94320R_BOARD 0x0461 ++ ++#define BU5352_BOARD 0x0462 ++ ++#define BCM94318MPGH_BOARD 0x0463 ++ ++#define BU4311_BOARD 0x0464 ++#define BCM94311MC_BOARD 0x0465 ++#define BCM94311MCAG_BOARD 0x0466 ++ ++#define BCM95352GR_BOARD 0x0467 ++ ++/* bcm95351agr */ ++#define BCM95351AGR_BOARD 0x0470 ++ ++/* bcm94704mpcb */ ++#define BCM94704MPCB_BOARD 0x0472 ++ ++/* 4785 boards */ ++#define BU4785_BOARD 0x0478 ++ ++/* 4321 boards */ ++#define BU4321_BOARD 0x046b ++#define BU4321E_BOARD 0x047c ++#define MP4321_BOARD 0x046c ++#define CB2_4321_BOARD 0x046d ++#define CB2_4321_AG_BOARD 0x0066 ++#define MC4321_BOARD 0x046e ++ ++/* 4328 boards */ ++#define BU4328_BOARD 0x0481 ++#define BCM4328SDG_BOARD 0x0482 ++#define BCM4328SDAG_BOARD 0x0483 ++#define BCM4328UG_BOARD 0x0484 ++#define BCM4328UAG_BOARD 0x0485 ++#define BCM4328PC_BOARD 0x0486 ++#define BCM4328CF_BOARD 0x0487 ++ ++/* 4325 boards */ ++#define BCM94325DEVBU_BOARD 0x0490 ++#define BCM94325BGABU_BOARD 0x0491 ++ ++#define BCM94325SDGWB_BOARD 0x0492 ++ ++#define BCM94325SDGMDL_BOARD 0x04aa ++#define BCM94325SDGMDL2_BOARD 0x04c6 ++#define BCM94325SDGMDL3_BOARD 0x04c9 ++ ++#define BCM94325SDABGWBA_BOARD 0x04e1 ++ ++/* 4322 boards */ ++#define BCM94322MC_SSID 0x04a4 ++#define BCM94322USB_SSID 0x04a8 /* dualband */ ++#define BCM94322HM_SSID 0x04b0 ++#define BCM94322USB2D_SSID 0x04bf /* single band discrete front end */ ++ ++/* 4312 boards */ ++#define BCM4312MCGSG_BOARD 0x04b5 ++ ++/* 4315 boards */ ++#define BCM94315DEVBU_SSID 0x04c2 ++#define BCM94315USBGP_SSID 0x04c7 ++#define BCM94315BGABU_SSID 0x04ca ++#define BCM94315USBGP41_SSID 0x04cb ++ ++/* 4319 boards */ ++#define BCM94319DEVBU_SSID 0X04e5 ++#define BCM94319USB_SSID 0X04e6 ++#define BCM94319SD_SSID 0X04e7 ++ ++/* 4716 boards */ ++#define BCM94716NR2_SSID 0x04cd ++ ++/* 4319 boards */ ++#define BCM94319DEVBU_SSID 0X04e5 ++#define BCM94319USBNP4L_SSID 0X04e6 ++#define BCM94319WLUSBN4L_SSID 0X04e7 ++#define BCM94319SDG_SSID 0X04ea ++#define BCM94319LCUSBSDN4L_SSID 0X04eb ++#define BCM94319USBB_SSID 0x04ee ++#define BCM94319LCSDN4L_SSID 0X0507 ++#define BCM94319LSUSBN4L_SSID 0X0508 ++#define BCM94319SDNA4L_SSID 0X0517 ++#define BCM94319SDELNA4L_SSID 0X0518 ++#define BCM94319SDELNA6L_SSID 0X0539 ++#define BCM94319ARCADYAN_SSID 0X0546 ++#define BCM94319WINDSOR_SSID 0x0561 ++#define BCM94319MLAP_SSID 0x0562 ++#define BCM94319SDNA_SSID 0x058b ++#define BCM94319BHEMU3_SSID 0x0563 ++#define BCM94319SDHMB_SSID 0x058c ++#define BCM94319SDBREF_SSID 0x05a1 ++#define BCM94319USBSDB_SSID 0x05a2 ++ ++ ++/* 4329 boards */ ++#define BCM94329AGB_SSID 0X04b9 ++#define BCM94329TDKMDL1_SSID 0X04ba ++#define BCM94329TDKMDL11_SSID 0X04fc ++#define BCM94329OLYMPICN18_SSID 0X04fd ++#define BCM94329OLYMPICN90_SSID 0X04fe ++#define BCM94329OLYMPICN90U_SSID 0X050c ++#define BCM94329OLYMPICN90M_SSID 0X050b ++#define BCM94329AGBF_SSID 0X04ff ++#define BCM94329OLYMPICX17_SSID 0X0504 ++#define BCM94329OLYMPICX17M_SSID 0X050a ++#define BCM94329OLYMPICX17U_SSID 0X0509 ++#define BCM94329OLYMPICUNO_SSID 0X0564 ++#define BCM94329MOTOROLA_SSID 0X0565 ++#define BCM94329OLYMPICLOCO_SSID 0X0568 ++/* 4336 SDIO board types */ ++#define BCM94336SD_WLBGABU_SSID 0x0511 ++#define BCM94336SD_WLBGAREF_SSID 0x0519 ++#define BCM94336SDGP_SSID 0x0538 ++#define BCM94336SDG_SSID 0x0519 ++#define BCM94336SDGN_SSID 0x0538 ++#define BCM94336SDGFC_SSID 0x056B ++ ++/* 4330 SDIO board types */ ++#define BCM94330SDG_SSID 0x0528 ++#define BCM94330SD_FCBGABU_SSID 0x052e ++#define BCM94330SD_WLBGABU_SSID 0x052f ++#define BCM94330SD_FCBGA_SSID 0x0530 ++#define BCM94330FCSDAGB_SSID 0x0532 ++#define BCM94330OLYMPICAMG_SSID 0x0549 ++#define BCM94330OLYMPICAMGEPA_SSID 0x054F ++#define BCM94330OLYMPICUNO3_SSID 0x0551 ++#define BCM94330WLSDAGB_SSID 0x0547 ++#define BCM94330CSPSDAGBB_SSID 0x054A ++ ++/* 43224 boards */ ++#define BCM943224X21 0x056e ++#define BCM943224X21_FCC 0x00d1 ++#define BCM943224X21B 0x00e9 ++#define BCM943224M93 0x008b ++#define BCM943224M93A 0x0090 ++#define BCM943224X16 0x0093 ++#define BCM94322X9 0x008d ++#define BCM94322M35e 0x008e ++ ++/* 43228 Boards */ ++#define BCM943228BU8_SSID 0x0540 ++#define BCM943228BU9_SSID 0x0541 ++#define BCM943228BU_SSID 0x0542 ++#define BCM943227HM4L_SSID 0x0543 ++#define BCM943227HMB_SSID 0x0544 ++#define BCM943228HM4L_SSID 0x0545 ++#define BCM943228SD_SSID 0x0573 ++ ++/* 43239 Boards */ ++#define BCM943239MOD_SSID 0x05ac ++#define BCM943239REF_SSID 0x05aa ++ ++/* 4331 boards */ ++#define BCM94331X19 0x00D6 /* X19B */ ++#define BCM94331X28 0x00E4 /* X28 */ ++#define BCM94331X28B 0x010E /* X28B */ ++#define BCM94331PCIEBT3Ax_SSID BCM94331X28 ++#define BCM94331X12_2G_SSID 0x00EC /* X12 2G */ ++#define BCM94331X12_5G_SSID 0x00ED /* X12 5G */ ++#define BCM94331X29B 0x00EF /* X29B */ ++#define BCM94331CSAX_SSID BCM94331X29B ++#define BCM94331X19C 0x00F5 /* X19C */ ++#define BCM94331X33 0x00F4 /* X33 */ ++#define BCM94331BU_SSID 0x0523 ++#define BCM94331S9BU_SSID 0x0524 ++#define BCM94331MC_SSID 0x0525 ++#define BCM94331MCI_SSID 0x0526 ++#define BCM94331PCIEBT4_SSID 0x0527 ++#define BCM94331HM_SSID 0x0574 ++#define BCM94331PCIEDUAL_SSID 0x059B ++#define BCM94331MCH5_SSID 0x05A9 ++#define BCM94331CS_SSID 0x05C6 ++#define BCM94331CD_SSID 0x05DA ++ ++/* 4314 Boards */ ++#define BCM94314BU_SSID 0x05b1 ++ ++/* 53572 Boards */ ++#define BCM953572BU_SSID 0x058D ++#define BCM953572NR2_SSID 0x058E ++#define BCM947188NR2_SSID 0x058F ++#define BCM953572SDRNR2_SSID 0x0590 ++ ++/* 43236 boards */ ++#define BCM943236OLYMPICSULLEY_SSID 0x594 ++#define BCM943236PREPROTOBLU2O3_SSID 0x5b9 ++#define BCM943236USBELNA_SSID 0x5f8 ++ ++/* 4314 Boards */ ++#define BCM94314BUSDIO_SSID 0x05c8 ++#define BCM94314BGABU_SSID 0x05c9 ++#define BCM94314HMEPA_SSID 0x05ca ++#define BCM94314HMEPABK_SSID 0x05cb ++#define BCM94314SUHMEPA_SSID 0x05cc ++#define BCM94314SUHM_SSID 0x05cd ++#define BCM94314HM_SSID 0x05d1 ++ ++/* 4334 Boards */ ++#define BCM94334FCAGBI_SSID 0x05df ++#define BCM94334WLAGBI_SSID 0x05dd ++ ++/* 43217 Boards */ ++#define BCM943217BU_SSID 0x05d5 ++#define BCM943217HM2L_SSID 0x05d6 ++#define BCM943217HMITR2L_SSID 0x05d7 ++ ++/* 43142 Boards */ ++#define BCM943142HM_SSID 0x05e0 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* # of GPIO pins */ ++#define GPIO_NUMPINS 32 ++ ++/* These values are used by dhd host driver. */ ++#define RDL_RAM_BASE_4319 0x60000000 ++#define RDL_RAM_BASE_4329 0x60000000 ++#define RDL_RAM_SIZE_4319 0x48000 ++#define RDL_RAM_SIZE_4329 0x48000 ++#define RDL_RAM_SIZE_43236 0x70000 ++#define RDL_RAM_BASE_43236 0x60000000 ++#define RDL_RAM_SIZE_4328 0x60000 ++#define RDL_RAM_BASE_4328 0x80000000 ++#define RDL_RAM_SIZE_4322 0x60000 ++#define RDL_RAM_BASE_4322 0x60000000 ++#define RDL_RAM_SIZE_4360 0xE0000 ++#define RDL_RAM_BASE_4360 0x60000000 ++ ++/* generic defs for nvram "muxenab" bits ++* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options. ++*/ ++#define MUXENAB_UART 0x00000001 ++#define MUXENAB_GPIO 0x00000002 ++#define MUXENAB_ERCX 0x00000004 ++#define MUXENAB_JTAG 0x00000008 ++#define MUXENAB_HOST_WAKE 0x00000010 ++ ++/* Boot flags */ ++#define FLASH_KERNEL_NFLASH 0x00000001 ++#define FLASH_BOOT_NFLASH 0x00000002 ++ ++#endif /* _BCMDEVS_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmendian.h b/drivers/bcmdrivers/gmac/src/include/bcmendian.h +new file mode 100755 +index 0000000..6e810d3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmendian.h +@@ -0,0 +1,324 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Byte order utilities ++ * ++ * $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $ ++ * ++ * This file by default provides proper behavior on little-endian architectures. ++ * On big-endian architectures, IL_BIGENDIAN should be defined. ++ */ ++ ++#ifndef _BCMENDIAN_H_ ++#define _BCMENDIAN_H_ ++ ++#include ++ ++/* Reverse the bytes in a 16-bit value */ ++#define BCMSWAP16(val) \ ++ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \ ++ (((uint16)(val) & (uint16)0xff00U) >> 8))) ++ ++/* Reverse the bytes in a 32-bit value */ ++#define BCMSWAP32(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \ ++ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \ ++ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \ ++ (((uint32)(val) & (uint32)0xff000000U) >> 24))) ++ ++/* Reverse the two 16-bit halves of a 32-bit value */ ++#define BCMSWAP32BY16(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \ ++ (((uint32)(val) & (uint32)0xffff0000U) >> 16))) ++ ++/* Byte swapping macros ++ * Host <=> Network (Big Endian) for 16- and 32-bit values ++ * Host <=> Little-Endian for 16- and 32-bit values ++ */ ++#ifndef hton16 ++#ifndef IL_BIGENDIAN ++#define HTON16(i) BCMSWAP16(i) ++#define hton16(i) bcmswap16(i) ++#define HTON32(i) BCMSWAP32(i) ++#define hton32(i) bcmswap32(i) ++#define NTOH16(i) BCMSWAP16(i) ++#define ntoh16(i) bcmswap16(i) ++#define NTOH32(i) BCMSWAP32(i) ++#define ntoh32(i) bcmswap32(i) ++#define LTOH16(i) (i) ++#define ltoh16(i) (i) ++#define LTOH32(i) (i) ++#define ltoh32(i) (i) ++#define HTOL16(i) (i) ++#define htol16(i) (i) ++#define HTOL32(i) (i) ++#define htol32(i) (i) ++#else /* IL_BIGENDIAN */ ++#define HTON16(i) (i) ++#define hton16(i) (i) ++#define HTON32(i) (i) ++#define hton32(i) (i) ++#define NTOH16(i) (i) ++#define ntoh16(i) (i) ++#define NTOH32(i) (i) ++#define ntoh32(i) (i) ++#define LTOH16(i) BCMSWAP16(i) ++#define ltoh16(i) bcmswap16(i) ++#define LTOH32(i) BCMSWAP32(i) ++#define ltoh32(i) bcmswap32(i) ++#define HTOL16(i) BCMSWAP16(i) ++#define htol16(i) bcmswap16(i) ++#define HTOL32(i) BCMSWAP32(i) ++#define htol32(i) bcmswap32(i) ++#endif /* IL_BIGENDIAN */ ++#endif /* hton16 */ ++ ++#ifndef IL_BIGENDIAN ++#define ltoh16_buf(buf, i) ++#define htol16_buf(buf, i) ++#else ++#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) ++#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) ++#endif /* IL_BIGENDIAN */ ++ ++/* Unaligned loads and stores in host byte order */ ++#ifndef IL_BIGENDIAN ++#define load32_ua(a) ltoh32_ua(a) ++#define store32_ua(a, v) htol32_ua_store(v, a) ++#define load16_ua(a) ltoh16_ua(a) ++#define store16_ua(a, v) htol16_ua_store(v, a) ++#else ++#define load32_ua(a) ntoh32_ua(a) ++#define store32_ua(a, v) hton32_ua_store(v, a) ++#define load16_ua(a) ntoh16_ua(a) ++#define store16_ua(a, v) hton16_ua_store(v, a) ++#endif /* IL_BIGENDIAN */ ++ ++#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) ++#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) ++#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) ++#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) ++ ++#define ltoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#define ntoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#ifdef __GNUC__ ++ ++/* GNU macro versions avoid referencing the argument multiple times, while also ++ * avoiding the -fno-inline used in ROM builds. ++ */ ++ ++#define bcmswap16(val) ({ \ ++ uint16 _val = (val); \ ++ BCMSWAP16(_val); \ ++}) ++ ++#define bcmswap32(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32(_val); \ ++}) ++ ++#define bcmswap32by16(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32BY16(_val); \ ++}) ++ ++#define bcmswap16_buf(buf, len) ({ \ ++ uint16 *_buf = (uint16 *)(buf); \ ++ uint _wds = (len) / 2; \ ++ while (_wds--) { \ ++ *_buf = bcmswap16(*_buf); \ ++ _buf++; \ ++ } \ ++}) ++ ++#define htol16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = _val >> 8; \ ++}) ++ ++#define htol32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = (_val >> 8) & 0xff; \ ++ _bytes[2] = (_val >> 16) & 0xff; \ ++ _bytes[3] = _val >> 24; \ ++}) ++ ++#define hton16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 8; \ ++ _bytes[1] = _val & 0xff; \ ++}) ++ ++#define hton32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 24; \ ++ _bytes[1] = (_val >> 16) & 0xff; \ ++ _bytes[2] = (_val >> 8) & 0xff; \ ++ _bytes[3] = _val & 0xff; \ ++}) ++ ++#define ltoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH16_UA(_bytes); \ ++}) ++ ++#define ltoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH32_UA(_bytes); \ ++}) ++ ++#define ntoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH16_UA(_bytes); \ ++}) ++ ++#define ntoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH32_UA(_bytes); \ ++}) ++ ++#else /* !__GNUC__ */ ++ ++/* Inline versions avoid referencing the argument multiple times */ ++static INLINE uint16 ++bcmswap16(uint16 val) ++{ ++ return BCMSWAP16(val); ++} ++ ++static INLINE uint32 ++bcmswap32(uint32 val) ++{ ++ return BCMSWAP32(val); ++} ++ ++static INLINE uint32 ++bcmswap32by16(uint32 val) ++{ ++ return BCMSWAP32BY16(val); ++} ++ ++/* Reverse pairs of bytes in a buffer (not for high-performance use) */ ++/* buf - start of buffer of shorts to swap */ ++/* len - byte length of buffer */ ++static INLINE void ++bcmswap16_buf(uint16 *buf, uint len) ++{ ++ len = len / 2; ++ ++ while (len--) { ++ *buf = bcmswap16(*buf); ++ buf++; ++ } ++} ++ ++/* ++ * Store 16-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = val >> 8; ++} ++ ++/* ++ * Store 32-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = (val >> 8) & 0xff; ++ bytes[2] = (val >> 16) & 0xff; ++ bytes[3] = val >> 24; ++} ++ ++/* ++ * Store 16-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 8; ++ bytes[1] = val & 0xff; ++} ++ ++/* ++ * Store 32-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 24; ++ bytes[1] = (val >> 16) & 0xff; ++ bytes[2] = (val >> 8) & 0xff; ++ bytes[3] = val & 0xff; ++} ++ ++/* ++ * Load 16-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint16 ++ltoh16_ua(const void *bytes) ++{ ++ return _LTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint32 ++ltoh32_ua(const void *bytes) ++{ ++ return _LTOH32_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 16-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint16 ++ntoh16_ua(const void *bytes) ++{ ++ return _NTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint32 ++ntoh32_ua(const void *bytes) ++{ ++ return _NTOH32_UA((const uint8 *)bytes); ++} ++ ++#endif /* !__GNUC__ */ ++#endif /* !_BCMENDIAN_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h b/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h +new file mode 100755 +index 0000000..6f733fc +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetmib.h +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific MIB definition for ++ * Broadcom Home Networking Division ++ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. ++ * ++ * $Id: bcmenetmib.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetmib_h_ ++#define _bcmenetmib_h_ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* ++ * EMAC MIB Registers ++ */ ++typedef volatile struct { ++ uint32 tx_good_octets; ++ uint32 tx_good_pkts; ++ uint32 tx_octets; ++ uint32 tx_pkts; ++ uint32 tx_broadcast_pkts; ++ uint32 tx_multicast_pkts; ++ uint32 tx_len_64; ++ uint32 tx_len_65_to_127; ++ uint32 tx_len_128_to_255; ++ uint32 tx_len_256_to_511; ++ uint32 tx_len_512_to_1023; ++ uint32 tx_len_1024_to_max; ++ uint32 tx_jabber_pkts; ++ uint32 tx_oversize_pkts; ++ uint32 tx_fragment_pkts; ++ uint32 tx_underruns; ++ uint32 tx_total_cols; ++ uint32 tx_single_cols; ++ uint32 tx_multiple_cols; ++ uint32 tx_excessive_cols; ++ uint32 tx_late_cols; ++ uint32 tx_defered; ++ uint32 tx_carrier_lost; ++ uint32 tx_pause_pkts; ++ uint32 PAD[8]; ++ ++ uint32 rx_good_octets; ++ uint32 rx_good_pkts; ++ uint32 rx_octets; ++ uint32 rx_pkts; ++ uint32 rx_broadcast_pkts; ++ uint32 rx_multicast_pkts; ++ uint32 rx_len_64; ++ uint32 rx_len_65_to_127; ++ uint32 rx_len_128_to_255; ++ uint32 rx_len_256_to_511; ++ uint32 rx_len_512_to_1023; ++ uint32 rx_len_1024_to_max; ++ uint32 rx_jabber_pkts; ++ uint32 rx_oversize_pkts; ++ uint32 rx_fragment_pkts; ++ uint32 rx_missed_pkts; ++ uint32 rx_crc_align_errs; ++ uint32 rx_undersize; ++ uint32 rx_crc_errs; ++ uint32 rx_align_errs; ++ uint32 rx_symbol_errs; ++ uint32 rx_pause_pkts; ++ uint32 rx_nonpause_pkts; ++} bcmenetmib_t; ++ ++#endif /* _bcmenetmib_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h b/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h +new file mode 100755 +index 0000000..19c9c86 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetphy.h +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc Broadcom BCM47XX MDC/MDIO enet phy definitions. ++ * ++ * $Id: bcmenetphy.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetphy_h_ ++#define _bcmenetphy_h_ ++ ++/* phy address */ ++#define MAXEPHY 32 /* mdio phy addresses are 5bit quantities */ ++#define EPHY_MASK 0x1f /* phy mask */ ++#define EPHY_NONE 31 /* nvram: no phy present at all */ ++#define EPHY_NOREG 30 /* nvram: no local phy regs */ ++ ++#define MAXPHYREG 32 /* max 32 registers per phy */ ++ ++/* just a few phy registers */ ++#define CTL_RESET (1 << 15) /* reset */ ++#define CTL_LOOP (1 << 14) /* loopback */ ++#define CTL_SPEED (1 << 13) /* speed selection lsb 0=10, 1=100 */ ++#define CTL_ANENAB (1 << 12) /* autonegotiation enable */ ++#define CTL_RESTART (1 << 9) /* restart autonegotiation */ ++#define CTL_DUPLEX (1 << 8) /* duplex mode 0=half, 1=full */ ++#define CTL_SPEED_MSB (1 << 6) /* speed selection msb */ ++ ++#define CTL_SPEED_10 ((0 << 6) | (0 << 13)) /* speed selection CTL.6=0, CTL.13=0 */ ++#define CTL_SPEED_100 ((0 << 6) | (1 << 13)) /* speed selection CTL.6=0, CTL.13=1 */ ++#define CTL_SPEED_1000 ((1 << 6) | (0 << 13)) /* speed selection CTL.6=1, CTL.13=0 */ ++ ++#define ADV_10FULL (1 << 6) /* autonegotiate advertise 10full */ ++#define ADV_10HALF (1 << 5) /* autonegotiate advertise 10half */ ++#define ADV_100FULL (1 << 8) /* autonegotiate advertise 100full */ ++#define ADV_100HALF (1 << 7) /* autonegotiate advertise 100half */ ++#define ADV_PAUSE (1 << 10) /* autonegotiate advertise pause */ ++ ++/* link partner ability register */ ++#define LPA_SLCT 0x001f /* same as advertise selector */ ++#define LPA_10HALF 0x0020 /* can do 10mbps half-duplex */ ++#define LPA_10FULL 0x0040 /* can do 10mbps full-duplex */ ++#define LPA_100HALF 0x0080 /* can do 100mbps half-duplex */ ++#define LPA_100FULL 0x0100 /* can do 100mbps full-duplex */ ++#define LPA_100BASE4 0x0200 /* can do 100mbps 4k packets */ ++#define LPA_RESV 0x1c00 /* unused */ ++#define LPA_RFAULT 0x2000 /* link partner faulted */ ++#define LPA_LPACK 0x4000 /* link partner acked us */ ++#define LPA_NPAGE 0x8000 /* next page bit */ ++ ++#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) ++#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) ++ ++/* 1000BASE-T control register */ ++#define ADV_1000HALF 0x0100 /* advertise 1000BASE-T half duplex */ ++#define ADV_1000FULL 0x0200 /* advertise 1000BASE-T full duplex */ ++ ++/* 1000BASE-T status register */ ++#define LPA_1000HALF 0x0400 /* link partner 1000BASE-T half duplex */ ++#define LPA_1000FULL 0x0800 /* link partner 1000BASE-T full duplex */ ++ ++/* 1000BASE-T extended status register */ ++#define EST_1000THALF 0x1000 /* 1000BASE-T half duplex capable */ ++#define EST_1000TFULL 0x2000 /* 1000BASE-T full duplex capable */ ++#define EST_1000XHALF 0x4000 /* 1000BASE-X half duplex capable */ ++#define EST_1000XFULL 0x8000 /* 1000BASE-X full duplex capable */ ++ ++#define STAT_REMFAULT (1 << 4) /* remote fault */ ++#define STAT_LINK (1 << 2) /* link status */ ++#define STAT_JAB (1 << 1) /* jabber detected */ ++#define AUX_FORCED (1 << 2) /* forced 10/100 */ ++#define AUX_SPEED (1 << 1) /* speed 0=10mbps 1=100mbps */ ++#define AUX_DUPLEX (1 << 0) /* duplex 0=half 1=full */ ++ ++#endif /* _bcmenetphy_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h b/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h +new file mode 100755 +index 0000000..b82e0fe +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmenetrxh.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific Receive Data Header for the ++ * Broadcom Home Networking Division ++ * BCM44XX and BCM47XX 10/100 Mbps Ethernet cores. ++ * ++ * $Id: bcmenetrxh.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmenetrxh_h_ ++#define _bcmenetrxh_h_ ++ ++/* ++ * The Ethernet MAC core returns an 8-byte Receive Frame Data Header ++ * with every frame consisting of ++ * 16bits of frame length, followed by ++ * 16bits of EMAC rx descriptor info, followed by 32bits of undefined. ++ */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++ uint16 pad[12]; ++} bcmenetrxh_t; ++ ++#define RXHDR_LEN 28 /* Header length */ ++ ++#define RXF_L ((uint16)1 << 11) /* last buffer in a frame */ ++#define RXF_MISS ((uint16)1 << 7) /* received due to promisc mode */ ++#define RXF_BRDCAST ((uint16)1 << 6) /* dest is broadcast address */ ++#define RXF_MULT ((uint16)1 << 5) /* dest is multicast address */ ++#define RXF_LG ((uint16)1 << 4) /* frame length > rxmaxlength */ ++#define RXF_NO ((uint16)1 << 3) /* odd number of nibbles */ ++#define RXF_RXER ((uint16)1 << 2) /* receive symbol error */ ++#define RXF_CRC ((uint16)1 << 1) /* crc error */ ++#define RXF_OV ((uint16)1 << 0) /* fifo overflow */ ++ ++#endif /* _bcmenetrxh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h b/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h +new file mode 100755 +index 0000000..6f0cf09 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmgmacmib.h +@@ -0,0 +1,117 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific MIB definition for ++ * Broadcom Home Networking Division ++ * GbE Unimac core ++ * ++ * $Id: bcmgmacmib.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmgmacmib_h_ ++#define _bcmgmacmib_h_ ++ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* GMAC MIB structure */ ++ ++typedef struct _gmacmib { ++ uint32 tx_good_octets; /* 0x300 */ ++ uint32 tx_good_octets_high; /* 0x304 */ ++ uint32 tx_good_pkts; /* 0x308 */ ++ uint32 tx_octets; /* 0x30c */ ++ uint32 tx_octets_high; /* 0x310 */ ++ uint32 tx_pkts; /* 0x314 */ ++ uint32 tx_broadcast_pkts; /* 0x318 */ ++ uint32 tx_multicast_pkts; /* 0x31c */ ++ uint32 tx_len_64; /* 0x320 */ ++ uint32 tx_len_65_to_127; /* 0x324 */ ++ uint32 tx_len_128_to_255; /* 0x328 */ ++ uint32 tx_len_256_to_511; /* 0x32c */ ++ uint32 tx_len_512_to_1023; /* 0x330 */ ++ uint32 tx_len_1024_to_1522; /* 0x334 */ ++ uint32 tx_len_1523_to_2047; /* 0x338 */ ++ uint32 tx_len_2048_to_4095; /* 0x33c */ ++ uint32 tx_len_4095_to_8191; /* 0x340 */ ++ uint32 tx_len_8192_to_max; /* 0x344 */ ++ uint32 tx_jabber_pkts; /* 0x348 */ ++ uint32 tx_oversize_pkts; /* 0x34c */ ++ uint32 tx_fragment_pkts; /* 0x350 */ ++ uint32 tx_underruns; /* 0x354 */ ++ uint32 tx_total_cols; /* 0x358 */ ++ uint32 tx_single_cols; /* 0x35c */ ++ uint32 tx_multiple_cols; /* 0x360 */ ++ uint32 tx_excessive_cols; /* 0x364 */ ++ uint32 tx_late_cols; /* 0x368 */ ++ uint32 tx_defered; /* 0x36c */ ++ uint32 tx_carrier_lost; /* 0x370 */ ++ uint32 tx_pause_pkts; /* 0x374 */ ++ uint32 tx_uni_pkts; /* 0x378 */ ++ uint32 tx_q0_pkts; /* 0x37c */ ++ uint32 tx_q0_octets; /* 0x380 */ ++ uint32 tx_q0_octets_high; /* 0x384 */ ++ uint32 tx_q1_pkts; /* 0x388 */ ++ uint32 tx_q1_octets; /* 0x38c */ ++ uint32 tx_q1_octets_high; /* 0x390 */ ++ uint32 tx_q2_pkts; /* 0x394 */ ++ uint32 tx_q2_octets; /* 0x398 */ ++ uint32 tx_q2_octets_high; /* 0x39c */ ++ uint32 tx_q3_pkts; /* 0x3a0 */ ++ uint32 tx_q3_octets; /* 0x3a4 */ ++ uint32 tx_q3_octets_high; /* 0x3a8 */ ++ uint32 PAD; ++ uint32 rx_good_octets; /* 0x3b0 */ ++ uint32 rx_good_octets_high; /* 0x3b4 */ ++ uint32 rx_good_pkts; /* 0x3b8 */ ++ uint32 rx_octets; /* 0x3bc */ ++ uint32 rx_octets_high; /* 0x3c0 */ ++ uint32 rx_pkts; /* 0x3c4 */ ++ uint32 rx_broadcast_pkts; /* 0x3c8 */ ++ uint32 rx_multicast_pkts; /* 0x3cc */ ++ uint32 rx_len_64; /* 0x3d0 */ ++ uint32 rx_len_65_to_127; /* 0x3d4 */ ++ uint32 rx_len_128_to_255; /* 0x3d8 */ ++ uint32 rx_len_256_to_511; /* 0x3dc */ ++ uint32 rx_len_512_to_1023; /* 0x3e0 */ ++ uint32 rx_len_1024_to_1522; /* 0x3e4 */ ++ uint32 rx_len_1523_to_2047; /* 0x3e8 */ ++ uint32 rx_len_2048_to_4095; /* 0x3ec */ ++ uint32 rx_len_4095_to_8191; /* 0x3f0 */ ++ uint32 rx_len_8192_to_max; /* 0x3f4 */ ++ uint32 rx_jabber_pkts; /* 0x3f8 */ ++ uint32 rx_oversize_pkts; /* 0x3fc */ ++ uint32 rx_fragment_pkts; /* 0x400 */ ++ uint32 rx_missed_pkts; /* 0x404 */ ++ uint32 rx_crc_align_errs; /* 0x408 */ ++ uint32 rx_undersize; /* 0x40c */ ++ uint32 rx_crc_errs; /* 0x410 */ ++ uint32 rx_align_errs; /* 0x414 */ ++ uint32 rx_symbol_errs; /* 0x418 */ ++ uint32 rx_pause_pkts; /* 0x41c */ ++ uint32 rx_nonpause_pkts; /* 0x420 */ ++ uint32 rx_sachanges; /* 0x424 */ ++ uint32 rx_uni_pkts; /* 0x428 */ ++} gmacmib_t; ++ ++#define GM_MIB_BASE 0x300 ++#define GM_MIB_LIMIT 0x800 ++ ++#endif /* _bcmgmacmib_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h b/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h +new file mode 100755 +index 0000000..c3d58e9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmgmacrxh.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Hardware-specific Receive Data Header for the ++ * Broadcom Home Networking Division ++ * BCM47XX GbE cores. ++ * ++ * $Id: bcmgmacrxh.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmgmacrxh_h_ ++#define _bcmgmacrxh_h_ ++ ++/* ++ * The Ethernet GMAC core returns an 8-byte Receive Frame Data Header ++ * with every frame consisting of ++ * 16 bits of frame length, followed by ++ * 16 bits of GMAC rx descriptor info, followed by 32bits of undefined. ++ */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++ uint16 pad[12]; ++} bcmgmacrxh_t; ++ ++#define RXHDR_LEN 28 /* Header length */ ++ ++#define GRXF_DT_MASK ((uint16)0xf) /* data type */ ++#define GRXF_DT_SHIFT 12 ++#define GRXF_DC_MASK ((uint16)0xf) /* (num descr to xfer the frame) - 1 */ ++#define GRXF_DC_SHIFT 8 ++#define GRXF_OVF ((uint16)1 << 7) /* overflow error occured */ ++#define GRXF_CTFERR ((uint16)1 << 6) /* overflow error occured */ ++#define GRXF_OVERSIZE ((uint16)1 << 4) /* frame size > rxmaxlength */ ++#define GRXF_CRC ((uint16)1 << 3) /* crc error */ ++#define GRXF_VLAN ((uint16)1 << 2) /* vlan tag detected */ ++#define GRXF_PT_MASK ((uint16)3) /* packet type 0 - Unicast, ++ * 1 - Multicast, 2 - Broadcast ++ */ ++ ++#endif /* _bcmgmacrxh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h +new file mode 100755 +index 0000000..3698729 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy.h +@@ -0,0 +1,267 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy_h_ ++#define _bcm_iproc_phy_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++/* ++ * Defines: SOC_E_XXX ++ * Purpose: SOC API error codes ++ * Notes: ++ * An error code may be converted to a string by passing ++ * the code to soc_errmsg(). ++ */ ++ ++typedef enum { ++ SOC_E_NONE = 0, ++ SOC_E_INTERNAL = -1, ++ SOC_E_MEMORY = -2, ++ SOC_E_UNIT = -3, ++ SOC_E_PARAM = -4, ++ SOC_E_EMPTY = -5, ++ SOC_E_FULL = -6, ++ SOC_E_NOT_FOUND = -7, ++ SOC_E_EXISTS = -8, ++ SOC_E_TIMEOUT = -9, ++ SOC_E_BUSY = -10, ++ SOC_E_FAIL = -11, ++ SOC_E_DISABLED = -12, ++ SOC_E_BADID = -13, ++ SOC_E_RESOURCE = -14, ++ SOC_E_CONFIG = -15, ++ SOC_E_UNAVAIL = -16, ++ SOC_E_INIT = -17, ++ SOC_E_PORT = -18, ++ ++ SOC_E_LIMIT = -19 /* Must come last */ ++} soc_error_t; ++ ++#define SOC_SUCCESS(rv) ((rv) >= 0) ++#define SOC_FAILURE(rv) ((rv) < 0) ++ ++typedef enum _soc_port_if_e { ++ SOC_PORT_IF_NOCXN, /* No physical connection */ ++ SOC_PORT_IF_NULL, /* Pass-through connection without PHY */ ++ SOC_PORT_IF_MII, ++ SOC_PORT_IF_GMII, ++ SOC_PORT_IF_SGMII, ++ SOC_PORT_IF_TBI, ++ SOC_PORT_IF_XGMII, ++ SOC_PORT_IF_RGMII, ++ SOC_PORT_IF_RvMII, ++ SOC_PORT_IF_SFI, ++ SOC_PORT_IF_XFI, ++ SOC_PORT_IF_KR, ++ SOC_PORT_IF_KR4, ++ SOC_PORT_IF_CR, ++ SOC_PORT_IF_CR4, ++ SOC_PORT_IF_XLAUI, ++ SOC_PORT_IF_SR, ++ SOC_PORT_IF_RXAUI, ++ SOC_PORT_IF_XAUI, ++ SOC_PORT_IF_SPAUI, ++ SOC_PORT_IF_QSGMII, ++ SOC_PORT_IF_ILKN, ++ SOC_PORT_IF_RCY, ++ SOC_PORT_IF_FAT_PIPE, ++ SOC_PORT_IF_CGMII, ++ SOC_PORT_IF_CAUI, ++ SOC_PORT_IF_LR, ++ SOC_PORT_IF_LR4, ++ SOC_PORT_IF_SR4, ++ SOC_PORT_IF_KX, ++ SOC_PORT_IF_CPU, ++ SOC_PORT_IF_OLP, ++ SOC_PORT_IF_OAMP, ++ SOC_PORT_IF_ERP, ++ SOC_PORT_IF_COUNT /* last, please */ ++} _soc_port_if_t; ++typedef _soc_port_if_t soc_port_if_t; ++ ++ ++/* 1000BASE-T/100BASE-TX/10BASE-T MII Control Register (Addr 00h) */ ++#define PHY_MII_CTRLr_FLAGS 0x00 ++#define PHY_MII_CTRLr_BANK 0x0000 ++#define PHY_MII_CTRLr_ADDR 0x00 ++/* 1000BASE-T/100BASE-TX/10BASE-T MII Status Register (ADDR 01h) */ ++#define PHY_MII_STATr_FLAGS 0x00 ++#define PHY_MII_STATr_BANK 0x0000 ++#define PHY_MII_STATr_ADDR 0x01 ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 02h) */ ++#define PHY_MII_PHY_ID0r_FLAGS _SOC_PHY_REG_DIRECT ++#define PHY_MII_PHY_ID0r_BANK 0x0000 ++#define PHY_MII_PHY_ID0r_ADDR 0x02 ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Identifier Register (ADDR 03h) */ ++#define PHY_MII_PHY_ID1r_FLAGS _SOC_PHY_REG_DIRECT ++#define PHY_MII_PHY_ID1r_BANK 0x0000 ++#define PHY_MII_PHY_ID1r_ADDR 0x03 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Advertisment Register (ADDR 04h) */ ++#define PHY_MII_ANAr_FLAGS 0x00 ++#define PHY_MII_ANAr_BANK 0x0000 ++#define PHY_MII_ANAr_ADDR 0x04 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auto-neg Link Partner Ability (ADDR 05h) */ ++#define PHY_MII_ANPr_FLAGS 0x00 ++#define PHY_MII_ANPr_BANK 0x0000 ++#define PHY_MII_ANPr_ADDR 0x05 ++/* 1000BASE-T Control Register (ADDR 09h) */ ++#define PHY_MII_GB_CTRLr_FLAGS 0x00 ++#define PHY_MII_GB_CTRLr_BANK 0x0000 ++#define PHY_MII_GB_CTRLr_ADDR 0x09 ++/* 1000BASE-T Status Register (ADDR 0ah) */ ++#define PHY_MII_GB_STATr_FLAGS 0x00 ++#define PHY_MII_GB_STATr_BANK 0x0000 ++#define PHY_MII_GB_STATr_ADDR 0x0a ++/* 1000BASE-T/100BASE-TX/10BASE-T IEEE Extended Status Register (ADDR 0fh) */ ++#define PHY_MII_ESRr_FLAGS 0x00 ++#define PHY_MII_ESRr_BANK 0x0000 ++#define PHY_MII_ESRr_ADDR 0x0f ++/* 1000BASE-T/100BASE-TX/10BASE-T PHY Extended Control Register (ADDR 10h) */ ++#define PHY_MII_ECRr_FLAGS 0x00 ++#define PHY_MII_ECRr_BANK 0x0000 ++#define PHY_MII_ECRr_ADDR 0x10 ++/* 1000BASE-T/100BASE-TX/10BASE-T Auxiliary Control Reg (ADDR 18h Shadow 000)*/ ++#define PHY_MII_AUX_CTRLr_FLAGS 0x00 ++#define PHY_MII_AUX_CTRLr_BANK 0x0000 ++#define PHY_MII_AUX_CTRLr_ADDR 0x18 ++/* 1000BASE-T/100BASE-TX/10BASE-T Power/MII Control Reg (ADDR 18h Shadow 010)*/ ++#define PHY_MII_POWER_CTRLr_FLAGS 0x00 ++#define PHY_MII_POWER_CTRLr_BANK 0x0002 ++#define PHY_MII_POWER_CTRLr_ADDR 0x18 ++/* Auxiliary 1000BASE-X Control Reg (ADDR 1ch shadow 11011) */ ++#define PHY_AUX_1000X_CTRLr_FLAGS 0x00 ++#define PHY_AUX_1000X_CTRLr_BANK 0x001B ++#define PHY_AUX_1000X_CTRLr_ADDRS 0x1c ++/* Mode Control Reg (ADDR 1ch shadow 11111) */ ++#define PHY_MODE_CTRLr_FLAGS 0x00 ++#define PHY_MODE_CTRLr_BANK 0x001F ++#define PHY_MODE_CTRLr_ADDR 0x1c ++ ++/* ++ * Primary SerDes Registers ++ */ ++/* 1000BASE-X MII Control Register (Addr 00h) */ ++#define PHY_1000X_MII_CTRLr_FLAGS SOC_PHY_REG_1000X ++#define PHY_1000X_MII_CTRLr_BANK 0x0000 ++#define PHY_1000X_MII_CTRLr_ADDR 0x00 ++ ++ ++/* MII Control Register: bit definitions */ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++/* ++ * MII Status Register: See 802.3, 1998 pg 544 ++ */ ++#define MII_STAT_EXT (1 << 0) /* Extended Registers */ ++#define MII_STAT_JBBR (1 << 1) /* Jabber Detected */ ++#define MII_STAT_LA (1 << 2) /* Link Active */ ++#define MII_STAT_AN_CAP (1 << 3) /* Autoneg capable */ ++#define MII_STAT_RF (1 << 4) /* Remote Fault */ ++#define MII_STAT_AN_DONE (1 << 5) /* Autoneg complete */ ++#define MII_STAT_MF_PS (1 << 6) /* Preamble suppression */ ++#define MII_STAT_ES (1 << 8) /* Extended status (R15) */ ++#define MII_STAT_HD_100_T2 (1 << 9) /* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_100_T2 (1 << 10)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_HD_10 (1 << 11)/* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_10 (1 << 12)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_HD_100 (1 << 13)/* Half duplex 100Mb/s supported */ ++#define MII_STAT_FD_100 (1 << 14)/* Full duplex 100Mb/s supported */ ++#define MII_STAT_100_T4 (1 << 15)/* Full duplex 100Mb/s supported */ ++ ++/* ++ * MII Link Advertisment ++ */ ++#define MII_ANA_ASF (1 << 0)/* Advertise Selector Field */ ++#define MII_ANA_HD_10 (1 << 5)/* Half duplex 10Mb/s supported */ ++#define MII_ANA_FD_10 (1 << 6)/* Full duplex 10Mb/s supported */ ++#define MII_ANA_HD_100 (1 << 7)/* Half duplex 100Mb/s supported */ ++#define MII_ANA_FD_100 (1 << 8)/* Full duplex 100Mb/s supported */ ++#define MII_ANA_T4 (1 << 9)/* T4 */ ++#define MII_ANA_PAUSE (1 << 10)/* Pause supported */ ++#define MII_ANA_ASYM_PAUSE (1 << 11)/* Asymmetric pause supported */ ++#define MII_ANA_RF (1 << 13)/* Remote fault */ ++#define MII_ANA_NP (1 << 15)/* Next Page */ ++ ++#define MII_ANA_ASF_802_3 (1) /* 802.3 PHY */ ++ ++/* ++ * 1000Base-T Control Register ++ */ ++#define MII_GB_CTRL_MS_MAN (1 << 12) /* Manual Master/Slave mode */ ++#define MII_GB_CTRL_MS (1 << 11) /* Master/Slave negotiation mode */ ++#define MII_GB_CTRL_PT (1 << 10) /* Port type */ ++#define MII_GB_CTRL_ADV_1000FD (1 << 9) /* Advertise 1000Base-T FD */ ++#define MII_GB_CTRL_ADV_1000HD (1 << 8) /* Advertise 1000Base-T HD */ ++ ++/* ++ * 1000Base-T Status Register ++ */ ++#define MII_GB_STAT_MS_FAULT (1 << 15) /* Master/Slave Fault */ ++#define MII_GB_STAT_MS (1 << 14) /* Master/Slave, 1 == Master */ ++#define MII_GB_STAT_LRS (1 << 13) /* Local receiver status */ ++#define MII_GB_STAT_RRS (1 << 12) /* Remote receiver status */ ++#define MII_GB_STAT_LP_1000FD (1 << 11) /* Link partner 1000FD capable */ ++#define MII_GB_STAT_LP_1000HD (1 << 10) /* Link partner 1000HD capable */ ++#define MII_GB_STAT_IDE (0xff << 0) /* Idle error count */ ++ ++/* ++ * IEEE Extended Status Register ++ */ ++#define MII_ESR_1000_X_FD (1 << 15) /* 1000Base-T FD capable */ ++#define MII_ESR_1000_X_HD (1 << 14) /* 1000Base-T HD capable */ ++#define MII_ESR_1000_T_FD (1 << 13) /* 1000Base-T FD capable */ ++#define MII_ESR_1000_T_HD (1 << 12) /* 1000Base-T FD capable */ ++ ++/* MII Extended Control Register (BROADCOM) */ ++#define MII_ECR_FE (1 << 0) /* FIFO Elasticity */ ++#define MII_ECR_TLLM (1 << 1) /* Three link LED mode */ ++#define MII_ECR_ET_IPG (1 << 2) /* Extended XMIT IPG mode */ ++#define MII_ECR_FLED_OFF (1 << 3) /* Force LED off */ ++#define MII_ECR_FLED_ON (1 << 4) /* Force LED on */ ++#define MII_ECR_ELT (1 << 5) /* Enable LED traffic */ ++#define MII_ECR_RS (1 << 6) /* Reset Scrambler */ ++#define MII_ECR_BRSA (1 << 7) /* Bypass Receive Sym. align */ ++#define MII_ECR_BMLT3 (1 << 8) /* Bypass MLT3 Encoder/Decoder */ ++#define MII_ECR_BSD (1 << 9) /* Bypass Scramble/Descramble */ ++#define MII_ECR_B4B5B (1 << 10) /* Bypass 4B/5B Encode/Decode */ ++#define MII_ECR_FI (1 << 11) /* Force Interrupt */ ++#define MII_ECR_ID (1 << 12) /* Interrupt Disable */ ++#define MII_ECR_TD (1 << 13) /* XMIT Disable */ ++#define MII_ECR_DAMC (1 << 14) /* DIsable Auto-MDI Crossover */ ++#define MII_ECR_10B (1 << 15) /* 1 == 10B, 0 == GMII */ ++ ++#endif /* _bcm_iproc_phy_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h +new file mode 100755 +index 0000000..523c8e1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5221.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy5221_h_ ++#define _bcm_iproc_phy5221_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++#define PHY_AUX_MULTIPLE_PHYr_BANK 0x0000 ++#define PHY_AUX_MULTIPLE_PHYr_ADDR 0x1e ++ ++#define PHY522X_SUPER_ISOLATE_MODE (1<<3) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern int phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask); ++extern int phy5221_init(uint eth_num, uint phyaddr); ++extern int phy5221_link_get(uint eth_num, uint phyaddr, int *link); ++extern int phy5221_enable_set(uint eth_num, uint phyaddr, int enable); ++extern int phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); ++ ++#endif /* _bcm_iproc_phy5221_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h +new file mode 100755 +index 0000000..a366dd8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_phy5461s.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++#ifndef _bcm_iproc_phy5461s_h_ ++#define _bcm_iproc_phy5461s_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++/* Indirect PHY register address flags */ ++#define SOC_PHY_REG_RESERVE_ACCESS 0x20000000 ++#define SOC_PHY_REG_1000X 0x40000000 ++#define SOC_PHY_REG_INDIRECT 0x80000000 ++#define _SOC_PHY_REG_DIRECT ((SOC_PHY_REG_1000X << 1) | (SOC_PHY_REG_1000X >> 1)) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern int phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data); ++extern int phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask); ++extern int phy5461_init(uint eth_num, uint phyaddr); ++extern int phy5461_link_get(uint eth_num, uint phyaddr, int *link); ++extern int phy5461_enable_set(uint eth_num, uint phyaddr, int enable); ++extern int phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex); ++ ++#endif /* _bcm_iproc_phy5461s_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h +new file mode 100755 +index 0000000..d8e0a39 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_robo_serdes.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++#ifndef _bcm_iproc_robo_serdes_h_ ++#define _bcm_iproc_robo_serdes_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include "bcmrobo.h" ++ ++#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ ++ ++/* ++ * MII Link Advertisment (Clause 37) ++ */ ++#define MII_ANA_C37_NP (1 << 15) /* Next Page */ ++#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ ++#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ ++#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ ++#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ ++#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ ++#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ ++#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ ++#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ ++ ++/* MII Control Register: bit definitions */ ++ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++#define GPIO_SFP0_TXDIS 26 ++#define GPIO_SFP1_TXDIS 27 ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern uint16 robo_serdes_get_id(robo_info_t *robo, uint page, uint off); ++extern void robo_serdes_reset(robo_info_t *robo, uint page); ++extern int robo_serdes_reset_core(robo_info_t *robo, uint page); ++extern int robo_serdes_start_pll(robo_info_t *robo, uint page); ++extern int robo_serdes_init(robo_info_t *robo, uint page); ++extern int robo_serdes_enable_set(robo_info_t *robo, uint page, int enable); ++extern int robo_serdes_speed_set(robo_info_t *robo, uint page, int speed); ++extern int robo_serdes_speed_get(robo_info_t *robo, uint page, int *speed); ++ ++#endif /* _bcm_iproc_serdes_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h +new file mode 100755 +index 0000000..f9abc47 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++#ifndef _bcm_iproc_serdes_h_ ++#define _bcm_iproc_serdes_h_ ++ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++ ++#define PHY_REG_BLK_ADDR 0x001f /* GLOBAL BLOCK ADDRESS REGISTER */ ++ ++/* ++ * MII Link Advertisment (Clause 37) ++ */ ++#define MII_ANA_C37_NP (1 << 15) /* Next Page */ ++#define MII_ANA_C37_RF_OK (0 << 12) /* No error, link OK */ ++#define MII_ANA_C37_RF_LINK_FAIL (1 << 12) /* Offline */ ++#define MII_ANA_C37_RF_OFFLINE (2 << 12) /* Link failure */ ++#define MII_ANA_C37_RF_AN_ERR (3 << 12) /* Auto-Negotiation Error */ ++#define MII_ANA_C37_PAUSE (1 << 7) /* Symmetric Pause */ ++#define MII_ANA_C37_ASYM_PAUSE (1 << 8) /* Asymmetric Pause */ ++#define MII_ANA_C37_HD (1 << 6) /* Half duplex */ ++#define MII_ANA_C37_FD (1 << 5) /* Full duplex */ ++ ++/* MII Control Register: bit definitions */ ++ ++#define MII_CTRL_FS_2500 (1 << 5) /* Force speed to 2500 Mbps */ ++#define MII_CTRL_SS_MSB (1 << 6) /* Speed select, MSb */ ++#define MII_CTRL_CST (1 << 7) /* Collision Signal test */ ++#define MII_CTRL_FD (1 << 8) /* Full Duplex */ ++#define MII_CTRL_RAN (1 << 9) /* Restart Autonegotiation */ ++#define MII_CTRL_IP (1 << 10) /* Isolate Phy */ ++#define MII_CTRL_PD (1 << 11) /* Power Down */ ++#define MII_CTRL_AE (1 << 12) /* Autonegotiation enable */ ++#define MII_CTRL_SS_LSB (1 << 13) /* Speed select, LSb */ ++#define MII_CTRL_LE (1 << 14) /* Loopback enable */ ++#define MII_CTRL_RESET (1 << 15) /* PHY reset */ ++ ++#define MII_CTRL_SS(_x) ((_x) & (MII_CTRL_SS_LSB|MII_CTRL_SS_MSB)) ++#define MII_CTRL_SS_10 0 ++#define MII_CTRL_SS_100 (MII_CTRL_SS_LSB) ++#define MII_CTRL_SS_1000 (MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_INVALID (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++#define MII_CTRL_SS_MASK (MII_CTRL_SS_LSB | MII_CTRL_SS_MSB) ++ ++/* ---- External Function Prototypes ------------------------------------- */ ++ ++extern void serdes_set_blk(uint eth_num, uint phyaddr, uint blk); ++extern void serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data); ++extern uint16 serdes_rd_reg(uint eth_num, uint phyaddr, uint reg); ++extern uint16 serdes_get_id(uint eth_num, uint phyaddr, uint off); ++extern void serdes_reset(uint eth_num, uint phyaddr); ++extern int serdes_reset_core(uint eth_num, uint phyaddr); ++extern int serdes_start_pll(uint eth_num, uint phyaddr); ++extern int serdes_init(uint eth_num, uint phyaddr); ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++extern int serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx); ++extern int serdes_set_asym_mode(uint eth_num, uint phyaddr); ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ ++ ++#endif /* _bcm_iproc_serdes_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h +new file mode 100755 +index 0000000..5bd5abd +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmiproc_serdes_def.h +@@ -0,0 +1,306 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These are serdes defines ++ * ++ */ ++ ++#ifndef _PHY_XGXS16G_H_ ++#define _PHY_XGXS16G_H_ ++ ++/* macros */ ++ ++/* Macros ONLY used after initialization */ ++#define XGXS16G_2p5G_ID(id2) ((id2 & 0xff) == 0xf) ++ ++ ++/****************************************************************************/ ++/***** Starting below is auto-generated register macros from RDB files *****/ ++/****************************************************************************/ ++ ++/**************************************************************************** ++ * Core Enums. ++ ***************************************************************************/ ++ ++#define XGXS16G_IEEE0BLK_IEEECONTROL0r 0x00000000 ++#define XGXS16G_XGXSBLK0_XGXSCONTROLr 0x00008000 ++#define XGXS16G_XGXSBLK0_XGXSSTATUSr 0x00008001 ++#define XGXS16G_XGXSBLK0_MMDSELECTr 0x0000800d ++#define XGXS16G_XGXSBLK0_MISCCONTROL1r 0x0000800e ++#define XGXS16G_XGXSBLK1_LANECTRL0r 0x00008015 ++#define XGXS16G_XGXSBLK1_LANECTRL1r 0x00008016 ++#define XGXS16G_XGXSBLK1_LANECTRL3r 0x00008018 ++#define XGXS16G_TX0_TX_ACONTROL0r 0x00008061 ++#define XGXS16G_RX0_RX_CONTROLr 0x000080b1 ++#define XGXS16G_AN73_PDET_PARDET10GCONTROLr 0x00008131 ++#define XGXS16G_XGXSBLK7_EEECONTROLr 0x00008150 ++#define XGXS16G_TX_LN_SWAP1r 0x00008169 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X1r 0x00008300 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X2r 0x00008301 ++#define XGXS16G_SERDESDIGITAL_CONTROL1000X3r 0x00008302 ++#define XGXS16G_SERDESDIGITAL_STATUS1000X1r 0x00008304 ++#define XGXS16G_SERDESDIGITAL_MISC1r 0x00008308 ++#define XGXS16G_SERDESID_SERDESID0r 0x00008310 ++#define XGXS16G_SERDESID_SERDESID1r 0x00008311 ++#define XGXS16G_SERDESID_SERDESID2r 0x00008312 ++#define XGXS16G_SERDESID_SERDESID3r 0x00008313 ++#define XGXS16G_REMOTEPHY_MISC3r 0x0000833c ++#define XGXS16G_REMOTEPHY_MISC5r 0x0000833e ++#define XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr 0x00008350 ++#define XGXS16G_BAM_NEXTPAGE_UD_FIELDr 0x00008357 ++#define XGXS16G_COMBO_IEEE0_MIICNTLr 0x0000ffe0 ++#define XGXS16G_COMBO_IEEE0_AUTONEGADVr 0x0000ffe4 ++ ++ ++/**************************************************************************** ++ * XGXS16G_IEEE_ieee0Blk ++ ***************************************************************************/ ++/**************************************************************************** ++ * ieee0Blk :: ieeeControl0 ++ ***************************************************************************/ ++/* ieee0Blk :: ieeeControl0 :: rst_hw [15:15] */ ++#define IEEE0BLK_IEEECONTROL0_RST_HW_MASK 0x8000 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_RST_HW_SHIFT 15 ++ ++/* ieee0Blk :: ieeeControl0 :: gloopback [14:14] */ ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK 0x4000 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_ALIGN 0 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_BITS 1 ++#define IEEE0BLK_IEEECONTROL0_GLOOPBACK_SHIFT 14 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsControl ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsControl :: start_sequencer [13:13] */ ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK 0x2000 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_START_SEQUENCER_SHIFT 13 ++ ++/* XgxsBlk0 :: xgxsControl :: mode_10g [11:08] */ ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_MASK 0x0f00 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_BITS 4 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS 0 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noCC 1 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane 6 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss 8 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_XGXS_noLss_noCC 9 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass 10 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_protBypass_noDsk 11 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ComboCoreMode 12 ++#define XGXSBLK0_XGXSCONTROL_MODE_10G_ClocksOff 15 ++ ++/* XgxsBlk0 :: xgxsControl :: hstl [05:05] */ ++#define XGXSBLK0_XGXSCONTROL_HSTL_MASK 0x0020 ++#define XGXSBLK0_XGXSCONTROL_HSTL_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_HSTL_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_HSTL_SHIFT 5 ++ ++/* XgxsBlk0 :: xgxsControl :: cdet_en [03:03] */ ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_MASK 0x0008 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_CDET_EN_SHIFT 3 ++ ++/* XgxsBlk0 :: xgxsControl :: eden [02:02] */ ++#define XGXSBLK0_XGXSCONTROL_EDEN_MASK 0x0004 ++#define XGXSBLK0_XGXSCONTROL_EDEN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_EDEN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_EDEN_SHIFT 2 ++ ++/* XgxsBlk0 :: xgxsControl :: afrst_en [01:01] */ ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK 0x0002 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_AFRST_EN_SHIFT 1 ++ ++/* XgxsBlk0 :: xgxsControl :: txcko_div [00:00] */ ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK 0x0001 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_ALIGN 0 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_BITS 1 ++#define XGXSBLK0_XGXSCONTROL_TXCKO_DIV_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: xgxsStatus ++ ***************************************************************************/ ++/* XgxsBlk0 :: xgxsStatus :: txpll_lock [11:11] */ ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK 0x0800 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_ALIGN 0 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_BITS 1 ++#define XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_SHIFT 11 ++ ++ ++/**************************************************************************** ++ * XgxsBlk0 :: miscControl1 ++ ***************************************************************************/ ++/* XgxsBlk0 :: miscControl1 :: PCS_dev_en_override [10:10] */ ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK 0x0400 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_SHIFT 10 ++ ++/* XgxsBlk0 :: miscControl1 :: PMD_dev_en_override [09:09] */ ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK 0x0200 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_SHIFT 9 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_autodet [01:01] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK 0x0002 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_SHIFT 1 ++ ++/* XgxsBlk0 :: miscControl1 :: ieee_blksel_val [00:00] */ ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK 0x0001 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_ALIGN 0 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_BITS 1 ++#define XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_XgxsBlk1 ++ ***************************************************************************/ ++/**************************************************************************** ++ * XgxsBlk1 :: laneCtrl0 ++ ***************************************************************************/ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_rx [07:04] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK 0x00f0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_SHIFT 4 ++ ++/* XgxsBlk1 :: laneCtrl0 :: cl36_pcs_en_tx [03:00] */ ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK 0x000f ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_ALIGN 0 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_BITS 4 ++#define XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_TX0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * TX0 :: Tx_AControl0 ++ ***************************************************************************/ ++/* TX0 :: Tx_AControl0 :: txpol_flip [05:05] */ ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_MASK 0x0020 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_ALIGN 0 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_BITS 1 ++#define TX0_TX_ACONTROL0_TXPOL_FLIP_SHIFT 5 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_dsc_2_0 ++ ***************************************************************************/ ++/**************************************************************************** ++ * dsc_2_0 :: dsc_ctrl0 ++ ***************************************************************************/ ++/* dsc_2_0 :: dsc_ctrl0 :: rxSeqStart [15:15] */ ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK 0x8000 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_ALIGN 0 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_BITS 1 ++#define DSC_2_0_DSC_CTRL0_RXSEQSTART_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * XGXS16G_USER_SerdesDigital ++ ***************************************************************************/ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X1 :: crc_checker_disable [07:07] */ ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK 0x0080 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_SHIFT 7 ++ ++/* SerdesDigital :: Control1000X1 :: disable_pll_pwrdwn [06:06] */ ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK 0x0040 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_SHIFT 6 ++ ++/* SerdesDigital :: Control1000X1 :: fiber_mode_1000X [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Control1000X3 ++ ***************************************************************************/ ++/* SerdesDigital :: Control1000X3 :: fifo_elasicity_tx_rx [02:01] */ ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK 0x0006 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_BITS 2 ++#define SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_SHIFT 1 ++ ++/* SerdesDigital :: Control1000X3 :: tx_fifo_rst [00:00] */ ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK 0x0001 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_ALIGN 0 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_BITS 1 ++#define SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_SHIFT 0 ++ ++/**************************************************************************** ++ * SerdesDigital :: Status1000X1 ++ ***************************************************************************/ ++/* SerdesDigital :: Status1000X1 :: speed_status [04:03] */ ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK 0x0018 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_ALIGN 0 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_BITS 2 ++#define SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT 3 ++ ++/**************************************************************************** ++ * SerdesDigital :: Misc1 ++ ***************************************************************************/ ++/* SerdesDigital :: Misc1 :: force_speed_sel [04:04] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK 0x0010 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_BITS 1 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_SHIFT 4 ++ ++/* SerdesDigital :: Misc1 :: force_speed [03:00] */ ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_MASK 0x000f ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_ALIGN 0 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_BITS 4 ++#define SERDESDIGITAL_MISC1_FORCE_SPEED_SHIFT 0 ++ ++ ++/**************************************************************************** ++ * CL73_UserB0 :: CL73_BAMCtrl1 ++ ***************************************************************************/ ++/* CL73_UserB0 :: CL73_BAMCtrl1 :: CL73_bamEn [15:15] */ ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK 0x8000 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_ALIGN 0 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_BITS 1 ++#define CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_SHIFT 15 ++ ++ ++/**************************************************************************** ++ * Datatype Definitions. ++ ***************************************************************************/ ++#endif /* _PHY_XGXS16G_H_ */ ++ ++/* End of File */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmnvram.h b/drivers/bcmdrivers/gmac/src/include/bcmnvram.h +new file mode 100755 +index 0000000..a9c63d8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmnvram.h +@@ -0,0 +1,295 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * NVRAM variable manipulation ++ * ++ * $Id: bcmnvram.h 325984 2012-04-05 08:51:37Z $ ++ */ ++ ++#ifndef _bcmnvram_h_ ++#define _bcmnvram_h_ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++#include ++#include ++#include ++ ++struct nvram_header { ++ uint32 magic; ++ uint32 len; ++ uint32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ ++ uint32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ ++ uint32 config_ncdl; /* ncdl values for memc */ ++}; ++ ++struct nvram_otphdr { ++ struct nvram_header nvh; ++ uint16 flags_swmacm_gpio_phya; /* otp flags, switch/gmac mode, gpio, phyaddr */ ++ struct ether_addr mac; ++ uint32 clkfreq; ++}; ++ ++struct nvram_tuple { ++ char *name; ++ char *value; ++ struct nvram_tuple *next; ++}; ++ ++/* ++ * Get default value for an NVRAM variable ++ */ ++extern char *nvram_default_get(const char *name); ++ ++/* ++ * Initialize NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern int nvram_init(void *sih); ++ ++/* ++ * Append a chunk of nvram variables to the global list ++ */ ++extern int nvram_append(void *si, char *vars, uint varsz); ++ ++extern void nvram_get_global_vars(char **varlst, uint *varsz); ++ ++ ++/* ++ * Check for reset button press for restoring factory defaults. ++ */ ++extern int nvram_reset(void *sih); ++ ++/* ++ * Disable NVRAM access. May be unnecessary or undefined on certain ++ * platforms. ++ */ ++extern void nvram_exit(void *sih); ++ ++/* ++ * Get the value of an NVRAM variable. The pointer returned may be ++ * invalid after a set. ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined ++ */ ++extern char * nvram_get(const char *name); ++ ++/* ++ * Read the reset GPIO value from the nvram and set the GPIO ++ * as input ++ */ ++extern int BCMINITFN(nvram_resetgpio_init)(void *sih); ++ ++/* ++ * Get the value of an NVRAM variable. ++ * @param name name of variable to get ++ * @return value of variable or NUL if undefined ++ */ ++static INLINE char * ++nvram_safe_get(const char *name) ++{ ++ char *p = nvram_get(name); ++ return p ? p : ""; ++} ++ ++/* ++ * Match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is string equal ++ * to match or FALSE otherwise ++ */ ++static INLINE int ++nvram_match(char *name, char *match) ++{ ++ const char *value = nvram_get(name); ++ return (value && !strcmp(value, match)); ++} ++ ++/* ++ * Inversely match an NVRAM variable. ++ * @param name name of variable to match ++ * @param match value to compare against value of variable ++ * @return TRUE if variable is defined and its value is not string ++ * equal to invmatch or FALSE otherwise ++ */ ++static INLINE int ++nvram_invmatch(char *name, char *invmatch) ++{ ++ const char *value = nvram_get(name); ++ return (value && strcmp(value, invmatch)); ++} ++ ++/* ++ * Set the value of an NVRAM variable. The name and value strings are ++ * copied into private storage. Pointers to previously set values ++ * may become invalid. The new value may be immediately ++ * retrieved but will not be permanently stored until a commit. ++ * @param name name of variable to set ++ * @param value value of variable ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_set(const char *name, const char *value); ++ ++/* ++ * Unset an NVRAM variable. Pointers to previously set values ++ * remain valid until a set. ++ * @param name name of variable to unset ++ * @return 0 on success and errno on failure ++ * NOTE: use nvram_commit to commit this change to flash. ++ */ ++extern int nvram_unset(const char *name); ++ ++/* ++ * NVRAM is based of FLASH or OTP. ++ * @return From FLASH: TRUE ++ * From OTP: FALSE ++ */ ++extern bool nvram_inotp(void); ++ ++/* ++ * Commit NVRAM header to OTP. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_otpcommit(void *sih); ++ ++/* ++ * Commit NVRAM variables to permanent storage. All pointers to values ++ * may be invalid after a commit. ++ * NVRAM values are undefined after a commit. ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_commit(void); ++ ++/* ++ * Get all NVRAM variables (format name=value\0 ... \0\0). ++ * @param buf buffer to store variables ++ * @param count size of buffer in bytes ++ * @return 0 on success and errno on failure ++ */ ++extern int nvram_getall(char *nvram_buf, int count); ++ ++/* ++ * returns the crc value of the nvram ++ * @param nvh nvram header pointer ++ */ ++uint8 nvram_calc_crc(struct nvram_header * nvh); ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* The NVRAM version number stored as an NVRAM variable */ ++#define NVRAM_SOFTWARE_VERSION "1" ++ ++#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ ++#define NVRAM_CLEAR_MAGIC 0x0 ++#define NVRAM_INVALID_MAGIC 0xFFFFFFFF ++#define NVRAM_VERSION 1 ++#define NVRAM_HEADER_SIZE 20 ++#define NVRAM_SPACE 0x8000 ++#define ENVRAM_SPACE 0x1000 ++ ++#define NVRAM_MAX_VALUE_LEN 255 ++#define NVRAM_MAX_PARAM_LEN 64 ++ ++#define NVRAM_CRC_START_POSITION 9 /* magic, len, crc8 to be skipped */ ++#define NVRAM_CRC_VER_MASK 0xffffff00 /* for crc_ver_init */ ++ ++/* Incase of nvram header(in OTP), we save 16bit after nvram header ++ * o 0:0 Switch Present ++ * o 1:4 Switch and gmac mode ++ * o 5:10 robo reset GPIO pin number ++ * o 11:15 phyaddr ++ */ ++#define OTPNVRAM_SWITCH_PRESENT 0x1 ++ ++#define OTPNVRAM_FLAGS_MASK 0x1 ++#define OTPNVRAM_SMACMODE_MASK 0x1e ++#define OTPNVRAM_GPIO_MASK 0x7e0 ++#define OTPNVRAM_PHYADDR_MASK 0xf800 ++ ++#define OTPNVRAM_SMACMODE_SHIFT 1 ++#define OTPNVRAM_GPIO_SHIFT 5 ++#define OTPNVRAM_PHYADDR_SHIFT 11 ++ ++/* clkfreq is saved in following format in OTP nvram data ++ * 9:0 pci clock ++ * 20:10 si clock ++ * 31:21 mips clock ++ */ ++ ++#define NVRAM_PCI_CLKMASK 0x3ff ++#define NVRAM_SI_CLKMASK 0x1ffc00 ++#define NVRAM_SI_CLKSHIFT 10 ++#define NVRAM_CPUCLK_SHIFT 21 ++ ++/* Offsets to embedded nvram area */ ++#define NVRAM_START_COMPRESSED 0x400 ++#define NVRAM_START 0x1000 ++ ++#define BCM_JUMBO_NVRAM_DELIMIT '\n' ++#define BCM_JUMBO_START "Broadcom Jumbo Nvram file" ++ ++#if !defined(BCMHIGHSDIO) && defined(BCMTRXV2) ++extern char *_vars; ++extern uint _varsz; ++#endif ++ ++#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \ ++ defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__)) ++#define IMAGE_SIZE "image_size" ++#define BOOTPARTITION "bootpartition" ++#define IMAGE_BOOT BOOTPARTITION ++#define PARTIALBOOTS "partialboots" ++#define MAXPARTIALBOOTS "maxpartialboots" ++#define IMAGE_1ST_FLASH_TRX "flash0.trx" ++#define IMAGE_1ST_FLASH_OS "flash0.os" ++#define IMAGE_2ND_FLASH_TRX "flash0.trx2" ++#define IMAGE_2ND_FLASH_OS "flash0.os2" ++#define IMAGE_FIRST_OFFSET "image_first_offset" ++#define IMAGE_SECOND_OFFSET "image_second_offset" ++#define LINUX_FIRST "linux" ++#define LINUX_SECOND "linux2" ++#endif ++ ++#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \ ++ defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__)) ++/* Shared by all: CFE, Linux Kernel, and Ap */ ++#define IMAGE_BOOT "image_boot" ++#define BOOTPARTITION IMAGE_BOOT ++/* CFE variables */ ++#define IMAGE_1ST_FLASH_TRX "flash0.trx" ++#define IMAGE_1ST_FLASH_OS "flash0.os" ++#define IMAGE_2ND_FLASH_TRX "flash0.trx2" ++#define IMAGE_2ND_FLASH_OS "flash0.os2" ++#define IMAGE_SIZE "image_size" ++ ++/* CFE and Linux Kernel shared variables */ ++#define IMAGE_FIRST_OFFSET "image_first_offset" ++#define IMAGE_SECOND_OFFSET "image_second_offset" ++ ++/* Linux application variables */ ++#define LINUX_FIRST "linux" ++#define LINUX_SECOND "linux2" ++#define POLICY_TOGGLE "toggle" ++#define LINUX_PART_TO_FLASH "linux_to_flash" ++#define LINUX_FLASH_POLICY "linux_flash_policy" ++ ++#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */ ++ ++int nvram_env_gmac_name(int gmac, char *name); ++ ++#endif /* _bcmnvram_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmotp.h b/drivers/bcmdrivers/gmac/src/include/bcmotp.h +new file mode 100755 +index 0000000..d1ec475 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmotp.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OTP support. ++ * ++ * $Id: bcmotp.h 321779 2012-03-16 19:39:00Z $ ++ */ ++ ++#ifndef _bcmotp_h_ ++#define _bcmotp_h_ ++ ++/* OTP regions */ ++#define OTP_HW_RGN 1 ++#define OTP_SW_RGN 2 ++#define OTP_CI_RGN 4 ++#define OTP_FUSE_RGN 8 ++#define OTP_ALL_RGN 0xf /* From h/w region to end of OTP including checksum */ ++ ++/* OTP Size */ ++#define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ ++ ++/* Fixed size subregions sizes in words */ ++#define OTPGU_CI_SZ 2 ++ ++/* OTP usage */ ++#define OTP4325_FM_DISABLED_OFFSET 188 ++ ++#ifdef BCMNVRAMW ++/* Global RDE index for chips not having an OTP PMU resource. */ ++#define OTP_GLOBAL_RDE_IDX 0xFF ++#endif ++ ++/* Exported functions */ ++extern int otp_status(void *oh); ++extern int otp_size(void *oh); ++extern uint16 otp_read_bit(void *oh, uint offset); ++extern void* otp_init(si_t *sih); ++extern int otp_read_region(si_t *sih, int region, uint16 *data, uint *wlen); ++extern int otp_read_word(si_t *sih, uint wn, uint16 *data); ++extern int otp_nvread(void *oh, char *data, uint *len); ++#ifdef BCMNVRAMW ++extern int otp_write_region(si_t *sih, int region, uint16 *data, uint wlen); ++extern int otp_write_word(si_t *sih, uint wn, uint16 data); ++extern int otp_cis_append_region(si_t *sih, int region, char *vars, int count); ++extern int otp_lock(si_t *sih); ++extern int otp_nvwrite(void *oh, uint16 *data, uint wlen); ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) ++extern int otp_dump(void *oh, int arg, char *buf, uint size); ++extern int otp_dumpstats(void *oh, int arg, char *buf, uint size); ++#endif ++ ++#if defined(BCMNVRAMW) ++#define otp_write_rde(oh, rde, bit, val) ipxotp_write_rde(oh, rde, bit, val) ++extern int ipxotp_write_rde(void *oh, int rde, uint bit, uint val); ++extern int otp_write_bits(void *oh, uint offset, int bits, uint8* data); ++ ++#ifdef OTP_DEBUG ++extern int otp_verify1x(void *oh, uint off, uint fuse); ++extern int otp_read1x(void *oh, uint off, uint fuse); ++extern int otp_repair_bit(void *oh, uint off, uint val); ++extern int otp_write_ones(void *oh, uint off, uint bits); ++extern int otp_write_ones_old(void *oh, uint off, uint bits); ++#endif ++ ++#endif ++ ++#endif /* _bcmotp_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmparams.h b/drivers/bcmdrivers/gmac/src/include/bcmparams.h +new file mode 100755 +index 0000000..da6eb4c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmparams.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc system wide parameters. ++ * ++ * $Id: bcmparams.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _bcmparams_h_ ++#define _bcmparams_h_ ++ ++#define VLAN_MAXVID 15 /* Max. VLAN ID supported/allowed */ ++ ++#define VLAN_NUMPRIS 8 /* # of prio, start from 0 */ ++ ++#define DEV_NUMIFS 16 /* Max. # of devices/interfaces supported */ ++ ++#define WL_MAXBSSCFG 16 /* maximum number of BSS Configs we can configure */ ++ ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmperf.h b/drivers/bcmdrivers/gmac/src/include/bcmperf.h +new file mode 100755 +index 0000000..2ec4079 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmperf.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Performance counters software interface. ++ * ++ * $Id: bcmperf.h 241182 2011-02-17 21:50:03Z $ ++ */ ++/* essai */ ++#ifndef _BCMPERF_H_ ++#define _BCMPERF_H_ ++/* get cache hits and misses */ ++#if defined(BCMMIPS) && defined(BCMPERFSTATS) ++#include ++#define BCMPERF_ENABLE_INSTRCOUNT() hndmips_perf_instrcount_enable() ++#define BCMPERF_ENABLE_ICACHE_MISS() hndmips_perf_icache_miss_enable() ++#define BCMPERF_ENABLE_ICACHE_HIT() hndmips_perf_icache_hit_enable() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = hndmips_perf_read_cache_miss()) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = hndmips_perf_read_cache_hit()) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = hndmips_perf_read_instrcount()) ++#else ++#define BCMPERF_ENABLE_INSTRCOUNT() ++#define BCMPERF_ENABLE_ICACHE_MISS() ++#define BCMPERF_ENABLE_ICACHE_HIT() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) ++#endif /* defined(mips) */ ++#endif /* _BCMPERF_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmrobo.h b/drivers/bcmdrivers/gmac/src/include/bcmrobo.h +new file mode 100755 +index 0000000..38f5a9f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmrobo.h +@@ -0,0 +1,203 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * RoboSwitch setup functions ++ * ++ * $Id: bcmrobo.h 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++#ifndef _bcm_robo_h_ ++#define _bcm_robo_h_ ++ ++/* ++ * MODELID: ++ * 0x53010: BCM53010, Select Low SKU device if SKU ID[1:0] = 01. ++ * 0x53011: BCM53011, Select Middle SKU device if SKU ID[1:0] = 10. ++ * 0x53012: BCM53012, Select High SKU device if SKU ID[1:0] = 00. ++ * Note: The SKU ID[1:0] is loaded from OTP configuration data. ++ */ ++#define DEVID53010 0x53010 /* 53010 */ ++#define DEVID53011 0x53011 /* 53011 */ ++#define DEVID53012 0x53012 /* 53012 */ ++#define DEVID53013 0x53013 /* 53013 */ ++#define DEVID53014 0x53014 /* 53014 */ ++#define DEVID53015 0x53015 /* 53015 */ ++#define DEVID53016 0x53016 /* 53016 */ ++#define DEVID53017 0x53017 /* 53017 */ ++#define DEVID53018 0x53018 /* 53018 */ ++#define DEVID53019 0x53019 /* 53019 */ ++#define DEVID53022 0x53022 /* 53022 */ ++#define DEVID53025 0x53025 /* 53025 */ ++ ++#define ROBO_IS_BCM5301X(id) (1) ++#define ROBO_IS_VEGA(id) ((id) >= DEVID53014 && (id) <= DEVID53017) ++ ++#define OTP_SKU_ID_53014 0x2 ++#define OTP_SKU_ID_53015 0x3 ++#define OTP_SKU_ID_53016 0x4 ++ ++/* Power save duty cycle times */ ++#define MAX_NO_PHYS 5 ++#define PWRSAVE_SLEEP_TIME 12 ++#define PWRSAVE_WAKE_TIME 3 ++ ++/* Power save modes for the switch */ ++#define ROBO_PWRSAVE_NORMAL 0 ++#define ROBO_PWRSAVE_AUTO 1 ++#define ROBO_PWRSAVE_MANUAL 2 ++#define ROBO_PWRSAVE_AUTO_MANUAL 3 ++ ++#define ROBO_IS_PWRSAVE_MANUAL(r) ((r)->pwrsave_mode_manual) ++#define ROBO_IS_PWRSAVE_AUTO(r) ((r)->pwrsave_mode_auto) ++ ++/* NorthStar SRAB interface */ ++/* Access switch registers through SRAB (Switch Register Access Bridge) */ ++#define REG_VERSION_ID 0x40 ++#define REG_CTRL_PORT0_GMIIPO 0x58 /* 53012: GMII Port0 Override register */ ++#define REG_CTRL_PORT1_GMIIPO 0x59 /* 53012: GMII Port1 Override register */ ++#define REG_CTRL_PORT2_GMIIPO 0x5a /* 53012: GMII Port2 Override register */ ++#define REG_CTRL_PORT3_GMIIPO 0x5b /* 53012: GMII Port3 Override register */ ++#define REG_CTRL_PORT4_GMIIPO 0x5c /* 53012: GMII Port4 Override register */ ++#define REG_CTRL_PORT5_GMIIPO 0x5d /* 53012: GMII Port5 Override register */ ++#define REG_CTRL_PORT7_GMIIPO 0x5f /* 53012: GMII Port7 Override register */ ++ ++/* Command and status register of the SRAB */ ++#define CFG_F_sra_rst_MASK (1 << 2) ++#define CFG_F_sra_write_MASK (1 << 1) ++#define CFG_F_sra_gordyn_MASK (1 << 0) ++#define CFG_F_sra_page_R 24 ++#define CFG_F_sra_offset_R 16 ++ ++/* Switch interface controls */ ++#define CFG_F_sw_init_done_MASK (1 << 6) ++#define CFG_F_rcareq_MASK (1 << 3) ++#define CFG_F_rcagnt_MASK (1 << 4) ++ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++#define PAGE_P5_SGMII 0x16 ++#define PAGE_P4_SGMII 0x17 ++ ++/* SGMII REGISTERS */ ++#define REG_SGMII_BLK_ADDR 0x3e ++#define REG_IEEECTRL0 0x0000 ++#define REG_TX_ACTL0 0x8061 ++#define REG_TX_DRIVER 0x8065 ++#define REG_RX_CONTROL 0x80f1 ++#define REG_RX_ANLOGBIAS0L 0x80fc ++#define REG_SERDES_CTL1000X1 0x8300 ++#define REG_SERDES_CTL1000X2 0x8301 ++#define REG_SERDES_CTL1000X3 0x8302 ++#define REG_SERDES_STAT1000X1 0x8304 ++#define REG_COMBO_IEEE0_MIICTL 0xffe0 ++#define REG_COMBO_IEEE0_ANADV 0xffe4 ++#define REG_COMBO_IEEE0_ANLP 0xffe5 ++ ++#define PORTCFG_5 5 ++#define PORTCFG_4 4 ++#define PORTCFG "port%dcfg" ++#define PORTCFG_RGMII "rgmii" ++#define PORTCFG_SGMII "sgmii" ++#define PORTCFG_GPHY "gphy" ++ ++typedef volatile struct { ++ uint32 PAD[11]; ++ uint32 cmdstat; /* 0x2c, command and status register of the SRAB */ ++ uint32 wd_h; /* 0x30, high order word of write data to switch registe */ ++ uint32 wd_l; /* 0x34, low order word of write data to switch registe */ ++ uint32 rd_h; /* 0x38, high order word of read data from switch register */ ++ uint32 rd_l; /* 0x3c, low order word of read data from switch register */ ++ uint32 ctrls; /* 0x40, switch interface controls */ ++ uint32 intr; /* 0x44, the register captures interrupt pulses from the switch */ ++} srabregs_t; ++ ++/* Forward declaration */ ++typedef struct robo_info_s robo_info_t; ++ ++/* Device access/config oprands */ ++typedef struct { ++ /* low level routines */ ++ void (*enable_mgmtif)(robo_info_t *robo); /* enable mgmt i/f, optional */ ++ void (*disable_mgmtif)(robo_info_t *robo); /* disable mgmt i/f, optional */ ++ int (*write_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); ++ int (*read_reg)(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len); ++ /* description */ ++ char *desc; ++} dev_ops_t; ++ ++ ++typedef uint16 (*miird_f)(void *h, int add, int off); ++typedef void (*miiwr_f)(void *h, int add, int off, uint16 val); ++ ++/* Private state per RoboSwitch */ ++struct robo_info_s { ++ si_t *sih; /* SiliconBackplane handle */ ++ char *vars; /* nvram variables handle */ ++ void *h; /* dev handle */ ++ uint16 devid; /* Device id for the switch */ ++ uint32 devid32; /* Device id for the switch (32bits) */ ++ uint32 corerev; /* Core rev of internal switch */ ++ ++ dev_ops_t *ops; /* device ops */ ++ uint8 page; /* current page */ ++ ++ /* SPI */ ++ uint32 ss, sck, mosi, miso; /* GPIO mapping */ ++ ++ /* MII */ ++ miird_f miird; ++ miiwr_f miiwr; ++ ++ /* SRAB */ ++ srabregs_t *srabregs; ++ ++ uint16 prev_status; /* link status of switch ports */ ++ uint32 pwrsave_mode_manual; /* bitmap of ports in manual power save */ ++ uint32 pwrsave_mode_auto; /* bitmap of ports in auto power save mode */ ++ uint8 pwrsave_phys; /* Phys that can be put into power save mode */ ++ uint8 pwrsave_mode_phys[MAX_NO_PHYS]; /* Power save mode on the switch */ ++}; ++ ++extern int srab_sgmii_rreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val); ++extern int srab_sgmii_wreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val); ++ ++/* Power Save mode related functions */ ++extern int32 robo_power_save_mode_get(robo_info_t *robo, int32 phy); ++extern int32 robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy); ++extern void robo_power_save_mode_update(robo_info_t *robo); ++extern int robo_power_save_mode(robo_info_t *robo, int mode, int phy); ++extern int robo_power_save_toggle(robo_info_t *robo, int normal); ++ ++extern robo_info_t *bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr); ++extern void bcm_robo_detach(robo_info_t *robo); ++extern int bcm_robo_enable_device(robo_info_t *robo); ++extern int bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr); ++extern int bcm_robo_enable_switch(robo_info_t *robo); ++extern int robo_is_port5_cpu(void); ++extern int robo_is_port_cfg(int port, char *cfg); ++ ++extern void robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b); ++ ++extern void robo_watchdog(robo_info_t *robo); ++ ++void robo_reset_mib(robo_info_t *robo); ++void robo_dump_mib(robo_info_t *robo); ++void robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b); ++ ++#endif /* _bcm_robo_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsdh.h b/drivers/bcmdrivers/gmac/src/include/bcmsdh.h +new file mode 100755 +index 0000000..2767f73 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsdh.h +@@ -0,0 +1,226 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SDIO host client driver interface of Broadcom HNBU ++ * export functions to client drivers ++ * abstract OS and BUS specific details of SDIO ++ * ++ * $Id: bcmsdh.h 299859 2011-12-01 03:53:27Z $ ++ */ ++ ++/** ++ * @file bcmsdh.h ++ */ ++ ++#ifndef _bcmsdh_h_ ++#define _bcmsdh_h_ ++ ++#define BCMSDH_ERROR_VAL 0x0001 /* Error */ ++#define BCMSDH_INFO_VAL 0x0002 /* Info */ ++extern const uint bcmsdh_msglevel; ++ ++#ifdef BCMDBG ++#define BCMSDH_ERROR(x) do { if (bcmsdh_msglevel & BCMSDH_ERROR_VAL) printf x; } while (0) ++#define BCMSDH_INFO(x) do { if (bcmsdh_msglevel & BCMSDH_INFO_VAL) printf x; } while (0) ++#else /* BCMDBG */ ++#define BCMSDH_ERROR(x) ++#define BCMSDH_INFO(x) ++#endif /* BCMDBG */ ++ ++ ++/* forward declarations */ ++typedef struct bcmsdh_info bcmsdh_info_t; ++typedef void (*bcmsdh_cb_fn_t)(void *); ++ ++/* Attach and build an interface to the underlying SD host driver. ++ * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. ++ * - Returns the bcmsdh handle and virtual address base for register access. ++ * The returned handle should be used in all subsequent calls, but the bcmsh ++ * implementation may maintain a single "default" handle (e.g. the first or ++ * most recent one) to enable single-instance implementations to pass NULL. ++ */ ++extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq); ++ ++/* Detach - freeup resources allocated in attach */ ++extern int bcmsdh_detach(osl_t *osh, void *sdh); ++ ++/* Query if SD device interrupts are enabled */ ++extern bool bcmsdh_intr_query(void *sdh); ++ ++/* Enable/disable SD interrupt */ ++extern int bcmsdh_intr_enable(void *sdh); ++extern int bcmsdh_intr_disable(void *sdh); ++ ++/* Register/deregister device interrupt handler. */ ++extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++extern int bcmsdh_intr_dereg(void *sdh); ++ ++#if defined(DHD_DEBUG) || defined(BCMDBG) ++/* Query pending interrupt status from the host controller */ ++extern bool bcmsdh_intr_pending(void *sdh); ++#endif ++ ++/* Register a callback to be called if and when bcmsdh detects ++ * device removal. No-op in the case of non-removable/hardwired devices. ++ */ ++extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++ ++/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). ++ * fn: function number ++ * addr: unmodified SDIO-space address ++ * data: data byte to write ++ * err: pointer to error code (or NULL) ++ */ ++extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err); ++extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err); ++ ++/* Read/Write 4bytes from/to cfg space */ ++extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err); ++extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err); ++ ++/* Read CIS content for specified function. ++ * fn: function whose CIS is being requested (0 is common CIS) ++ * cis: pointer to memory location to place results ++ * length: number of bytes to read ++ * Internally, this routine uses the values from the cis base regs (0x9-0xB) ++ * to form an SDIO-space address to read the data from. ++ */ ++extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length); ++ ++/* Synchronous access to device (client) core registers via CMD53 to F1. ++ * addr: backplane address (i.e. >= regsva from attach) ++ * size: register width in bytes (2 or 4) ++ * data: data for register write ++ */ ++extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size); ++extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data); ++ ++/* set sb address window */ ++extern int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set); ++ ++/* Indicate if last reg read/write failed */ ++extern bool bcmsdh_regfail(void *sdh); ++ ++/* Buffer transfer to/from device (client) core via cmd53. ++ * fn: function number ++ * addr: backplane address (i.e. >= regsva from attach) ++ * flags: backplane width, address increment, sync/async ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * pkt: pointer to packet associated with buf (if any) ++ * complete: callback function for command completion (async only) ++ * handle: handle for completion callback (first arg in callback) ++ * Returns 0 or error code. ++ * NOTE: Async operation is not currently supported. ++ */ ++typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting); ++extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++ ++/* Flags bits */ ++#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */ ++#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */ ++#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */ ++#define SDIO_BYTE_MODE 0x8 /* Byte mode request(non-block mode) */ ++ ++/* Pending (non-error) return code */ ++#define BCME_PENDING 1 ++ ++/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). ++ * rw: read or write (0/1) ++ * addr: direct SDIO address ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * Returns 0 or error code. ++ */ ++extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes); ++ ++/* Issue an abort to the specified function */ ++extern int bcmsdh_abort(void *sdh, uint fn); ++ ++/* Start SDIO Host Controller communication */ ++extern int bcmsdh_start(void *sdh, int stage); ++ ++/* Stop SDIO Host Controller communication */ ++extern int bcmsdh_stop(void *sdh); ++ ++/* Wait system lock free */ ++extern int bcmsdh_waitlockfree(void *sdh); ++ ++/* Returns the "Device ID" of target device on the SDIO bus. */ ++extern int bcmsdh_query_device(void *sdh); ++ ++/* Returns the number of IO functions reported by the device */ ++extern uint bcmsdh_query_iofnum(void *sdh); ++ ++/* Miscellaneous knob tweaker. */ ++extern int bcmsdh_iovar_op(void *sdh, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Reset and reinitialize the device */ ++extern int bcmsdh_reset(bcmsdh_info_t *sdh); ++ ++/* helper functions */ ++ ++extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); ++ ++/* callback functions */ ++typedef struct { ++ /* attach to device */ ++ void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot, ++ uint16 func, uint bustype, void * regsva, osl_t * osh, ++ void * param); ++ /* detach from device */ ++ void (*detach)(void *ch); ++} bcmsdh_driver_t; ++ ++/* platform specific/high level functions */ ++extern int bcmsdh_register(bcmsdh_driver_t *driver); ++extern void bcmsdh_unregister(void); ++extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device); ++extern void bcmsdh_device_remove(void * sdh); ++ ++#if defined(OOB_INTR_ONLY) ++extern int bcmsdh_register_oob_intr(void * dhdp); ++extern void bcmsdh_unregister_oob_intr(void); ++extern void bcmsdh_oob_intr_set(bool enable); ++#endif /* defined(OOB_INTR_ONLY) */ ++ ++/* Function to pass device-status bits to DHD. */ ++extern uint32 bcmsdh_get_dstatus(void *sdh); ++ ++/* Function to return current window addr */ ++extern uint32 bcmsdh_cur_sbwad(void *sdh); ++ ++/* Function to pass chipid and rev to lower layers for controlling pr's */ ++extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev); ++ ++#ifdef BCMSPI ++extern void bcmsdh_dwordmode(void *sdh, bool set); ++#endif /* BCMSPI */ ++ ++extern int bcmsdh_sleep(void *sdh, bool enab); ++ ++/* GPIO support */ ++extern int bcmsdh_gpio_init(void *sd); ++extern bool bcmsdh_gpioin(void *sd, uint32 gpio); ++extern int bcmsdh_gpioouten(void *sd, uint32 gpio); ++extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab); ++ ++#endif /* _bcmsdh_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h b/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h +new file mode 100755 +index 0000000..c1a320c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsdpcm.h +@@ -0,0 +1,268 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SDIO/PCMCIA ++ * Software-specific definitions shared between device and host side ++ * ++ * $Id: bcmsdpcm.h 314495 2012-02-12 07:56:39Z $ ++ */ ++ ++#ifndef _bcmsdpcm_h_ ++#define _bcmsdpcm_h_ ++ ++/* ++ * Software allocation of To SB Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */ ++#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */ ++#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */ ++#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOSBMAIL (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT) ++ ++/* tosbmailbox bits corresponding to intstatus bits */ ++#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */ ++#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */ ++#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */ ++#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */ ++#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */ ++ ++/* tosbmailboxdata */ ++#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ ++#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ ++ ++/* ++ * Software allocation of To Host Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */ ++#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */ ++#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */ ++#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOHOSTMAIL (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT) ++ ++/* tohostmailbox bits corresponding to intstatus bits */ ++#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */ ++#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */ ++#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */ ++#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */ ++#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */ ++ ++/* tohostmailboxdata */ ++#define HMB_DATA_NAKHANDLED 0x01 /* we're ready to retransmit NAK'd frame to host */ ++#define HMB_DATA_DEVREADY 0x02 /* we're ready to to talk to host after enable */ ++#define HMB_DATA_FC 0x04 /* per prio flowcontrol update flag to host */ ++#define HMB_DATA_FWREADY 0x08 /* firmware is ready for protocol activity */ ++#define HMB_DATA_FWHALT 0x10 /* firmware has halted operation */ ++ ++#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ ++#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ ++ ++#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */ ++#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */ ++ ++/* ++ * Software-defined protocol header ++ */ ++ ++/* Current protocol version */ ++#define SDPCM_PROT_VERSION 4 ++ ++/* SW frame header */ ++#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */ ++#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */ ++ ++#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */ ++#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */ ++#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */ ++ ++#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */ ++#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */ ++#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */ ++ ++/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */ ++#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */ ++#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */ ++#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */ ++#define SDPCM_NEXTLEN_OFFSET 2 ++ ++/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ ++#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ ++#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) ++#define SDPCM_DOFFSET_MASK 0xff000000 ++#define SDPCM_DOFFSET_SHIFT 24 ++ ++#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ ++#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff) ++#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ ++#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) ++#define SDPCM_VERSION_OFFSET 6 /* Version # */ ++#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff) ++#define SDPCM_UNUSED_OFFSET 7 /* Spare */ ++#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff) ++ ++#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ ++ ++/* logical channel numbers */ ++#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */ ++#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ ++#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ ++#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */ ++#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ ++#define SDPCM_MAX_CHANNEL 15 ++ ++#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */ ++ ++#define SDPCM_FLAG_RESVD0 0x01 ++#define SDPCM_FLAG_RESVD1 0x02 ++#define SDPCM_FLAG_GSPI_TXENAB 0x04 ++#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */ ++ ++/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */ ++#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT) ++ ++#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) ++ ++/* For TEST_CHANNEL packets, define another 4-byte header */ ++#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); ++ * Semantics of Ext byte depend on command. ++ * Len is current or requested frame length, not ++ * including test header; sent little-endian. ++ */ ++#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ ++#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count */ ++#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off */ ++ ++/* Handy macro for filling in datagen packets with a pattern */ ++#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) ++ ++/* ++ * Software counters (first part matches hardware counters) ++ */ ++ ++typedef volatile struct { ++ uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */ ++ uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */ ++ uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */ ++ uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */ ++ uint32 abort; /* AbortCount, SDIO: aborts */ ++ uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */ ++ uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */ ++ uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */ ++ uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */ ++ uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */ ++ uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */ ++ uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */ ++ uint32 rxdescuflo; /* receive descriptor underflows */ ++ uint32 rxfifooflo; /* receive fifo overflows */ ++ uint32 txfifouflo; /* transmit fifo underflows */ ++ uint32 runt; /* runt (too short) frames recv'd from bus */ ++ uint32 badlen; /* frame's rxh len does not match its hw tag len */ ++ uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */ ++ uint32 seqbreak; /* break in sequence # space from one rx frame to the next */ ++ uint32 rxfcrc; /* frame rx header indicates crc error */ ++ uint32 rxfwoos; /* frame rx header indicates write out of sync */ ++ uint32 rxfwft; /* frame rx header indicates write frame termination */ ++ uint32 rxfabort; /* frame rx header indicates frame aborted */ ++ uint32 woosint; /* write out of sync interrupt */ ++ uint32 roosint; /* read out of sync interrupt */ ++ uint32 rftermint; /* read frame terminate interrupt */ ++ uint32 wftermint; /* write frame terminate interrupt */ ++} sdpcmd_cnt_t; ++ ++/* ++ * Register Access Macros ++ */ ++ ++#define SDIODREV_IS(var, val) ((var) == (val)) ++#define SDIODREV_GE(var, val) ((var) >= (val)) ++#define SDIODREV_GT(var, val) ((var) > (val)) ++#define SDIODREV_LT(var, val) ((var) < (val)) ++#define SDIODREV_LE(var, val) ((var) <= (val)) ++ ++#define SDIODDMAREG32(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv)) ++ ++#define SDIODDMAREG64(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv)) ++ ++#define SDIODDMAREG(h, dir, chnl) \ ++ (SDIODREV_LT((h)->corerev, 1) ? \ ++ SDIODDMAREG32((h), (dir), (chnl)) : \ ++ SDIODDMAREG64((h), (dir), (chnl))) ++ ++#define PCMDDMAREG(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv)) ++ ++#define SDPCMDMAREG(h, dir, chnl, coreid) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODDMAREG(h, dir, chnl) : \ ++ PCMDDMAREG(h, dir, chnl)) ++ ++#define SDIODFIFOREG(h, corerev) \ ++ (SDIODREV_LT((corerev), 1) ? \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo))) ++ ++#define PCMDFIFOREG(h) \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo)) ++ ++#define SDPCMFIFOREG(h, coreid, corerev) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODFIFOREG(h, corerev) : \ ++ PCMDFIFOREG(h)) ++ ++/* ++ * Shared structure between dongle and the host. ++ * The structure contains pointers to trap or assert information. ++ */ ++#define SDPCM_SHARED_VERSION 0x0001 ++#define SDPCM_SHARED_VERSION_MASK 0x00FF ++#define SDPCM_SHARED_ASSERT_BUILT 0x0100 ++#define SDPCM_SHARED_ASSERT 0x0200 ++#define SDPCM_SHARED_TRAP 0x0400 ++#define SDPCM_SHARED_IN_BRPT 0x0800 ++#define SDPCM_SHARED_SET_BRPT 0x1000 ++#define SDPCM_SHARED_PENDING_BRPT 0x2000 ++ ++typedef struct { ++ uint32 flags; ++ uint32 trap_addr; ++ uint32 assert_exp_addr; ++ uint32 assert_file_addr; ++ uint32 assert_line; ++ uint32 console_addr; /* Address of hndrte_cons_t */ ++ uint32 msgtrace_addr; ++ uint32 fwid; ++} sdpcm_shared_t; ++ ++extern sdpcm_shared_t sdpcm_shared; ++ ++/* Function can be used to notify host of FW halt */ ++extern void sdpcmd_fwhalt(void); ++ ++#endif /* _bcmsdpcm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom.h +new file mode 100755 +index 0000000..0e6c210 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc useful routines to access NIC local SROM/OTP . ++ * ++ * $Id: bcmsrom.h 280889 2011-08-31 18:39:27Z $ ++ */ ++ ++#ifndef _bcmsrom_h_ ++#define _bcmsrom_h_ ++ ++#include ++ ++/* Prototypes */ ++extern int srom_var_init(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ char **vars, uint *count); ++extern void srom_var_deinit(si_t *sih); ++ ++extern int srom_read(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf, ++ bool check_crc); ++ ++extern int srom_write(si_t *sih, uint bus, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf); ++ ++extern int srom_otp_cisrwvar(si_t *sih, osl_t *osh, char *vars, int *count); ++#if defined(WLTEST) || defined(BCMDBG) ++extern int srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write); ++#endif ++ ++/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP ++ * and extract from it into name=value pairs ++ */ ++extern int srom_probe_boardtype(uint8 *pcis[], uint ciscnt); ++extern int srom_parsecis(osl_t *osh, uint8 **pcis, uint ciscnt, ++ char **vars, uint *count); ++ ++#if defined(BCMUSBDEV) ++/* Return sprom size in 16-bit words */ ++extern uint srom_size(si_t *sih, osl_t *osh); ++#endif ++ ++#endif /* _bcmsrom_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h +new file mode 100755 +index 0000000..9f90ed8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom_fmt.h +@@ -0,0 +1,549 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SROM format definition. ++ * ++ * $Id: bcmsrom_fmt.h 322525 2012-03-21 01:28:39Z $ ++ */ ++ ++#ifndef _bcmsrom_fmt_h_ ++#define _bcmsrom_fmt_h_ ++ ++#define SROM_MAXREV 11 /* max revisiton supported by driver */ ++ ++/* Maximum srom: 6 Kilobits == 768 bytes */ ++#define SROM_MAX 768 ++#define SROM_MAXW 384 ++#define VARS_MAX 4096 ++ ++/* PCI fields */ ++#define PCI_F0DEVID 48 ++ ++ ++#define SROM_WORDS 64 ++ ++#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ ++ ++#define SROM_SSID 2 ++ ++#define SROM_WL1LHMAXP 29 ++ ++#define SROM_WL1LPAB0 30 ++#define SROM_WL1LPAB1 31 ++#define SROM_WL1LPAB2 32 ++ ++#define SROM_WL1HPAB0 33 ++#define SROM_WL1HPAB1 34 ++#define SROM_WL1HPAB2 35 ++ ++#define SROM_MACHI_IL0 36 ++#define SROM_MACMID_IL0 37 ++#define SROM_MACLO_IL0 38 ++#define SROM_MACHI_ET0 39 ++#define SROM_MACMID_ET0 40 ++#define SROM_MACLO_ET0 41 ++#define SROM_MACHI_ET1 42 ++#define SROM_MACMID_ET1 43 ++#define SROM_MACLO_ET1 44 ++#define SROM3_MACHI 37 ++#define SROM3_MACMID 38 ++#define SROM3_MACLO 39 ++ ++#define SROM_BXARSSI2G 40 ++#define SROM_BXARSSI5G 41 ++ ++#define SROM_TRI52G 42 ++#define SROM_TRI5GHL 43 ++ ++#define SROM_RXPO52G 45 ++ ++#define SROM2_ENETPHY 45 ++ ++#define SROM_AABREV 46 ++/* Fields in AABREV */ ++#define SROM_BR_MASK 0x00ff ++#define SROM_CC_MASK 0x0f00 ++#define SROM_CC_SHIFT 8 ++#define SROM_AA0_MASK 0x3000 ++#define SROM_AA0_SHIFT 12 ++#define SROM_AA1_MASK 0xc000 ++#define SROM_AA1_SHIFT 14 ++ ++#define SROM_WL0PAB0 47 ++#define SROM_WL0PAB1 48 ++#define SROM_WL0PAB2 49 ++ ++#define SROM_LEDBH10 50 ++#define SROM_LEDBH32 51 ++ ++#define SROM_WL10MAXP 52 ++ ++#define SROM_WL1PAB0 53 ++#define SROM_WL1PAB1 54 ++#define SROM_WL1PAB2 55 ++ ++#define SROM_ITT 56 ++ ++#define SROM_BFL 57 ++#define SROM_BFL2 28 ++#define SROM3_BFL2 61 ++ ++#define SROM_AG10 58 ++ ++#define SROM_CCODE 59 ++ ++#define SROM_OPO 60 ++ ++#define SROM3_LEDDC 62 ++ ++#define SROM_CRCREV 63 ++ ++/* SROM Rev 4: Reallocate the software part of the srom to accomodate ++ * MIMO features. It assumes up to two PCIE functions and 440 bytes ++ * of useable srom i.e. the useable storage in chips with OTP that ++ * implements hardware redundancy. ++ */ ++ ++#define SROM4_WORDS 220 ++ ++#define SROM4_SIGN 32 ++#define SROM4_SIGNATURE 0x5372 ++ ++#define SROM4_BREV 33 ++ ++#define SROM4_BFL0 34 ++#define SROM4_BFL1 35 ++#define SROM4_BFL2 36 ++#define SROM4_BFL3 37 ++#define SROM5_BFL0 37 ++#define SROM5_BFL1 38 ++#define SROM5_BFL2 39 ++#define SROM5_BFL3 40 ++ ++#define SROM4_MACHI 38 ++#define SROM4_MACMID 39 ++#define SROM4_MACLO 40 ++#define SROM5_MACHI 41 ++#define SROM5_MACMID 42 ++#define SROM5_MACLO 43 ++ ++#define SROM4_CCODE 41 ++#define SROM4_REGREV 42 ++#define SROM5_CCODE 34 ++#define SROM5_REGREV 35 ++ ++#define SROM4_LEDBH10 43 ++#define SROM4_LEDBH32 44 ++#define SROM5_LEDBH10 59 ++#define SROM5_LEDBH32 60 ++ ++#define SROM4_LEDDC 45 ++#define SROM5_LEDDC 45 ++ ++#define SROM4_AA 46 ++#define SROM4_AA2G_MASK 0x00ff ++#define SROM4_AA2G_SHIFT 0 ++#define SROM4_AA5G_MASK 0xff00 ++#define SROM4_AA5G_SHIFT 8 ++ ++#define SROM4_AG10 47 ++#define SROM4_AG32 48 ++ ++#define SROM4_TXPID2G 49 ++#define SROM4_TXPID5G 51 ++#define SROM4_TXPID5GL 53 ++#define SROM4_TXPID5GH 55 ++ ++#define SROM4_TXRXC 61 ++#define SROM4_TXCHAIN_MASK 0x000f ++#define SROM4_TXCHAIN_SHIFT 0 ++#define SROM4_RXCHAIN_MASK 0x00f0 ++#define SROM4_RXCHAIN_SHIFT 4 ++#define SROM4_SWITCH_MASK 0xff00 ++#define SROM4_SWITCH_SHIFT 8 ++ ++ ++/* Per-path fields */ ++#define MAX_PATH_SROM 4 ++#define SROM4_PATH0 64 ++#define SROM4_PATH1 87 ++#define SROM4_PATH2 110 ++#define SROM4_PATH3 133 ++ ++#define SROM4_2G_ITT_MAXP 0 ++#define SROM4_2G_PA 1 ++#define SROM4_5G_ITT_MAXP 5 ++#define SROM4_5GLH_MAXP 6 ++#define SROM4_5G_PA 7 ++#define SROM4_5GL_PA 11 ++#define SROM4_5GH_PA 15 ++ ++/* Fields in the ITT_MAXP and 5GLH_MAXP words */ ++#define B2G_MAXP_MASK 0xff ++#define B2G_ITT_SHIFT 8 ++#define B5G_MAXP_MASK 0xff ++#define B5G_ITT_SHIFT 8 ++#define B5GH_MAXP_MASK 0xff ++#define B5GL_MAXP_SHIFT 8 ++ ++/* All the miriad power offsets */ ++#define SROM4_2G_CCKPO 156 ++#define SROM4_2G_OFDMPO 157 ++#define SROM4_5G_OFDMPO 159 ++#define SROM4_5GL_OFDMPO 161 ++#define SROM4_5GH_OFDMPO 163 ++#define SROM4_2G_MCSPO 165 ++#define SROM4_5G_MCSPO 173 ++#define SROM4_5GL_MCSPO 181 ++#define SROM4_5GH_MCSPO 189 ++#define SROM4_CDDPO 197 ++#define SROM4_STBCPO 198 ++#define SROM4_BW40PO 199 ++#define SROM4_BWDUPPO 200 ++ ++#define SROM4_CRCREV 219 ++ ++ ++/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. ++ * This is acombined srom for both MIMO and SISO boards, usable in ++ * the .130 4Kilobit OTP with hardware redundancy. ++ */ ++ ++#define SROM8_SIGN 64 ++ ++#define SROM8_BREV 65 ++ ++#define SROM8_BFL0 66 ++#define SROM8_BFL1 67 ++#define SROM8_BFL2 68 ++#define SROM8_BFL3 69 ++ ++#define SROM8_MACHI 70 ++#define SROM8_MACMID 71 ++#define SROM8_MACLO 72 ++ ++#define SROM8_CCODE 73 ++#define SROM8_REGREV 74 ++ ++#define SROM8_LEDBH10 75 ++#define SROM8_LEDBH32 76 ++ ++#define SROM8_LEDDC 77 ++ ++#define SROM8_AA 78 ++ ++#define SROM8_AG10 79 ++#define SROM8_AG32 80 ++ ++#define SROM8_TXRXC 81 ++ ++#define SROM8_BXARSSI2G 82 ++#define SROM8_BXARSSI5G 83 ++#define SROM8_TRI52G 84 ++#define SROM8_TRI5GHL 85 ++#define SROM8_RXPO52G 86 ++ ++#define SROM8_FEM2G 87 ++#define SROM8_FEM5G 88 ++#define SROM8_FEM_ANTSWLUT_MASK 0xf800 ++#define SROM8_FEM_ANTSWLUT_SHIFT 11 ++#define SROM8_FEM_TR_ISO_MASK 0x0700 ++#define SROM8_FEM_TR_ISO_SHIFT 8 ++#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 ++#define SROM8_FEM_PDET_RANGE_SHIFT 3 ++#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 ++#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 ++#define SROM8_FEM_TSSIPOS_MASK 0x0001 ++#define SROM8_FEM_TSSIPOS_SHIFT 0 ++ ++#define SROM8_THERMAL 89 ++ ++/* Temp sense related entries */ ++#define SROM8_MPWR_RAWTS 90 ++#define SROM8_TS_SLP_OPT_CORRX 91 ++/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */ ++#define SROM8_FOC_HWIQ_IQSWP 92 ++ ++#define SROM8_EXTLNAGAIN 93 ++ ++/* Temperature delta for PHY calibration */ ++#define SROM8_PHYCAL_TEMPDELTA 94 ++ ++/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */ ++#define SROM8_MPWR_1_AND_2 95 ++ ++ ++/* Per-path offsets & fields */ ++#define SROM8_PATH0 96 ++#define SROM8_PATH1 112 ++#define SROM8_PATH2 128 ++#define SROM8_PATH3 144 ++ ++#define SROM8_2G_ITT_MAXP 0 ++#define SROM8_2G_PA 1 ++#define SROM8_5G_ITT_MAXP 4 ++#define SROM8_5GLH_MAXP 5 ++#define SROM8_5G_PA 6 ++#define SROM8_5GL_PA 9 ++#define SROM8_5GH_PA 12 ++ ++/* All the miriad power offsets */ ++#define SROM8_2G_CCKPO 160 ++ ++#define SROM8_2G_OFDMPO 161 ++#define SROM8_5G_OFDMPO 163 ++#define SROM8_5GL_OFDMPO 165 ++#define SROM8_5GH_OFDMPO 167 ++ ++#define SROM8_2G_MCSPO 169 ++#define SROM8_5G_MCSPO 177 ++#define SROM8_5GL_MCSPO 185 ++#define SROM8_5GH_MCSPO 193 ++ ++#define SROM8_CDDPO 201 ++#define SROM8_STBCPO 202 ++#define SROM8_BW40PO 203 ++#define SROM8_BWDUPPO 204 ++ ++/* SISO PA parameters are in the path0 spaces */ ++#define SROM8_SISO 96 ++ ++/* Legacy names for SISO PA paramters */ ++#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) ++#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) ++#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) ++#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) ++#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) ++#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) ++#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) ++#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) ++#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) ++#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) ++#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) ++#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) ++#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) ++#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) ++#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) ++ ++#define SROM8_CRCREV 219 ++ ++/* SROM REV 9 */ ++#define SROM9_2GPO_CCKBW20 160 ++#define SROM9_2GPO_CCKBW20UL 161 ++#define SROM9_2GPO_LOFDMBW20 162 ++#define SROM9_2GPO_LOFDMBW20UL 164 ++ ++#define SROM9_5GLPO_LOFDMBW20 166 ++#define SROM9_5GLPO_LOFDMBW20UL 168 ++#define SROM9_5GMPO_LOFDMBW20 170 ++#define SROM9_5GMPO_LOFDMBW20UL 172 ++#define SROM9_5GHPO_LOFDMBW20 174 ++#define SROM9_5GHPO_LOFDMBW20UL 176 ++ ++#define SROM9_2GPO_MCSBW20 178 ++#define SROM9_2GPO_MCSBW20UL 180 ++#define SROM9_2GPO_MCSBW40 182 ++ ++#define SROM9_5GLPO_MCSBW20 184 ++#define SROM9_5GLPO_MCSBW20UL 186 ++#define SROM9_5GLPO_MCSBW40 188 ++#define SROM9_5GMPO_MCSBW20 190 ++#define SROM9_5GMPO_MCSBW20UL 192 ++#define SROM9_5GMPO_MCSBW40 194 ++#define SROM9_5GHPO_MCSBW20 196 ++#define SROM9_5GHPO_MCSBW20UL 198 ++#define SROM9_5GHPO_MCSBW40 200 ++ ++#define SROM9_PO_MCS32 202 ++#define SROM9_PO_LOFDM40DUP 203 ++#define SROM8_RXGAINERR_2G 205 ++#define SROM8_RXGAINERR_5GL 206 ++#define SROM8_RXGAINERR_5GM 207 ++#define SROM8_RXGAINERR_5GH 208 ++#define SROM8_RXGAINERR_5GU 209 ++#define SROM8_SUBBAND_PPR 210 ++#define SROM8_PCIEINGRESS_WAR 211 ++#define SROM9_SAR 212 ++ ++#define SROM8_NOISELVL_2G 213 ++#define SROM8_NOISELVL_5GL 214 ++#define SROM8_NOISELVL_5GM 215 ++#define SROM8_NOISELVL_5GH 216 ++#define SROM8_NOISELVL_5GU 217 ++ ++#define SROM9_REV_CRC 219 ++ ++#define SROM10_CCKPWROFFSET 218 ++#define SROM10_SIGN 219 ++#define SROM10_SWCTRLMAP_2G 220 ++#define SROM10_CRCREV 229 ++ ++#define SROM10_WORDS 230 ++#define SROM10_SIGNATURE SROM4_SIGNATURE ++ ++ ++/* SROM REV 11 */ ++#define SROM11_BREV 65 ++ ++#define SROM11_BFL0 66 ++#define SROM11_BFL1 67 ++#define SROM11_BFL2 68 ++#define SROM11_BFL3 69 ++#define SROM11_BFL4 70 ++#define SROM11_BFL5 71 ++ ++#define SROM11_MACHI 72 ++#define SROM11_MACMID 73 ++#define SROM11_MACLO 74 ++ ++#define SROM11_CCODE 75 ++#define SROM11_REGREV 76 ++ ++#define SROM11_LEDBH10 77 ++#define SROM11_LEDBH32 78 ++ ++#define SROM11_LEDDC 79 ++ ++#define SROM11_AA 80 ++ ++#define SROM11_AGBG10 81 ++#define SROM11_AGBG2A0 82 ++#define SROM11_AGA21 83 ++ ++#define SROM11_TXRXC 84 ++ ++#define SROM11_FEM_CFG1 85 ++#define SROM11_FEM_CFG2 86 ++ ++#define SROM11_THERMAL 87 ++#define SROM11_MPWR_RAWTS 88 ++#define SROM11_TS_SLP_OPT_CORRX 89 ++#define SROM11_PHYCAL_TEMPDELTA 92 ++#define SROM11_MPWR_1_AND_2 93 ++ ++#define SROM11_PDOFF_40M_A0 101 ++#define SROM11_PDOFF_40M_A1 102 ++#define SROM11_PDOFF_40M_A2 103 ++#define SROM11_PDOFF_80M_A0 104 ++#define SROM11_PDOFF_80M_A1 105 ++#define SROM11_PDOFF_80M_A2 106 ++ ++#define SROM11_SUBBAND5GVER 107 ++ ++/* Per-path fields and offset */ ++#define MAX_PATH_SROM_11 3 ++#define SROM11_PATH0 108 ++#define SROM11_PATH1 128 ++#define SROM11_PATH2 148 ++ ++#define SROM11_2G_MAXP 0 ++#define SROM11_2G_PA 1 ++#define SROM11_RXGAINS1 4 ++#define SROM11_RXGAINS 5 ++#define SROM11_5GB1B0_MAXP 6 ++#define SROM11_5GB3B2_MAXP 7 ++#define SROM11_5GB0_PA 8 ++#define SROM11_5GB1_PA 11 ++#define SROM11_5GB2_PA 14 ++#define SROM11_5GB3_PA 17 ++ ++/* Power per rate */ ++#define SROM11_CCKBW202GPO 168 ++#define SROM11_CCKBW20UL2GPO 169 ++#define SROM11_MCSBW202GPO 170 ++#define SROM11_MCSBW202GPO_1 171 ++#define SROM11_MCSBW402GPO 172 ++#define SROM11_MCSBW402GPO_1 173 ++#define SROM11_DOT11AGOFDMHRBW202GPO 174 ++#define SROM11_OFDMLRBW202GPO 175 ++ ++#define SROM11_MCSBW205GLPO 176 ++#define SROM11_MCSBW205GLPO_1 177 ++#define SROM11_MCSBW405GLPO 178 ++#define SROM11_MCSBW405GLPO_1 179 ++#define SROM11_MCSBW805GLPO 180 ++#define SROM11_MCSBW805GLPO_1 181 ++#define SROM11_MCSBW1605GLPO 182 ++#define SROM11_MCSBW1605GLPO_1 183 ++#define SROM11_MCSBW205GMPO 184 ++#define SROM11_MCSBW205GMPO_1 185 ++#define SROM11_MCSBW405GMPO 186 ++#define SROM11_MCSBW405GMPO_1 187 ++#define SROM11_MCSBW805GMPO 188 ++#define SROM11_MCSBW805GMPO_1 189 ++#define SROM11_MCSBW1605GMPO 190 ++#define SROM11_MCSBW1605GMPO_1 191 ++#define SROM11_MCSBW205GHPO 192 ++#define SROM11_MCSBW205GHPO_1 193 ++#define SROM11_MCSBW405GHPO 194 ++#define SROM11_MCSBW405GHPO_1 195 ++#define SROM11_MCSBW805GHPO 196 ++#define SROM11_MCSBW805GHPO_1 197 ++#define SROM11_MCSBW1605GHPO 198 ++#define SROM11_MCSBW1605GHPO_1 199 ++ ++#define SROM11_MCSLR5GLPO 200 ++#define SROM11_MCSLR5GMPO 201 ++#define SROM11_MCSLR5GHPO 202 ++ ++#define SROM11_SB20IN40HRPO 203 ++#define SROM11_SB20IN80AND160HR5GLPO 204 ++#define SROM11_SB40AND80HR5GLPO 205 ++#define SROM11_SB20IN80AND160HR5GMPO 206 ++#define SROM11_SB40AND80HR5GMPO 207 ++#define SROM11_SB20IN80AND160HR5GHPO 208 ++#define SROM11_SB40AND80HR5GHPO 209 ++#define SROM11_SB20IN40LRPO 210 ++#define SROM11_SB20IN80AND160LR5GLPO 211 ++#define SROM11_SB40AND80LR5GLPO 212 ++#define SROM11_SB20IN80AND160LR5GMPO 213 ++#define SROM11_SB40AND80LR5GMPO 214 ++#define SROM11_SB20IN80AND160LR5GHPO 215 ++#define SROM11_SB40AND80LR5GHPO 216 ++ ++#define SROM11_DOT11AGDUPHRPO 217 ++#define SROM11_DOT11AGDUPLRPO 218 ++ ++/* MISC */ ++#define SROM11_PCIEINGRESS_WAR 220 ++#define SROM11_SAR 221 ++ ++#define SROM11_NOISELVL_2G 222 ++#define SROM11_NOISELVL_5GL 223 ++#define SROM11_NOISELVL_5GM 224 ++#define SROM11_NOISELVL_5GH 225 ++#define SROM11_NOISELVL_5GU 226 ++ ++#define SROM11_RXGAINERR_2G 227 ++#define SROM11_RXGAINERR_5GL 228 ++#define SROM11_RXGAINERR_5GM 229 ++#define SROM11_RXGAINERR_5GH 230 ++#define SROM11_RXGAINERR_5GU 231 ++ ++#define SROM11_SIGN 64 ++#define SROM11_CRCREV 233 ++ ++#define SROM11_WORDS 234 ++#define SROM11_SIGNATURE 0x0634 ++ ++typedef struct { ++ uint8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */ ++ uint8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ ++ uint8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */ ++ uint8 triso; /* TR switch isolation */ ++ uint8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */ ++} srom_fem_t; ++ ++#endif /* _bcmsrom_fmt_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h b/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h +new file mode 100755 +index 0000000..2190d7e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmsrom_tbl.h +@@ -0,0 +1,878 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Table that encodes the srom formats for PCI/PCIe NICs. ++ * ++ * $Id: bcmsrom_tbl.h 324896 2012-03-30 19:35:36Z $ ++ */ ++ ++#ifndef _bcmsrom_tbl_h_ ++#define _bcmsrom_tbl_h_ ++ ++#include "sbpcmcia.h" ++#include "wlioctl.h" ++ ++typedef struct { ++ const char *name; ++ uint32 revmask; ++ uint32 flags; ++ uint16 off; ++ uint16 mask; ++} sromvar_t; ++ ++#define SRFL_MORE 1 /* value continues as described by the next entry */ ++#define SRFL_NOFFS 2 /* value bits can't be all one's */ ++#define SRFL_PRHEX 4 /* value is in hexdecimal format */ ++#define SRFL_PRSIGN 8 /* value is in signed decimal format */ ++#define SRFL_CCODE 0x10 /* value is in country code format */ ++#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ ++#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ ++#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */ ++#define SRFL_ARRAY 0x100 /* value is in an array. All elements EXCEPT FOR THE LAST ++ * ONE in the array should have this flag set. ++ */ ++ ++ ++/* Assumptions: ++ * - Ethernet address spans across 3 consective words ++ * ++ * Table rules: ++ * - Add multiple entries next to each other if a value spans across multiple words ++ * (even multiple fields in the same word) with each entry except the last having ++ * it's SRFL_MORE bit set. ++ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE ++ * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. ++ * - The last entry's name field must be NULL to indicate the end of the table. Other ++ * entries must have non-NULL name. ++ */ ++ ++static const sromvar_t pci_sromvars[] = { ++ {"devid", 0xffffff00, SRFL_PRHEX|SRFL_NOVAR, PCI_F0DEVID, 0xffff}, ++ {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, ++ {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, ++ {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, ++ {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, ++ {"boardflags", 0x00000004, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff}, ++ {"", 0, 0, SROM_BFL2, 0xffff}, ++ {"boardflags", 0x00000008, SRFL_PRHEX|SRFL_MORE, SROM_BFL, 0xffff}, ++ {"", 0, 0, SROM3_BFL2, 0xffff}, ++ {"boardflags", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL0, 0xffff}, ++ {"", 0, 0, SROM4_BFL1, 0xffff}, ++ {"boardflags", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL0, 0xffff}, ++ {"", 0, 0, SROM5_BFL1, 0xffff}, ++ {"boardflags", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL0, 0xffff}, ++ {"", 0, 0, SROM8_BFL1, 0xffff}, ++ {"boardflags2", 0x00000010, SRFL_PRHEX|SRFL_MORE, SROM4_BFL2, 0xffff}, ++ {"", 0, 0, SROM4_BFL3, 0xffff}, ++ {"boardflags2", 0x000000e0, SRFL_PRHEX|SRFL_MORE, SROM5_BFL2, 0xffff}, ++ {"", 0, 0, SROM5_BFL3, 0xffff}, ++ {"boardflags2", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL2, 0xffff}, ++ {"", 0, 0, SROM8_BFL3, 0xffff}, ++ {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, ++ ++ {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, ++ {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, ++ {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, ++ {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, ++ {"boardnum", 0x00000700, 0, SROM8_MACLO, 0xffff}, ++ {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, ++ {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, ++ {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff}, ++ {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff}, ++ {"regrev", 0x00000700, 0, SROM8_REGREV, 0x00ff}, ++ {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, ++ {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, ++ {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, ++ {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, ++ {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, ++ {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, ++ {"ledbh0", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, ++ {"ledbh1", 0x00000700, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, ++ {"ledbh2", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, ++ {"ledbh3", 0x00000700, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, ++ {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, ++ {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, ++ {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, ++ {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff}, ++ {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, ++ {"pa0b0", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, ++ {"pa0b1", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, ++ {"pa0b2", 0x00000700, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, ++ {"pa0itssit", 0x00000700, 0, SROM8_W0_ITTMAXP, 0xff00}, ++ {"pa0maxpwr", 0x00000700, 0, SROM8_W0_ITTMAXP, 0x00ff}, ++ {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff}, ++ {"opo", 0x00000700, 0, SROM8_2G_OFDMPO, 0x00ff}, ++ {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, ++ {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff}, ++ {"aa2g", 0x00000700, 0, SROM8_AA, 0x00ff}, ++ {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, ++ {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, ++ {"aa5g", 0x00000700, 0, SROM8_AA, 0xff00}, ++ {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff}, ++ {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, ++ {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff}, ++ {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, ++ {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff}, ++ {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, ++ {"ag0", 0x00000700, 0, SROM8_AG10, 0x00ff}, ++ {"ag1", 0x00000700, 0, SROM8_AG10, 0xff00}, ++ {"ag2", 0x00000700, 0, SROM8_AG32, 0x00ff}, ++ {"ag3", 0x00000700, 0, SROM8_AG32, 0xff00}, ++ {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, ++ {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, ++ {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, ++ {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, ++ {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, ++ {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, ++ {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, ++ {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, ++ {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, ++ {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, ++ {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, ++ {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, ++ {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, ++ {"pa1b0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, ++ {"pa1b1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, ++ {"pa1b2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, ++ {"pa1lob0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, ++ {"pa1lob1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, ++ {"pa1lob2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, ++ {"pa1hib0", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, ++ {"pa1hib1", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, ++ {"pa1hib2", 0x00000700, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, ++ {"pa1itssit", 0x00000700, 0, SROM8_W1_ITTMAXP, 0xff00}, ++ {"pa1maxpwr", 0x00000700, 0, SROM8_W1_ITTMAXP, 0x00ff}, ++ {"pa1lomaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0xff00}, ++ {"pa1himaxpwr", 0x00000700, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, ++ {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, ++ {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, ++ {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, ++ {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, ++ {"bxa2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x1800}, ++ {"rssisav2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x0700}, ++ {"rssismc2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x00f0}, ++ {"rssismf2g", 0x00000700, 0, SROM8_BXARSSI2G, 0x000f}, ++ {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, ++ {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, ++ {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, ++ {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, ++ {"bxa5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x1800}, ++ {"rssisav5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x0700}, ++ {"rssismc5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x00f0}, ++ {"rssismf5g", 0x00000700, 0, SROM8_BXARSSI5G, 0x000f}, ++ {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff}, ++ {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, ++ {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, ++ {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, ++ {"tri2g", 0x00000700, 0, SROM8_TRI52G, 0x00ff}, ++ {"tri5g", 0x00000700, 0, SROM8_TRI52G, 0xff00}, ++ {"tri5gl", 0x00000700, 0, SROM8_TRI5GHL, 0x00ff}, ++ {"tri5gh", 0x00000700, 0, SROM8_TRI5GHL, 0xff00}, ++ {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, ++ {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, ++ {"rxpo2g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, ++ {"rxpo5g", 0x00000700, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, ++ {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, ++ {"txchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0x00000700, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, ++ {"tssipos2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK}, ++ {"extpagain2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK}, ++ {"pdetrange2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK}, ++ {"triso2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, ++ {"antswctl2g", 0x00000700, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK}, ++ {"tssipos5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK}, ++ {"extpagain5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK}, ++ {"pdetrange5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK}, ++ {"triso5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, ++ {"antswctl5g", 0x00000700, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK}, ++ {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, ++ {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, ++ {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff}, ++ {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, ++ {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, ++ {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, ++ {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff}, ++ {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, ++ {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, ++ {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, ++ {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff}, ++ {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, ++ {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, ++ {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, ++ {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff}, ++ {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, ++ ++ {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, ++ {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, ++ {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, ++ {"ccode", 0x00000700, SRFL_CCODE, SROM8_CCODE, 0xffff}, ++ {"macaddr", 0x00000700, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, ++ {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, ++ {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, ++ {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, ++ {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, ++ {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, ++ {"leddc", 0x00000700, SRFL_NOFFS|SRFL_LEDDC, SROM8_LEDDC, 0xffff}, ++ {"leddc", 0x000000e0, SRFL_NOFFS|SRFL_LEDDC, SROM5_LEDDC, 0xffff}, ++ {"leddc", 0x00000010, SRFL_NOFFS|SRFL_LEDDC, SROM4_LEDDC, 0xffff}, ++ {"leddc", 0x00000008, SRFL_NOFFS|SRFL_LEDDC, SROM3_LEDDC, 0xffff}, ++ ++ {"tempthresh", 0x00000700, 0, SROM8_THERMAL, 0xff00}, ++ {"tempoffset", 0x00000700, 0, SROM8_THERMAL, 0x00ff}, ++ {"rawtempsense", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff}, ++ {"measpower", 0x00000700, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00}, ++ {"tempsense_slope", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff}, ++ {"tempcorrx", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00}, ++ {"tempsense_option", 0x00000700, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300}, ++ {"freqoffset_corr", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f}, ++ {"iqcal_swp_dis", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010}, ++ {"hw_iqcal_en", 0x00000700, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020}, ++ {"elna2g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0x00ff}, ++ {"elna5g", 0x00000700, 0, SROM8_EXTLNAGAIN, 0xff00}, ++ {"phycal_tempdelta", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff}, ++ {"temps_period", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0x0f00}, ++ {"temps_hysteresis", 0x00000700, 0, SROM8_PHYCAL_TEMPDELTA, 0xf000}, ++ {"measpower1", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x007f}, ++ {"measpower2", 0x00000700, SRFL_PRHEX, SROM8_MPWR_1_AND_2, 0x3f80}, ++ ++ {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, ++ {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, ++ {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, ++ {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, ++ {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, ++ {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, ++ {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, ++ {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, ++ {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, ++ {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, ++ {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, ++ {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, ++ {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, ++ {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, ++ {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, ++ {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, ++ {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, ++ {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, ++ {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, ++ {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, ++ {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, ++ {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, ++ {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, ++ {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, ++ {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, ++ {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, ++ {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, ++ {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, ++ {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, ++ {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, ++ {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, ++ {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, ++ {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, ++ {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, ++ {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, ++ {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, ++ {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, ++ {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, ++ {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, ++ {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, ++ {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, ++ {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, ++ {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, ++ {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, ++ {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, ++ {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, ++ {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, ++ {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, ++ {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, ++ {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, ++ {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, ++ {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, ++ {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, ++ {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, ++ {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, ++ {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, ++ {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, ++ {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, ++ {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, ++ {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, ++ {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, ++ {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, ++ {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, ++ {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, ++ {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, ++ {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, ++ {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, ++ {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, ++ {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, ++ {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, ++ {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, ++ {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, ++ {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, ++ {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, ++ {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, ++ {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, ++ {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, ++ {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, ++ {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, ++ {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff}, ++ {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff}, ++ {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff}, ++ {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, ++ ++ /* power per rate from sromrev 9 */ ++ {"cckbw202gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20, 0xffff}, ++ {"cckbw20ul2gpo", 0x00000600, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, ++ {"legofdmbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, ++ {"legofdmbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, ++ {"legofdmbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, ++ {"mcsbw202gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul2gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw402gpo", 0x00000600, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405glpo", 0x00000600, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405gmpo", 0x00000600, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, ++ {"mcsbw205ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, ++ {"mcsbw20ul5ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, ++ {"mcsbw405ghpo", 0x00000600, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff}, ++ {"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, ++ {"mcs32po", 0x00000600, 0, SROM9_PO_MCS32, 0xffff}, ++ {"legofdm40duppo", 0x00000600, 0, SROM9_PO_LOFDM40DUP, 0xffff}, ++ {"pcieingress_war", 0x00000700, 0, SROM8_PCIEINGRESS_WAR, 0xf}, ++ {"rxgainerr2ga0", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x003f}, ++ {"rxgainerr2ga1", 0x00000700, 0, SROM8_RXGAINERR_2G, 0x07c0}, ++ {"rxgainerr2ga2", 0x00000700, 0, SROM8_RXGAINERR_2G, 0xf800}, ++ {"rxgainerr5gla0", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x003f}, ++ {"rxgainerr5gla1", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0x07c0}, ++ {"rxgainerr5gla2", 0x00000700, 0, SROM8_RXGAINERR_5GL, 0xf800}, ++ {"rxgainerr5gma0", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x003f}, ++ {"rxgainerr5gma1", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0x07c0}, ++ {"rxgainerr5gma2", 0x00000700, 0, SROM8_RXGAINERR_5GM, 0xf800}, ++ {"rxgainerr5gha0", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x003f}, ++ {"rxgainerr5gha1", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0x07c0}, ++ {"rxgainerr5gha2", 0x00000700, 0, SROM8_RXGAINERR_5GH, 0xf800}, ++ {"rxgainerr5gua0", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x003f}, ++ {"rxgainerr5gua1", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0x07c0}, ++ {"rxgainerr5gua2", 0x00000700, 0, SROM8_RXGAINERR_5GU, 0xf800}, ++ {"sar2g", 0x00000600, 0, SROM9_SAR, 0x00ff}, ++ {"sar5g", 0x00000600, 0, SROM9_SAR, 0xff00}, ++ {"noiselvl2ga0", 0x00000700, 0, SROM8_NOISELVL_2G, 0x001f}, ++ {"noiselvl2ga1", 0x00000700, 0, SROM8_NOISELVL_2G, 0x03e0}, ++ {"noiselvl2ga2", 0x00000700, 0, SROM8_NOISELVL_2G, 0x7c00}, ++ {"noiselvl5gla0", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x001f}, ++ {"noiselvl5gla1", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x03e0}, ++ {"noiselvl5gla2", 0x00000700, 0, SROM8_NOISELVL_5GL, 0x7c00}, ++ {"noiselvl5gma0", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x001f}, ++ {"noiselvl5gma1", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x03e0}, ++ {"noiselvl5gma2", 0x00000700, 0, SROM8_NOISELVL_5GM, 0x7c00}, ++ {"noiselvl5gha0", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x001f}, ++ {"noiselvl5gha1", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x03e0}, ++ {"noiselvl5gha2", 0x00000700, 0, SROM8_NOISELVL_5GH, 0x7c00}, ++ {"noiselvl5gua0", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x001f}, ++ {"noiselvl5gua1", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x03e0}, ++ {"noiselvl5gua2", 0x00000700, 0, SROM8_NOISELVL_5GU, 0x7c00}, ++ {"subband5gver", 0x00000700, 0, SROM8_SUBBAND_PPR, 0x7}, ++ ++ {"cckPwrOffset", 0x00000400, 0, SROM10_CCKPWROFFSET, 0xffff}, ++ /* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */ ++ {"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 1, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 3, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 5, 0xffff}, ++ {"", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6, 0xffff}, ++ {"", 0x00000400, SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 7, 0xffff}, ++ {"", 0x00000400, SRFL_PRHEX, SROM10_SWCTRLMAP_2G + 8, 0xffff}, ++ ++ /* sromrev 11 */ ++ {"boardflags3", 0xfffff800, SRFL_PRHEX|SRFL_MORE, SROM11_BFL3, 0xffff}, ++ {"", 0, 0, SROM11_BFL3, 0xffff}, ++ {"boardnum", 0xfffff800, 0, SROM11_MACLO, 0xffff}, ++ {"macaddr", 0xfffff800, SRFL_ETHADDR, SROM11_MACHI, 0xffff}, ++ {"ccode", 0xfffff800, SRFL_CCODE, SROM11_CCODE, 0xffff}, ++ {"regrev", 0xfffff800, 0, SROM11_REGREV, 0x00ff}, ++ {"ledbh0", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0x00ff}, ++ {"ledbh1", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH10, 0xff00}, ++ {"ledbh2", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0x00ff}, ++ {"ledbh3", 0xfffff800, SRFL_NOFFS, SROM11_LEDBH32, 0xff00}, ++ {"leddc", 0xfffff800, SRFL_NOFFS|SRFL_LEDDC, SROM11_LEDDC, 0xffff}, ++ {"aa2g", 0xfffff800, 0, SROM11_AA, 0x00ff}, ++ {"aa5g", 0xfffff800, 0, SROM11_AA, 0xff00}, ++ {"agbg0", 0xfffff800, 0, SROM11_AGBG10, 0x00ff}, ++ {"agbg1", 0xfffff800, 0, SROM11_AGBG10, 0xff00}, ++ {"agbg2", 0xfffff800, 0, SROM11_AGBG2A0, 0x00ff}, ++ {"aga0", 0xfffff800, 0, SROM11_AGBG2A0, 0xff00}, ++ {"aga1", 0xfffff800, 0, SROM11_AGA21, 0x00ff}, ++ {"aga2", 0xfffff800, 0, SROM11_AGA21, 0xff00}, ++ {"txchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_TXCHAIN_MASK}, ++ {"rxchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_RXCHAIN_MASK}, ++ {"antswitch", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_SWITCH_MASK}, ++ ++ {"tssiposslope2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0001}, ++ {"epagain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x000e}, ++ {"pdgain2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x01f0}, ++ {"tworangetssi2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0200}, ++ {"papdcap2g", 0xfffff800, 0, SROM11_FEM_CFG1, 0x0400}, ++ {"femctrl", 0xfffff800, 0, SROM11_FEM_CFG1, 0xf800}, ++ ++ {"tssiposslope5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0001}, ++ {"epagain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x000e}, ++ {"pdgain5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x01f0}, ++ {"tworangetssi5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0200}, ++ {"papdcap5g", 0xfffff800, 0, SROM11_FEM_CFG2, 0x0400}, ++ {"gainctrlsph", 0xfffff800, 0, SROM11_FEM_CFG2, 0xf800}, ++ ++ {"tempthresh", 0xfffff800, 0, SROM11_THERMAL, 0xff00}, ++ {"tempoffset", 0xfffff800, 0, SROM11_THERMAL, 0x00ff}, ++ {"rawtempsense", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0x01ff}, ++ {"measpower", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_RAWTS, 0xfe00}, ++ {"tempsense_slope", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x00ff}, ++ {"tempcorrx", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0xfc00}, ++ {"tempsense_option", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x0300}, ++ {"phycal_tempdelta", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x00ff}, ++ {"temps_period", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x0f00}, ++ {"temps_hysteresis", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0xf000}, ++ {"measpower1", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x007f}, ++ {"measpower2", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x3f80}, ++ {"pdoffset40ma0", 0xfffff800, 0, SROM11_PDOFF_40M_A0, 0xffff}, ++ {"pdoffset40ma1", 0xfffff800, 0, SROM11_PDOFF_40M_A1, 0xffff}, ++ {"pdoffset40ma2", 0xfffff800, 0, SROM11_PDOFF_40M_A2, 0xffff}, ++ {"pdoffset80ma0", 0xfffff800, 0, SROM11_PDOFF_80M_A0, 0xffff}, ++ {"pdoffset80ma1", 0xfffff800, 0, SROM11_PDOFF_80M_A1, 0xffff}, ++ {"pdoffset80ma2", 0xfffff800, 0, SROM11_PDOFF_80M_A2, 0xffff}, ++ ++ {"subband5gver", 0xfffff800, SRFL_PRHEX, SROM11_SUBBAND5GVER, 0xffff}, ++ ++ /* power per rate */ ++ {"cckbw202gpo", 0xfffff800, 0, SROM11_CCKBW202GPO, 0xffff}, ++ {"cckbw20ul2gpo", 0xfffff800, 0, SROM11_CCKBW20UL2GPO, 0xffff}, ++ {"mcsbw202gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW202GPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW202GPO_1, 0xffff}, ++ {"mcsbw402gpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW402GPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW402GPO_1, 0xffff}, ++ {"dot11agofdmhrbw202gpo", 0xfffff800, 0, SROM11_DOT11AGOFDMHRBW202GPO, 0xffff}, ++ {"ofdmlrbw202gpo", 0xfffff800, 0, SROM11_OFDMLRBW202GPO, 0xffff}, ++ {"mcsbw205glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GLPO_1, 0xffff}, ++ {"mcsbw405glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GLPO_1, 0xffff}, ++ {"mcsbw805glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GLPO_1, 0xffff}, ++ {"mcsbw1605glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GLPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GLPO_1, 0xffff}, ++ {"mcsbw205gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GMPO_1, 0xffff}, ++ {"mcsbw405gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GMPO_1, 0xffff}, ++ {"mcsbw805gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GMPO_1, 0xffff}, ++ {"mcsbw1605gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GMPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GMPO_1, 0xffff}, ++ {"mcsbw205ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW205GHPO_1, 0xffff}, ++ {"mcsbw405ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW405GHPO_1, 0xffff}, ++ {"mcsbw805ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW805GHPO_1, 0xffff}, ++ {"mcsbw1605ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GHPO, 0xffff}, ++ {"", 0xfffff800, 0, SROM11_MCSBW1605GHPO_1, 0xffff}, ++ {"mcslr5glpo", 0xfffff800, 0, SROM11_MCSLR5GLPO, 0xffff}, ++ {"mcslr5gmpo", 0xfffff800, 0, SROM11_MCSLR5GMPO, 0xffff}, ++ {"mcslr5ghpo", 0xfffff800, 0, SROM11_MCSLR5GHPO, 0xffff}, ++ {"sb20in40hrrpo", 0xfffff800, 0, SROM11_SB20IN40HRPO, 0xffff}, ++ {"sb20in80and160hr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GLPO, 0xffff}, ++ {"sb40and80hr5glpo", 0xfffff800, 0, SROM11_SB40AND80HR5GLPO, 0xffff}, ++ {"sb20in80and160hr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GMPO, 0xffff}, ++ {"sb40and80hr5gmpo", 0xfffff800, 0, SROM11_SB40AND80HR5GMPO, 0xffff}, ++ {"sb20in80and160hr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GHPO, 0xffff}, ++ {"sb40and80hr5ghpo", 0xfffff800, 0, SROM11_SB40AND80HR5GHPO, 0xffff}, ++ {"sb20in40lrpo", 0xfffff800, 0, SROM11_SB20IN40LRPO, 0xffff}, ++ {"sb20in80and160lr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GLPO, 0xffff}, ++ {"sb40and80lr5glpo", 0xfffff800, 0, SROM11_SB40AND80LR5GLPO, 0xffff}, ++ {"sb20in80and160lr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GMPO, 0xffff}, ++ {"sb40and80lr5gmpo", 0xfffff800, 0, SROM11_SB40AND80LR5GMPO, 0xffff}, ++ {"sb20in80and160lr5ghpo", 0xfffff800, 0, SROM11_SB20IN80AND160LR5GHPO, 0xffff}, ++ {"sb40and80lr5ghpo", 0xfffff800, 0, SROM11_SB40AND80LR5GHPO, 0xffff}, ++ {"dot11agduphrpo", 0xfffff800, 0, SROM11_DOT11AGDUPHRPO, 0xffff}, ++ {"dot11agduplrpo", 0xfffff800, 0, SROM11_DOT11AGDUPLRPO, 0xffff}, ++ ++ /* Misc */ ++ {"pcieingress_war", 0xfffff800, 0, SROM11_PCIEINGRESS_WAR, 0xf}, ++ {"sar2g", 0xfffff800, 0, SROM11_SAR, 0x00ff}, ++ {"sar5g", 0xfffff800, 0, SROM11_SAR, 0xff00}, ++ {"noiselvl2ga0", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x001f}, ++ {"noiselvl2ga1", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x03e0}, ++ {"noiselvl2ga2", 0xfffff800, 0, SROM11_NOISELVL_2G, 0x7c00}, ++ {"noiselvl5gla0", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x001f}, ++ {"noiselvl5gla1", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x03e0}, ++ {"noiselvl5gla2", 0xfffff800, 0, SROM11_NOISELVL_5GL, 0x7c00}, ++ {"noiselvl5gma0", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x001f}, ++ {"noiselvl5gma1", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x03e0}, ++ {"noiselvl5gma2", 0xfffff800, 0, SROM11_NOISELVL_5GM, 0x7c00}, ++ {"noiselvl5gha0", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x001f}, ++ {"noiselvl5gha1", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x03e0}, ++ {"noiselvl5gha2", 0xfffff800, 0, SROM11_NOISELVL_5GH, 0x7c00}, ++ {"noiselvl5gua0", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x001f}, ++ {"noiselvl5gua1", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x03e0}, ++ {"noiselvl5gua2", 0xfffff800, 0, SROM11_NOISELVL_5GU, 0x7c00}, ++ {"rxgainerr2g", 0xfffff800, SRFL_PRHEX, SROM11_RXGAINERR_2G, 0xffff}, ++ {"rxgainerr5g", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GL, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX|SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_RXGAINERR_5GU, 0xffff}, ++ {NULL, 0, 0, 0, 0} ++}; ++ ++static const sromvar_t perpath_pci_sromvars[] = { ++ {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, ++ {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, ++ {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, ++ {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, ++ {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, ++ {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, ++ {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, ++ {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, ++ {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, ++ {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, ++ {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, ++ {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, ++ {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, ++ {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, ++ {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, ++ {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff}, ++ {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff}, ++ {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff}, ++ {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, ++ {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff}, ++ {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff}, ++ {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff}, ++ {"maxp2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0x00ff}, ++ {"itt2ga", 0x00000700, 0, SROM8_2G_ITT_MAXP, 0xff00}, ++ {"itt5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0xff00}, ++ {"pa2gw0a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, ++ {"pa2gw1a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, ++ {"pa2gw2a", 0x00000700, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, ++ {"maxp5ga", 0x00000700, 0, SROM8_5G_ITT_MAXP, 0x00ff}, ++ {"maxp5gha", 0x00000700, 0, SROM8_5GLH_MAXP, 0x00ff}, ++ {"maxp5gla", 0x00000700, 0, SROM8_5GLH_MAXP, 0xff00}, ++ {"pa5gw0a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, ++ {"pa5gw1a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, ++ {"pa5gw2a", 0x00000700, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, ++ {"pa5glw0a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, ++ {"pa5glw1a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff}, ++ {"pa5glw2a", 0x00000700, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff}, ++ {"pa5ghw0a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, ++ {"pa5ghw1a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff}, ++ {"pa5ghw2a", 0x00000700, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff}, ++ ++ /* sromrev 11 */ ++ {"maxp2ga", 0xfffff800, 0, SROM11_2G_MAXP, 0x00ff}, ++ {"pa2ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_2G_PA + 2, 0xffff}, ++ {"rxgains5gmelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0007}, ++ {"rxgains5gmtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0078}, ++ {"rxgains5gmtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x0080}, ++ {"rxgains5ghelnagaina", 0xfffff800, 0, SROM11_RXGAINS1, 0x0700}, ++ {"rxgains5ghtrisoa", 0xfffff800, 0, SROM11_RXGAINS1, 0x7800}, ++ {"rxgains5ghtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS1, 0x8000}, ++ {"rxgains2gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0007}, ++ {"rxgains2gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x0078}, ++ {"rxgains2gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x0080}, ++ {"rxgains5gelnagaina", 0xfffff800, 0, SROM11_RXGAINS, 0x0700}, ++ {"rxgains5gtrisoa", 0xfffff800, 0, SROM11_RXGAINS, 0x7800}, ++ {"rxgains5gtrelnabypa", 0xfffff800, 0, SROM11_RXGAINS, 0x8000}, ++ {"maxp5ga", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0x00ff}, ++ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB1B0_MAXP, 0xff00}, ++ {"", 0xfffff800, SRFL_ARRAY, SROM11_5GB3B2_MAXP, 0x00ff}, ++ {"", 0xfffff800, 0, SROM11_5GB3B2_MAXP, 0xff00}, ++ {"pa5ga", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1, 0xffff}, ++ {"", 0xfffff800, SRFL_PRHEX, SROM11_5GB3_PA + 2, 0xffff}, ++ ++ {NULL, 0, 0, 0, 0} ++}; ++ ++#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) ++#define PHY_TYPE_HT 7 /* HT-Phy value */ ++#define PHY_TYPE_N 4 /* N-Phy value */ ++#define PHY_TYPE_LP 5 /* LP-Phy value */ ++#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */ ++#if !defined(PHY_TYPE_AC) ++#define PHY_TYPE_AC 11 /* AC-Phy value */ ++#endif /* !defined(PHY_TYPE_AC) */ ++#if !defined(PHY_TYPE_NULL) ++#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ ++#endif /* !defined(PHY_TYPE_NULL) */ ++ ++typedef struct { ++ uint16 phy_type; ++ uint16 bandrange; ++ uint16 chain; ++ const char *vars; ++} pavars_t; ++ ++static const pavars_t pavars[] = { ++ /* HTPHY */ ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G, 2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GL, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GM, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, ++ /* HTPHY PPR_SUBBAND */ ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 0, "pa5gllw0a0 pa5gllw1a0 pa5gllw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 1, "pa5gllw0a1 pa5gllw1a1 pa5gllw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLL_5BAND, 2, "pa5gllw0a2 pa5gllw1a2 pa5gllw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 0, "pa5glhw0a0 pa5glhw1a0 pa5glhw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 1, "pa5glhw0a1 pa5glhw1a1 pa5glhw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GLH_5BAND, 2, "pa5glhw0a2 pa5glhw1a2 pa5glhw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 0, "pa5gmlw0a0 pa5gmlw1a0 pa5gmlw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 1, "pa5gmlw0a1 pa5gmlw1a1 pa5gmlw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GML_5BAND, 2, "pa5gmlw0a2 pa5gmlw1a2 pa5gmlw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 0, "pa5gmhw0a0 pa5gmhw1a0 pa5gmhw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 1, "pa5gmhw0a1 pa5gmhw1a1 pa5gmhw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GMH_5BAND, 2, "pa5gmhw0a2 pa5gmhw1a2 pa5gmhw2a2"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ {PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5GH_5BAND, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"}, ++ /* NPHY */ ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, ++ /* LPPHY */ ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"}, ++ {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"}, ++ /* ACPHY */ ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 0, "pa2ga0"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 1, "pa2ga1"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G, 2, "pa2ga2"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 0, "pa5ga0"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 1, "pa5ga1"}, ++ {PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND, 2, "pa5ga2"}, ++ {PHY_TYPE_NULL, 0, 0, ""} ++}; ++ ++typedef struct { ++ uint16 phy_type; ++ uint16 bandrange; ++ const char *vars; ++} povars_t; ++ ++static const povars_t povars[] = { ++ /* NPHY */ ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 " ++ "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 " ++ "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 " ++ "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"}, ++ {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 " ++ "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"}, ++ {PHY_TYPE_NULL, 0, ""} ++}; ++ ++typedef struct { ++ uint8 tag; /* Broadcom subtag name */ ++ uint32 revmask; /* Supported cis_sromrev */ ++ uint8 len; /* Length field of the tuple, note that it includes the ++ * subtag name (1 byte): 1 + tuple content length ++ */ ++ const char *params; ++} cis_tuple_t; ++ ++#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */ ++#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */ ++#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */ ++#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */ ++ ++static const cis_tuple_t cis_hnbuvars[] = { ++ {OTP_RAW1, 0xffffffff, 0, ""}, /* special case */ ++ {OTP_VERS_1, 0xffffffff, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */ ++ {OTP_MANFID, 0xffffffff, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */ ++ /* Unified OTP: tupple to embed USB manfid inside SDIO CIS */ ++ {HNBU_UMANFID, 0xffffffff, 8, "8usbmanfid"}, ++ {HNBU_SROMREV, 0xffffffff, 2, "1sromrev"}, ++ /* NOTE: subdevid is also written to boardtype. ++ * Need to write HNBU_BOARDTYPE to change it if it is different. ++ */ ++ {HNBU_CHIPID, 0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"}, ++ {HNBU_BOARDREV, 0xffffffff, 3, "2boardrev"}, ++ {HNBU_PAPARMS, 0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"}, ++ {HNBU_AA, 0xffffffff, 3, "1aa2g 1aa5g"}, ++ {HNBU_AA, 0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */ ++ {HNBU_AG, 0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"}, ++ {HNBU_BOARDFLAGS, 0xffffffff, 13, "4boardflags 4boardflags2 4boardflags3"}, ++ {HNBU_LEDS, 0xffffffff, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"}, ++ {HNBU_CCODE, 0xffffffff, 4, "2ccode 1cctl"}, ++ {HNBU_CCKPO, 0xffffffff, 3, "2cckpo"}, ++ {HNBU_OFDMPO, 0xffffffff, 5, "4ofdmpo"}, ++ {HNBU_PAPARMS5G, 0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 " ++ "2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit " ++ "1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"}, ++ {HNBU_RDLID, 0xffffffff, 3, "2rdlid"}, ++ {HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g " ++ "0rssisav2g 0bxa2g"}, /* special case */ ++ {HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g " ++ "0rssisav5g 0bxa5g"}, /* special case */ ++ {HNBU_XTALFREQ, 0xffffffff, 5, "4xtalfreq"}, ++ {HNBU_TRI2G, 0xffffffff, 2, "1tri2g"}, ++ {HNBU_TRI5G, 0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"}, ++ {HNBU_RXPO2G, 0xffffffff, 2, "1rxpo2g"}, ++ {HNBU_RXPO5G, 0xffffffff, 2, "1rxpo5g"}, ++ {HNBU_BOARDNUM, 0xffffffff, 3, "2boardnum"}, ++ {HNBU_MACADDR, 0xffffffff, 7, "6macaddr"}, /* special case */ ++ {HNBU_RDLSN, 0xffffffff, 3, "2rdlsn"}, ++ {HNBU_BOARDTYPE, 0xffffffff, 3, "2boardtype"}, ++ {HNBU_LEDDC, 0xffffffff, 3, "2leddc"}, ++ {HNBU_RDLRNDIS, 0xffffffff, 2, "1rdlndis"}, ++ {HNBU_CHAINSWITCH, 0xffffffff, 5, "1txchain 1rxchain 2antswitch"}, ++ {HNBU_REGREV, 0xffffffff, 2, "1regrev"}, ++ {HNBU_FEM, 0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g " ++ "0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */ ++ {HNBU_PAPARMS_C0, 0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 " ++ "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 " ++ "2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"}, ++ {HNBU_PAPARMS_C1, 0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 " ++ "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 " ++ "2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"}, ++ {HNBU_PO_CCKOFDM, 0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo " ++ "4ofdm5ghpo"}, ++ {HNBU_PO_MCS2G, 0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 " ++ "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"}, ++ {HNBU_PO_MCS5GM, 0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 " ++ "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"}, ++ {HNBU_PO_MCS5GLH, 0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 " ++ "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 " ++ "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 " ++ "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"}, ++ {HNBU_CCKFILTTYPE, 0xffffffff, 2, "1cckdigfilttype"}, ++ {HNBU_PO_CDD, 0xffffffff, 3, "2cddpo"}, ++ {HNBU_PO_STBC, 0xffffffff, 3, "2stbcpo"}, ++ {HNBU_PO_40M, 0xffffffff, 3, "2bw40po"}, ++ {HNBU_PO_40MDUP, 0xffffffff, 3, "2bwduppo"}, ++ {HNBU_RDLRWU, 0xffffffff, 2, "1rdlrwu"}, ++ {HNBU_WPS, 0xffffffff, 3, "1wpsgpio 1wpsled"}, ++ {HNBU_USBFS, 0xffffffff, 2, "1usbfs"}, ++ {HNBU_ELNA2G, 0xffffffff, 2, "1elna2g"}, ++ {HNBU_ELNA5G, 0xffffffff, 2, "1elna5g"}, ++ {HNBU_CUSTOM1, 0xffffffff, 5, "4customvar1"}, ++ {OTP_RAW, 0xffffffff, 0, ""}, /* special case */ ++ {HNBU_OFDMPO5G, 0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"}, ++ {HNBU_USBEPNUM, 0xffffffff, 3, "2usbepnum"}, ++ {HNBU_CCKBW202GPO, 0xffffffff, 5, "2cckbw202gpo 2cckbw20ul2gpo"}, ++ {HNBU_LEGOFDMBW202GPO, 0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gp"}, ++ {HNBU_LEGOFDMBW205GPO, 0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo " ++ "4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"}, ++ {HNBU_MCS2GPO, 0xffffffff, 13, "4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo"}, ++ {HNBU_MCS5GLPO, 0xffffffff, 13, "4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"}, ++ {HNBU_MCS5GMPO, 0xffffffff, 13, "4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"}, ++ {HNBU_MCS5GHPO, 0xffffffff, 13, "4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"}, ++ {HNBU_MCS32PO, 0xffffffff, 3, "2mcs32po"}, ++ {HNBU_LEG40DUPPO, 0xffffffff, 3, "2legofdm40duppo"}, ++ {HNBU_TEMPTHRESH, 0xffffffff, 6, "1tempthresh 1periodhyst 1tempoffset 1tempcoropt " ++ "1phycal_tempdelta"}, ++ {HNBU_FEM_CFG, 0xfffff800, 5, "2fem_cfg1 2fem_cfg2"}, ++ {HNBU_ACPA_C0, 0xfffff800, 41, "2subband5gver 2maxp2ga0 2*3pa2ga0 2rxgainsa0 " ++ "1*4maxp5ga0 2*12pa5ga0"}, ++ {HNBU_ACPA_C1, 0xfffff800, 39, "2maxp2ga1 2*3pa2ga1 2rxgainsa1 1*4maxp5ga1 " ++ "2*12pa5ga1"}, ++ {HNBU_ACPA_C2, 0xfffff800, 39, "2maxp2ga2 2*3pa2ga2 2rxgainsa2 1*4maxp5ga2 " ++ "2*12pa5ga2"}, ++ {HNBU_MEAS_PWR, 0xfffff800, 5, "1measpower 1measpower1 1measpower2 2rawtempsense"}, ++ {HNBU_PDOFF, 0xfffff800, 13, "2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 " ++ "2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"}, ++ {HNBU_ACPPR_2GPO, 0xfffff800, 5, "2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo"}, ++ {HNBU_ACPPR_5GPO, 0xfffff800, 31, "4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo " ++ "4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5rlpo 2mcslr5gmpo 2mcslr5ghpo"}, ++ {HNBU_ACPPR_SBPO, 0xfffff800, 33, "2sb20in40hrrpo 2sb20in80and160hr5glpo " ++ "2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo " ++ "2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo " ++ "2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo " ++ "2dot11agduphrpo 2dot11agduplrpo"}, ++ {HNBU_NOISELVL, 0xfffff800, 11, "2noiselvl2g 2noiselvl5gl 2noiselvl5gm " ++ "2noiselvl5gh 2noiselvl5gu"}, ++ {HNBU_RXGAIN_ERR, 0xfffff800, 11, "2rxgainerr2g 2*4rxgainerr5g"}, ++ {HNBU_AGBGA, 0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"}, ++ {HNBU_UUID, 0xffffffff, 17, "16uuid"}, ++ {0xFF, 0xffffffff, 0, ""} ++}; ++ ++#endif /* _bcmsrom_tbl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h b/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h +new file mode 100755 +index 0000000..de1686f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmstdlib.h +@@ -0,0 +1,128 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * prototypes for functions defined in bcmstdlib.c ++ * ++ * $Id: bcmstdlib.h 289936 2011-10-14 21:06:33Z $: ++ */ ++ ++/* ++ * bcmstdlib.h file should be used only to construct an OSL or alone without any OSL ++ * It should not be used with any orbitarary OSL's as there could be a conflict ++ * with some of the routines defined here. ++*/ ++ ++#ifndef _BCMSTDLIB_H ++#define _BCMSTDLIB_H ++ ++#include ++#include ++#include ++ ++#ifndef INT_MAX ++#define INT_MAX 2147483647 /* from limits.h */ ++#endif ++ ++ ++/* For backwards compatibility, define "BWL_NO_INTERNAL_STDLIB_SUPPORT" to ++ * exclude support for the BRCM stdlib APIs. This should be cleaned-up such ++ * that platforms that require the BRCM stdlib API should simply define ++ * "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate the need for the ++ * following #ifndef check. ++ */ ++#ifndef BWL_NO_INTERNAL_STDLIB_SUPPORT ++#define BWL_INTERNAL_STDLIB_SUPPORT ++#endif ++ ++#ifdef BWL_INTERNAL_STDLIB_SUPPORT ++/* This should be cleaned-up such that platforms that require the BRCM stdlib ++ * API should simply define "BWL_INTERNAL_STDLIB_SUPPORT". This would eliminate ++ * the need for the following #ifdef check. ++ */ ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(EFI) ++ ++typedef int FILE; ++#define stdout ((FILE *)1) ++#define stderr ((FILE *)2) ++ ++/* i/o functions */ ++extern int fputc(int c, FILE *stream); ++extern void putc(int c); ++/* extern int putc(int c, FILE *stream); */ ++#define putchar(c) putc(c) ++extern int fputs(const char *s, FILE *stream); ++extern int puts(const char *s); ++extern int getc(void); ++extern bool keypressed(void); ++ ++/* bcopy, bcmp, and bzero */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++extern unsigned long rand(void); ++ ++#define atoi(s) ((int)(strtoul((s), NULL, 10))) ++ ++#endif ++ ++#if !defined(_WIN32) || defined(EFI) ++/* string functions */ ++#define PRINTF_BUFLEN 512 ++extern int printf(const char *fmt, ...) ++ __attribute__ ((format (__printf__, 1, 2))); ++extern int BCMROMFN(sprintf)(char *buf, const char *fmt, ...) ++ __attribute__ ((format (__printf__, 2, 3))); ++ ++extern int BCMROMFN(strcmp)(const char *s1, const char *s2); ++extern size_t BCMROMFN(strlen)(const char *s); ++extern char *BCMROMFN(strcpy)(char *dest, const char *src); ++extern char *BCMROMFN(strstr)(const char *s, const char *find); ++extern char *BCMROMFN(strncpy)(char *dest, const char *src, size_t n); ++extern char *BCMROMFN(strcat)(char *d, const char *s); ++ ++extern int BCMROMFN(strncmp)(const char *s1, const char *s2, size_t n); ++extern char *BCMROMFN(strchr)(const char *str, int c); ++extern char *BCMROMFN(strrchr)(const char *str, int c); ++extern size_t BCMROMFN(strspn)(const char *s1, const char *s2); ++extern size_t BCMROMFN(strcspn)(const char *s1, const char *s2); ++extern unsigned long BCMROMFN(strtoul)(const char *cp, char **endp, int base); ++#define strtol(nptr, endptr, base) ((long)strtoul((nptr), (endptr), (base))) ++ ++extern void *BCMROMFN(memmove)(void *dest, const void *src, size_t n); ++extern void *BCMROMFN(memchr)(const void *s, int c, size_t n); ++ ++extern int BCMROMFN(vsprintf)(char *buf, const char *fmt, va_list ap); ++/* mem functions */ ++/* For EFI, using EFIDriverLib versions */ ++/* Cannot use memmem in ROM because of character array initialization wiht "" in gcc */ ++extern void *memset(void *dest, int c, size_t n); ++/* Cannot use memcpy in ROM because of structure assignmnets in gcc */ ++extern void *memcpy(void *dest, const void *src, size_t n); ++extern int BCMROMFN(memcmp)(const void *s1, const void *s2, size_t n); ++ ++#endif /* !_WIN32 || EFI */ ++#endif /* BWL_INTERNAL_STDLIB_SUPPORT */ ++ ++#if !defined(_WIN32) || defined(EFI) ++extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...) ++ __attribute__ ((format (__printf__, 3, 4))); ++#else ++extern int BCMROMFN(snprintf)(char *str, size_t n, char const *fmt, ...); ++#endif ++ ++extern int BCMROMFN(vsnprintf)(char *buf, size_t size, const char *fmt, va_list ap); ++ ++#endif /* _BCMSTDLIB_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmutils.h b/drivers/bcmdrivers/gmac/src/include/bcmutils.h +new file mode 100755 +index 0000000..ac00a91 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmutils.h +@@ -0,0 +1,864 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc useful os-independent macros and functions. ++ * ++ * $Id: bcmutils.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _bcmutils_h_ ++#define _bcmutils_h_ ++ ++#if defined(UNDER_CE) ++#include ++#else ++#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src)) ++#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) ++#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src)) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef PKTQ_LOG ++#include ++#endif ++ ++/* ctype replacement */ ++#define _BCM_U 0x01 /* upper */ ++#define _BCM_L 0x02 /* lower */ ++#define _BCM_D 0x04 /* digit */ ++#define _BCM_C 0x08 /* cntrl */ ++#define _BCM_P 0x10 /* punct */ ++#define _BCM_S 0x20 /* white space (space/lf/tab) */ ++#define _BCM_X 0x40 /* hex digit */ ++#define _BCM_SP 0x80 /* hard space (0x20) */ ++ ++#if defined(BCMROMBUILD) ++extern const unsigned char BCMROMDATA(bcm_ctype)[]; ++#else ++extern const unsigned char bcm_ctype[]; ++#endif ++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) ++ ++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) ++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) ++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) ++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) ++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) ++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) ++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) ++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) ++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) ++#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) ++#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) ++ ++/* Buffer structure for collecting string-formatted data ++* using bcm_bprintf() API. ++* Use bcm_binit() to initialize before use ++*/ ++ ++struct bcmstrbuf { ++ char *buf; /* pointer to current position in origbuf */ ++ unsigned int size; /* current (residual) size in bytes */ ++ char *origbuf; /* unmodified pointer to orignal buffer */ ++ unsigned int origsize; /* unmodified orignal buffer size in bytes */ ++}; ++ ++/* ** driver-only section ** */ ++#ifdef BCMDRIVER ++#ifdef EFI ++/* forward declare structyre type */ ++struct spktq; ++#endif ++#include ++ ++#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ ++ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++} ++ ++/* osl multi-precedence packet queue */ ++#ifndef PKTQ_LEN_DEFAULT ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#endif ++#ifndef PKTQ_MAX_PREC ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ ++#endif ++ ++typedef struct pktq_prec { ++ void *head; /* first packet to dequeue */ ++ void *tail; /* last packet to dequeue */ ++ uint16 len; /* number of queued packets */ ++ uint16 max; /* maximum number of queued packets */ ++} pktq_prec_t; ++ ++#ifdef PKTQ_LOG ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_counters_t; ++#endif /* PKTQ_LOG */ ++ ++ ++#define PKTQ_COMMON \ ++ uint16 num_prec; /* number of precedences in use */ \ ++ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \ ++ uint16 max; /* total max packets */ \ ++ uint16 len; /* total number of packets */ ++ ++/* multi-priority pkt queue */ ++struct pktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[PKTQ_MAX_PREC]; ++#ifdef PKTQ_LOG ++ pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ ++#endif ++}; ++ ++/* simple, non-priority pkt queue */ ++struct spktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[1]; ++}; ++ ++#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) ++ ++/* fn(pkt, arg). return true if pkt belongs to if */ ++typedef bool (*ifpkt_cb_t)(void*, int); ++ ++#ifdef BCMPKTPOOL ++#define POOL_ENAB(pool) ((pool) && (pool)->inited) ++#if defined(BCM4329C0) ++#define SHARED_POOL (pktpool_shared_ptr) ++#else ++#define SHARED_POOL (pktpool_shared) ++#endif /* BCM4329C0 */ ++#else /* BCMPKTPOOL */ ++#define POOL_ENAB(bus) 0 ++#define SHARED_POOL ((struct pktpool *)NULL) ++#endif /* BCMPKTPOOL */ ++ ++#ifndef PKTPOOL_LEN_MAX ++#define PKTPOOL_LEN_MAX 40 ++#endif /* PKTPOOL_LEN_MAX */ ++#define PKTPOOL_CB_MAX 3 ++ ++struct pktpool; ++typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); ++typedef struct { ++ pktpool_cb_t cb; ++ void *arg; ++} pktpool_cbinfo_t; ++ ++#ifdef BCMDBG_POOL ++/* pkt pool debug states */ ++#define POOL_IDLE 0 ++#define POOL_RXFILL 1 ++#define POOL_RXDH 2 ++#define POOL_RXD11 3 ++#define POOL_TXDH 4 ++#define POOL_TXD11 5 ++#define POOL_AMPDU 6 ++#define POOL_TXENQ 7 ++ ++typedef struct { ++ void *p; ++ uint32 cycles; ++ uint32 dur; ++} pktpool_dbg_t; ++ ++typedef struct { ++ uint8 txdh; /* tx to host */ ++ uint8 txd11; /* tx to d11 */ ++ uint8 enq; /* waiting in q */ ++ uint8 rxdh; /* rx from host */ ++ uint8 rxd11; /* rx from d11 */ ++ uint8 rxfill; /* dma_rxfill */ ++ uint8 idle; /* avail in pool */ ++} pktpool_stats_t; ++#endif /* BCMDBG_POOL */ ++ ++typedef struct pktpool { ++ bool inited; ++ uint16 r; ++ uint16 w; ++ uint16 len; ++ uint16 maxlen; ++ uint16 plen; ++ bool istx; ++ bool empty; ++ uint8 cbtoggle; ++ uint8 cbcnt; ++ uint8 ecbcnt; ++ bool emptycb_disable; ++ pktpool_cbinfo_t *availcb_excl; ++ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX]; ++ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; ++ void *q[PKTPOOL_LEN_MAX + 1]; ++ ++#ifdef BCMDBG_POOL ++ uint8 dbg_cbcnt; ++ pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; ++ uint16 dbg_qlen; ++ pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; ++#endif ++} pktpool_t; ++ ++#if defined(BCM4329C0) ++extern pktpool_t *pktpool_shared_ptr; ++#else ++extern pktpool_t *pktpool_shared; ++#endif /* BCM4329C0 */ ++ ++extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx); ++extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); ++extern void* pktpool_get(pktpool_t *pktp); ++extern void pktpool_free(pktpool_t *pktp, void *p); ++extern int pktpool_add(pktpool_t *pktp, void *p); ++extern uint16 pktpool_avail(pktpool_t *pktp); ++extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); ++extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); ++extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); ++extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); ++extern bool pktpool_emptycb_disabled(pktpool_t *pktp); ++ ++#define POOLPTR(pp) ((pktpool_t *)(pp)) ++#define pktpool_len(pp) (POOLPTR(pp)->len - 1) ++#define pktpool_plen(pp) (POOLPTR(pp)->plen) ++#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) ++ ++#ifdef BCMDBG_POOL ++extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_start_trigger(pktpool_t *pktp, void *p); ++extern int pktpool_dbg_dump(pktpool_t *pktp); ++extern int pktpool_dbg_notify(pktpool_t *pktp); ++extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); ++#endif /* BCMDBG_POOL */ ++ ++/* forward definition of ether_addr structure used by some function prototypes */ ++ ++struct ether_addr; ++ ++extern int ether_isbcast(const void *ea); ++extern int ether_isnulladdr(const void *ea); ++ ++/* operations on a specific precedence in packet queue */ ++ ++#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) ++#define pktq_pmax(pq, prec) ((pq)->q[prec].max) ++#define pktq_plen(pq, prec) ((pq)->q[prec].len) ++#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) ++#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) ++#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) ++ ++#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) ++#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) ++ ++extern void *pktq_penq(struct pktq *pq, int prec, void *p); ++extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); ++extern void *pktq_pdeq(struct pktq *pq, int prec); ++extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); ++extern void *pktq_pdeq_tail(struct pktq *pq, int prec); ++/* Empty the queue at particular precedence level */ ++extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ++ ifpkt_cb_t fn, int arg); ++/* Remove a specified packet from its queue */ ++extern bool pktq_pdel(struct pktq *pq, void *p, int prec); ++ ++/* operations on a set of precedences in packet queue */ ++ ++extern int pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); ++extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); ++ ++/* operations on packet queue as a whole */ ++ ++#define pktq_len(pq) ((int)(pq)->len) ++#define pktq_max(pq) ((int)(pq)->max) ++#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) ++#define pktq_full(pq) ((pq)->len >= (pq)->max) ++#define pktq_empty(pq) ((pq)->len == 0) ++ ++/* operations for single precedence queues */ ++#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) ++#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) ++#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) ++#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) ++#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) ++ ++extern void pktq_init(struct pktq *pq, int num_prec, int max_len); ++extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); ++ ++/* prec_out may be NULL if caller is not interested in return value */ ++extern void *pktq_deq(struct pktq *pq, int *prec_out); ++extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); ++extern void *pktq_peek(struct pktq *pq, int *prec_out); ++extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); ++ ++/* externs */ ++/* packet */ ++extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pkttotlen(osl_t *osh, void *p); ++extern void *pktlast(osl_t *osh, void *p); ++extern uint pktsegcnt(osl_t *osh, void *p); ++extern uint pktsegcnt_war(osl_t *osh, void *p); ++extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); ++extern void *pktoffset(osl_t *osh, void *p, uint offset); ++ ++/* Get priority from a packet and pass it back in scb (or equiv) */ ++#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ ++#define PKTPRIO_VLAN 0x200 /* VLAN prio found */ ++#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ ++#define PKTPRIO_DSCP 0x800 /* DSCP prio found */ ++ ++extern uint pktsetprio(void *pkt, bool update_vtag); ++ ++/* string */ ++extern int BCMROMFN(bcm_atoi)(const char *s); ++extern ulong BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base); ++extern char *BCMROMFN(bcmstrstr)(const char *haystack, const char *needle); ++extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src); ++extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size); ++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); ++char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); ++int bcmstricmp(const char *s1, const char *s2); ++int bcmstrnicmp(const char* s1, const char* s2, int cnt); ++ ++ ++/* ethernet address */ ++extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); ++extern int BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea); ++ ++/* ip address */ ++struct ipv4_addr; ++extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); ++ ++/* delay */ ++extern void bcm_mdelay(uint ms); ++/* variable access */ ++#if defined(DONGLEBUILD) && !defined(WLTEST) ++#ifdef BCMDBG ++#define NVRAM_RECLAIM_CHECK(name) \ ++ if (attach_part_reclaimed == TRUE) { \ ++ printf("%s: NVRAM already reclaimed, %s\n", __FUNCTION__, (name)); \ ++ *(char*) 0 = 0; /* TRAP */ \ ++ return NULL; \ ++ } ++#else /* BCMDBG */ ++#define NVRAM_RECLAIM_CHECK(name) \ ++ if (attach_part_reclaimed == TRUE) { \ ++ *(char*) 0 = 0; /* TRAP */ \ ++ return NULL; \ ++ } ++#endif /* BCMDBG */ ++#else /* DONGLEBUILD && !WLTEST && !BCMINTERNAL && !BCMDBG_DUMP */ ++#define NVRAM_RECLAIM_CHECK(name) ++#endif ++ ++extern char *getvar(char *vars, const char *name); ++extern int getintvar(char *vars, const char *name); ++extern int getintvararray(char *vars, const char *name, int index); ++extern int getintvararraysize(char *vars, const char *name); ++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); ++extern int getwanport(void); ++extern int getbrcmtag(void); ++#ifdef BCMDBG ++extern void prpkt(const char *msg, osl_t *osh, void *p0); ++#endif /* BCMDBG */ ++#ifdef BCMPERFSTATS ++extern void bcm_perf_enable(void); ++extern void bcmstats(char *fmt); ++extern void bcmlog(char *fmt, uint a1, uint a2); ++extern void bcmdumplog(char *buf, int size); ++extern int bcmdumplogent(char *buf, uint idx); ++#else ++#define bcm_perf_enable() ++#define bcmstats(fmt) ++#define bcmlog(fmt, a1, a2) ++#define bcmdumplog(buf, size) *buf = '\0' ++#define bcmdumplogent(buf, idx) -1 ++#endif /* BCMPERFSTATS */ ++ ++#if defined(BCMTSTAMPEDLOGS) ++#define TSF_TICKS_PER_MS 1024 ++/* Store a TSF timestamp and a log line in the log buffer */ ++extern void bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2); ++/* Print out the log buffer with timestamps */ ++extern void bcmprinttslogs(void); ++/* Print out a microsecond timestamp as "sec.ms.us " */ ++extern void bcmprinttstamp(uint32 us); ++/* Dump to buffer a microsecond timestamp as "sec.ms.us " */ ++extern void bcmdumptslog(char *buf, int size); ++#else ++#define bcmtslog(tstamp, fmt, a1, a2) ++#define bcmprinttslogs() ++#define bcmprinttstamp(us) ++#define bcmdumptslog(buf, size) ++#endif /* BCMTSTAMPEDLOGS */ ++ ++extern char *bcm_nvram_vars(uint *length); ++extern int bcm_nvram_cache(void *sih); ++ ++/* Support for sharing code across in-driver iovar implementations. ++ * The intent is that a driver use this structure to map iovar names ++ * to its (private) iovar identifiers, and the lookup function to ++ * find the entry. Macros are provided to map ids and get/set actions ++ * into a single number space for a switch statement. ++ */ ++ ++/* iovar structure */ ++typedef struct bcm_iovar { ++ const char *name; /* name for lookup and display */ ++ uint16 varid; /* id for switch */ ++ uint16 flags; /* driver-specific flag bits */ ++ uint16 type; /* base type of argument */ ++ uint16 minlen; /* min length for buffer vars */ ++} bcm_iovar_t; ++ ++/* varid definitions are per-driver, may use these get/set bits */ ++ ++/* IOVar action bits for id mapping */ ++#define IOV_GET 0 /* Get an iovar */ ++#define IOV_SET 1 /* Set an iovar */ ++ ++/* Varid to actionid mapping */ ++#define IOV_GVAL(id) ((id) * 2) ++#define IOV_SVAL(id) ((id) * 2 + IOV_SET) ++#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) ++#define IOV_ID(actionid) (actionid >> 1) ++ ++/* flags are per-driver based on driver attributes */ ++ ++extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); ++extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); ++#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ ++ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); ++#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ ++#endif /* BCMDRIVER */ ++ ++/* Base type definitions */ ++#define IOVT_VOID 0 /* no value (implictly set only) */ ++#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ ++#define IOVT_INT8 2 /* integer values are range-checked */ ++#define IOVT_UINT8 3 /* unsigned int 8 bits */ ++#define IOVT_INT16 4 /* int 16 bits */ ++#define IOVT_UINT16 5 /* unsigned int 16 bits */ ++#define IOVT_INT32 6 /* int 32 bits */ ++#define IOVT_UINT32 7 /* unsigned int 32 bits */ ++#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ ++#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) ++ ++/* Initializer for IOV type strings */ ++#define BCM_IOV_TYPE_INIT { \ ++ "void", \ ++ "bool", \ ++ "int8", \ ++ "uint8", \ ++ "int16", \ ++ "uint16", \ ++ "int32", \ ++ "uint32", \ ++ "buffer", \ ++ "" } ++ ++#define BCM_IOVT_IS_INT(type) (\ ++ (type == IOVT_BOOL) || \ ++ (type == IOVT_INT8) || \ ++ (type == IOVT_UINT8) || \ ++ (type == IOVT_INT16) || \ ++ (type == IOVT_UINT16) || \ ++ (type == IOVT_INT32) || \ ++ (type == IOVT_UINT32)) ++ ++/* ** driver/apps-shared section ** */ ++ ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) ++ ++ ++/* ++ * error codes could be added but the defined ones shouldn't be changed/deleted ++ * these error codes are exposed to the user code ++ * when ever a new error code is added to this list ++ * please update errorstring table with the related error string and ++ * update osl files with os specific errorcode map ++*/ ++ ++#define BCME_OK 0 /* Success */ ++#define BCME_ERROR -1 /* Error generic */ ++#define BCME_BADARG -2 /* Bad Argument */ ++#define BCME_BADOPTION -3 /* Bad option */ ++#define BCME_NOTUP -4 /* Not up */ ++#define BCME_NOTDOWN -5 /* Not down */ ++#define BCME_NOTAP -6 /* Not AP */ ++#define BCME_NOTSTA -7 /* Not STA */ ++#define BCME_BADKEYIDX -8 /* BAD Key Index */ ++#define BCME_RADIOOFF -9 /* Radio Off */ ++#define BCME_NOTBANDLOCKED -10 /* Not band locked */ ++#define BCME_NOCLK -11 /* No Clock */ ++#define BCME_BADRATESET -12 /* BAD Rate valueset */ ++#define BCME_BADBAND -13 /* BAD Band */ ++#define BCME_BUFTOOSHORT -14 /* Buffer too short */ ++#define BCME_BUFTOOLONG -15 /* Buffer too long */ ++#define BCME_BUSY -16 /* Busy */ ++#define BCME_NOTASSOCIATED -17 /* Not Associated */ ++#define BCME_BADSSIDLEN -18 /* Bad SSID len */ ++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ ++#define BCME_BADCHAN -20 /* Bad Channel */ ++#define BCME_BADADDR -21 /* Bad Address */ ++#define BCME_NORESOURCE -22 /* Not Enough Resources */ ++#define BCME_UNSUPPORTED -23 /* Unsupported */ ++#define BCME_BADLEN -24 /* Bad length */ ++#define BCME_NOTREADY -25 /* Not Ready */ ++#define BCME_EPERM -26 /* Not Permitted */ ++#define BCME_NOMEM -27 /* No Memory */ ++#define BCME_ASSOCIATED -28 /* Associated */ ++#define BCME_RANGE -29 /* Not In Range */ ++#define BCME_NOTFOUND -30 /* Not Found */ ++#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ ++#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ ++#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ ++#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ ++#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ ++#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ ++#define BCME_VERSION -37 /* Incorrect version */ ++#define BCME_TXFAIL -38 /* TX failure */ ++#define BCME_RXFAIL -39 /* RX failure */ ++#define BCME_NODEVICE -40 /* Device not present */ ++#define BCME_NMODE_DISABLED -41 /* NMODE disabled */ ++#define BCME_NONRESIDENT -42 /* access to nonresident overlay */ ++#define BCME_LAST BCME_NONRESIDENT ++ ++/* These are collection of BCME Error strings */ ++#define BCMERRSTRINGTABLE { \ ++ "OK", \ ++ "Undefined error", \ ++ "Bad Argument", \ ++ "Bad Option", \ ++ "Not up", \ ++ "Not down", \ ++ "Not AP", \ ++ "Not STA", \ ++ "Bad Key Index", \ ++ "Radio Off", \ ++ "Not band locked", \ ++ "No clock", \ ++ "Bad Rate valueset", \ ++ "Bad Band", \ ++ "Buffer too short", \ ++ "Buffer too long", \ ++ "Busy", \ ++ "Not Associated", \ ++ "Bad SSID len", \ ++ "Out of Range Channel", \ ++ "Bad Channel", \ ++ "Bad Address", \ ++ "Not Enough Resources", \ ++ "Unsupported", \ ++ "Bad length", \ ++ "Not Ready", \ ++ "Not Permitted", \ ++ "No Memory", \ ++ "Associated", \ ++ "Not In Range", \ ++ "Not Found", \ ++ "WME Not Enabled", \ ++ "TSPEC Not Found", \ ++ "ACM Not Supported", \ ++ "Not WME Association", \ ++ "SDIO Bus Error", \ ++ "Dongle Not Accessible", \ ++ "Incorrect version", \ ++ "TX Failure", \ ++ "RX Failure", \ ++ "Device Not Present", \ ++ "NMODE Disabled", \ ++ "Nonresident overlay access", \ ++} ++ ++#ifndef ABS ++#define ABS(a) (((a) < 0) ? -(a) : (a)) ++#endif /* ABS */ ++ ++#ifndef MIN ++#define MIN(a, b) (((a) < (b)) ? (a) : (b)) ++#endif /* MIN */ ++ ++#ifndef MAX ++#define MAX(a, b) (((a) > (b)) ? (a) : (b)) ++#endif /* MAX */ ++ ++#define CEIL(x, y) (((x) + ((y) - 1)) / (y)) ++#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) ++#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) ++#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0) ++#define VALID_MASK(mask) !((mask) & ((mask) + 1)) ++ ++#ifndef OFFSETOF ++#ifdef __ARMCC_VERSION ++/* ++ * The ARM RVCT compiler complains when using OFFSETOF where a constant ++ * expression is expected, such as an initializer for a static object. ++ * offsetof from the runtime library doesn't have that problem. ++ */ ++#include ++#define OFFSETOF(type, member) offsetof(type, member) ++#else ++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) ++#endif /* __ARMCC_VERSION */ ++#endif /* OFFSETOF */ ++ ++#ifndef ARRAYSIZE ++#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) ++#endif ++ ++/* Reference a function; used to prevent a static function from being optimized out */ ++extern void *_bcmutils_dummy_fn; ++#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) ++ ++/* bit map related macros */ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) ++#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) ++#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) ++#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) ++#endif /* setbit */ ++ ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) ++ ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) ++ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) ++ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) ++ ++/* modulo add/sub - assumes x, y E [0, bound - 1] */ ++#define MODADD(x, y, bound) \ ++ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) ++#define MODSUB(x, y, bound) \ ++ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) ++ ++/* module add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) ++ ++/* crc defines */ ++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ ++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ ++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ ++ ++/* use for direct output of MAC address in printf etc */ ++#define MACF "%02x:%02x:%02x:%02x:%02x:%02x" ++#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ ++ ((struct ether_addr *) (ea))->octet[1], \ ++ ((struct ether_addr *) (ea))->octet[2], \ ++ ((struct ether_addr *) (ea))->octet[3], \ ++ ((struct ether_addr *) (ea))->octet[4], \ ++ ((struct ether_addr *) (ea))->octet[5] ++ ++#define ETHER_TO_MACF(ea) (ea).octet[0], \ ++ (ea).octet[1], \ ++ (ea).octet[2], \ ++ (ea).octet[3], \ ++ (ea).octet[4], \ ++ (ea).octet[5] ++ ++/* bcm_format_flags() bit description structure */ ++typedef struct bcm_bit_desc { ++ uint32 bit; ++ const char* name; ++} bcm_bit_desc_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef struct bcm_tlv { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} bcm_tlv_t; ++ ++/* Check that bcm_tlv_t fits into the given buflen */ ++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) ++ ++/* buffer length for ethernet address from bcm_ether_ntoa() */ ++#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ ++ ++/* crypto utility function */ ++/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */ ++static INLINE void ++xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) ++{ ++ if ( ++#ifdef __i386__ ++ 1 || ++#endif ++ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { ++ /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ ++ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ ++ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0]; ++ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1]; ++ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2]; ++ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3]; ++ } else { ++ /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */ ++ int k; ++ for (k = 0; k < 16; k++) ++ dst[k] = src1[k] ^ src2[k]; ++ } ++} ++ ++/* externs */ ++/* crc */ ++extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc); ++extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc); ++extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc); ++ ++/* format/print */ ++#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ ++ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) ++extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); ++#endif ++ ++#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \ ++ defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ ++ defined(WLMEDIA_PEAKRATE) ++extern int bcm_format_hex(char *str, const void *bytes, int len); ++#endif ++ ++#ifdef BCMDBG ++extern void deadbeef(void *p, size_t len); ++#endif ++extern const char *bcm_crypto_algo_name(uint algo); ++extern char *bcm_chipname(uint chipid, char *buf, uint len); ++extern char *bcm_brev_str(uint32 brev, char *buf); ++extern void printbig(char *buf); ++extern void prhex(const char *msg, uchar *buf, uint len); ++ ++/* IE parsing */ ++extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); ++ ++/* bcmerror */ ++extern const char *bcmerrorstr(int bcmerror); ++extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++typedef uint32 mbool; ++#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ ++#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ ++#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++/* generic datastruct to help dump routines */ ++struct fielddesc { ++ const char *nameandfmt; ++ uint32 offset; ++ uint32 len; ++}; ++ ++extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); ++extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len); ++ ++extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); ++extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes); ++extern void bcm_print_bytes(const char *name, const uchar *cdata, int len); ++ ++typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); ++extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, ++ char *buf, uint32 bufsize); ++extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength); ++ ++extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); ++ ++/* power conversion */ ++extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm); ++extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw); ++ ++extern int32 exthdr_validate(char *ptr, uint size); ++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); ++ ++unsigned int process_nvram_vars(char *varbuf, unsigned int len); ++ ++#ifdef __cplusplus ++ } ++#endif ++ ++#endif /* _bcmutils_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/bcmwifi.h b/drivers/bcmdrivers/gmac/src/include/bcmwifi.h +new file mode 100755 +index 0000000..1470332 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/bcmwifi.h +@@ -0,0 +1,456 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for WL and Apps ++ * This header file housing the define and function prototype use by ++ * both the wl driver, tools & Apps. ++ * ++ * $Id: bcmwifi.h 293848 2011-11-03 12:31:04Z $ ++ */ ++ ++#ifndef _bcmwifi_h_ ++#define _bcmwifi_h_ ++ ++ ++/* A chanspec holds the channel number, band, bandwidth and control sideband */ ++typedef uint16 chanspec_t; ++ ++/* channel defines */ ++#define CH_UPPER_SB 0x01 ++#define CH_LOWER_SB 0x02 ++#define CH_EWA_VALID 0x04 ++#define CH_80MHZ_APART 16 ++#define CH_40MHZ_APART 8 ++#define CH_20MHZ_APART 4 ++#define CH_10MHZ_APART 2 ++#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ ++#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ ++#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, ++ * this is that + 1 rounded up to a multiple of NBBY (8). ++ * DO NOT MAKE it > 255: channels are uint8's all over ++ */ ++#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) ++ ++#ifndef D11AC_IOTYPES ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_CHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_CHANSPEC_BW_MASK 0x0C00 ++#define WL_CHANSPEC_BW_SHIFT 10 ++#define WL_CHANSPEC_BW_10 0x0400 ++#define WL_CHANSPEC_BW_20 0x0800 ++#define WL_CHANSPEC_BW_40 0x0C00 ++ ++#define WL_CHANSPEC_BAND_MASK 0xf000 ++#define WL_CHANSPEC_BAND_SHIFT 12 ++#define WL_CHANSPEC_BAND_5G 0x1000 ++#define WL_CHANSPEC_BAND_2G 0x2000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++ ++/* chanspec stores radio channel & flags to indicate control channel location, i.e. upper/lower */ ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) ++#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) ++#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) ++#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ ++ (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ ++ (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++#define CHANSPEC_STR_LEN 8 ++ ++#else /* D11AC_IOTYPES */ ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++#define WL_CHANSPEC_CHAN1_MASK 0x000f ++#define WL_CHANSPEC_CHAN1_SHIFT 0 ++#define WL_CHANSPEC_CHAN2_MASK 0x00f0 ++#define WL_CHANSPEC_CHAN2_SHIFT 4 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0700 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LLL 0x0000 ++#define WL_CHANSPEC_CTL_SB_LLU 0x0100 ++#define WL_CHANSPEC_CTL_SB_LUL 0x0200 ++#define WL_CHANSPEC_CTL_SB_LUU 0x0300 ++#define WL_CHANSPEC_CTL_SB_ULL 0x0400 ++#define WL_CHANSPEC_CTL_SB_ULU 0x0500 ++#define WL_CHANSPEC_CTL_SB_UUL 0x0600 ++#define WL_CHANSPEC_CTL_SB_UUU 0x0700 ++#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL ++#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU ++#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU ++ ++#define WL_CHANSPEC_BW_MASK 0x3800 ++#define WL_CHANSPEC_BW_SHIFT 11 ++#define WL_CHANSPEC_BW_5 0x0000 ++#define WL_CHANSPEC_BW_10 0x0800 ++#define WL_CHANSPEC_BW_20 0x1000 ++#define WL_CHANSPEC_BW_40 0x1800 ++#define WL_CHANSPEC_BW_80 0x2000 ++#define WL_CHANSPEC_BW_160 0x2800 ++#define WL_CHANSPEC_BW_8080 0x3000 ++ ++#define WL_CHANSPEC_BAND_MASK 0xc000 ++#define WL_CHANSPEC_BAND_SHIFT 14 ++#define WL_CHANSPEC_BAND_2G 0x0000 ++#define WL_CHANSPEC_BAND_3G 0x4000 ++#define WL_CHANSPEC_BAND_4G 0x8000 ++#define WL_CHANSPEC_BAND_5G 0xc000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ ++ ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_80 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_160 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++ ++/* simple MACROs to get different fields of chanspec */ ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) ++#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_UPPER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC_SB_LOWER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++/** ++ * Number of chars needed for wf_chspec_ntoa() destination character buffer. ++ */ ++#define CHANSPEC_STR_LEN 20 ++ ++ ++/* Legacy Chanspec defines ++ * These are the defines for the previous format of the chanspec_t ++ */ ++#define WL_LCHANSPEC_CHAN_MASK 0x00ff ++#define WL_LCHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_LCHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_LCHANSPEC_CTL_SB_SHIFT 8 ++#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_LCHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_LCHANSPEC_BW_MASK 0x0C00 ++#define WL_LCHANSPEC_BW_SHIFT 10 ++#define WL_LCHANSPEC_BW_10 0x0400 ++#define WL_LCHANSPEC_BW_20 0x0800 ++#define WL_LCHANSPEC_BW_40 0x0C00 ++ ++#define WL_LCHANSPEC_BAND_MASK 0xf000 ++#define WL_LCHANSPEC_BAND_SHIFT 12 ++#define WL_LCHANSPEC_BAND_5G 0x1000 ++#define WL_LCHANSPEC_BAND_2G 0x2000 ++ ++#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) ++#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) ++#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) ++#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) ++#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) ++#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) ++#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) ++#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) ++#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) ++ ++#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) ++ ++#endif /* D11AC_IOTYPES */ ++ ++/* ++ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency ++ * given a channel number. ++ * chan_freq = chan_factor * 500Mhz + chan_number * 5 ++ */ ++ ++/** ++ * Channel Factor for the starting frequence of 2.4 GHz channels. ++ * The value corresponds to 2407 MHz. ++ */ ++#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 5 GHz channels. ++ * The value corresponds to 5000 MHz. ++ */ ++#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 4.9 GHz channels. ++ * The value corresponds to 4000 MHz. ++ */ ++#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ ++ ++/* defined rate in 500kbps */ ++#define WLC_MAXRATE 108 /* in 500kbps units */ ++#define WLC_RATE_1M 2 /* in 500kbps units */ ++#define WLC_RATE_2M 4 /* in 500kbps units */ ++#define WLC_RATE_5M5 11 /* in 500kbps units */ ++#define WLC_RATE_11M 22 /* in 500kbps units */ ++#define WLC_RATE_6M 12 /* in 500kbps units */ ++#define WLC_RATE_9M 18 /* in 500kbps units */ ++#define WLC_RATE_12M 24 /* in 500kbps units */ ++#define WLC_RATE_18M 36 /* in 500kbps units */ ++#define WLC_RATE_24M 48 /* in 500kbps units */ ++#define WLC_RATE_36M 72 /* in 500kbps units */ ++#define WLC_RATE_48M 96 /* in 500kbps units */ ++#define WLC_RATE_54M 108 /* in 500kbps units */ ++ ++#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ ++ ++/** ++ * Convert chanspec to ascii string ++ * ++ * @param chspec chanspec format ++ * @param buf ascii string of chanspec ++ * ++ * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes ++ * ++ * @see CHANSPEC_STR_LEN ++ */ ++extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); ++ ++/** ++ * Convert ascii string to chanspec ++ * ++ * @param a pointer to input string ++ * ++ * @return >= 0 if successful or 0 otherwise ++ */ ++extern chanspec_t wf_chspec_aton(const char *a); ++ ++/** ++ * Verify the chanspec fields are valid. ++ * ++ * Verify the chanspec is using a legal set field values, i.e. that the chanspec ++ * specified a band, bw, ctl_sb and channel and that the combination could be ++ * legal given some set of circumstances. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is malformed, FALSE if it looks good. ++ */ ++extern bool wf_chspec_malformed(chanspec_t chanspec); ++ ++/** ++ * Verify the chanspec specifies a valid channel according to 802.11. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is a valid 802.11 channel ++ */ ++extern bool wf_chspec_valid(chanspec_t chanspec); ++ ++/** ++ * Return the primary (control) channel. ++ * ++ * This function returns the channel number of the primary 20MHz channel. For ++ * 20MHz channels this is just the channel number. For 40MHz or wider channels ++ * it is the primary 20MHz channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the channel number of the primary 20MHz channel ++ */ ++extern uint8 wf_chspec_ctlchan(chanspec_t chspec); ++ ++/** ++ * Return the primary (control) chanspec. ++ * ++ * This function returns the chanspec of the primary 20MHz channel. For 20MHz ++ * channels this is just the chanspec. For 40MHz or wider channels it is the ++ * chanspec of the primary 20MHZ channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the chanspec of the primary 20MHz channel ++ */ ++extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); ++ ++/** ++ * Return a channel number corresponding to a frequency. ++ * ++ * Return the channel number for a given frequency and base frequency. ++ * The returned channel number is relative to the given base frequency. ++ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for ++ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. ++ * ++ * Frequency is specified in MHz. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * ++ * The returned channel will be in the range [1, 14] in the 2.4 GHz band ++ * and [0, 200] otherwise. ++ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the ++ * frequency is not a 2.4 GHz channel, or if the frequency is not and even ++ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param freq frequency in MHz ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a channel number ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_mhz2channel(uint freq, uint start_factor); ++ ++/** ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * The channel number is interpreted relative to the given base frequency. ++ * ++ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * The channel range of [1, 14] is only checked for a start_factor of ++ * WF_CHAN_FACTOR_2_4_G (4814). ++ * Odd start_factors produce channels on .5 MHz boundaries, in which case ++ * the answer is rounded down to an integral MHz. ++ * -1 is returned for an out of range channel. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param channel input channel number ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a frequency in MHz ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_channel2mhz(uint channel, uint start_factor); ++ ++#endif /* _bcmwifi_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/compvers.sh b/drivers/bcmdrivers/gmac/src/include/compvers.sh +new file mode 100755 +index 0000000..3f6fd6a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/compvers.sh +@@ -0,0 +1,122 @@ ++#!/bin/bash ++# ++# Given a list of components, generate _version.h ++# from version.h.in in 's directory ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: compvers.sh 281527 2011-09-02 17:12:53Z $ ++# ++ ++# Optional argument ++ACTION=$1 ++[ -n "$VERBOSE" ] && export VERBOSE ++ ++SRCBASE=.. ++ ++# List of components ++# TODO: In the long term component versioning model, following list ++# TODO: or table of components will come from a central file ++COMPONENTS=( \ ++ upnp \ ++ phy \ ++ router \ ++ wps \ ++) ++ ++# Component dirs. Need one entry for each of above COMPONENTS ++COMPONENT_DIR_upnp=${SRCBASE}/router/libupnp/include ++COMPONENT_DIR_phy=${SRCBASE}/wl/phy ++COMPONENT_DIR_router=${SRCBASE}/router/shared ++COMPONENT_DIR_wps=${SRCBASE}/wps/common/include ++ ++# For a given component, query automerger for a different ++# path than COMPONENT_DIR_. ++# Force router component to be pointing to local branch or tag. ++COMPONENT_QUERY_router=src_force_local_component ++ ++ ++ ++# ===== DO NOT CHANGE ANYTHING BELOW THIS LINE ===== ++ ++NULL=/dev/null ++MKCOMPVER=${SRCBASE}/tools/release/mkversion.sh ++MERGERLOG=${SRCBASE}/../merger_sources.log ++ ++# TODO: Post svn transition, network paths will be taken away ++GETCOMPVER=getcompver.py ++GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER ++GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} ++ ++# ++# If there is a local copy GETCOMPVER use it ahead of network copy ++# ++if [ -s "$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER" ++elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" ++elif [ -s "$GETCOMPVER_NET" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET" ++elif [ -s "$GETCOMPVER_NET_WIN" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" ++fi ++ ++# ++# If $GETCOMPVER isn't found, fetch it from SVN ++# (this is very rare) ++# ++if [ ! -s "$GETCOMPVER_PATH" ]; then ++ svn export -q \ ++ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ ++ ${GETCOMPVER} 2> $NULL ++ GETCOMPVER_PATH=$GETCOMPVER ++fi ++ ++# ++# Now walk through each specified component to generate its ++# component_version.h file from version.h.in template ++# ++for component in ${COMPONENTS[*]} ++do ++ # Get relative path of component from current dir ++ tmp="COMPONENT_DIR_$component" ++ eval rel_path=\$$tmp ++ ++ # Get query path for component ++ tmp="COMPONENT_QUERY_$component" ++ eval query_path=\$$tmp ++ ++ if [ ! -d "$rel_path" ]; then ++ continue ++ fi ++ ++ if [ "$query_path" != "" ]; then ++ abs_path=$(echo $query_path | sed -e "s%\.\.%src%g") ++ else ++ abs_path=$(echo $rel_path | sed -e "s%\.\.%src%g") ++ fi ++ ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG $abs_path" ++ ++ tag=$(python $GETCOMPVER_PATH $MERGERLOG $abs_path 2> $NULL | sed -e 's/[[:space:]]*//g') ++ ++ template=$rel_path/version.h.in ++ verfile=$rel_path/${component}_version.h ++ ++ if [ "$ACTION" == "clean" ]; then ++ rm -fv $verfile ++ continue ++ fi ++ ++ # MKCOMPVER always has defaults if tag isn't set correctly ++ if [ ! -f "$verfile" -o "$FORCE" != "" ]; then ++ echo "" ++ echo ">>> Generate $abs_path/${component}_version.h from $tag" ++ ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: bash $MKCOMPVER $template $verfile $tag" ++ ++ bash $MKCOMPVER $template $verfile $tag ++ fi ++done +diff --git a/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h b/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h +new file mode 100755 +index 0000000..a44e08b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/ctf/ctf_cfg.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: $ ++ */ ++ ++#ifndef _CTF_CFG_H_ ++#define _CTF_CFG_H_ ++ ++#define NETLINK_CTF 20 ++ ++#define SUCCESS 0 ++#define FAILURE -1 ++ ++#define CTFCFG_MAX_SIZE sizeof(ctf_cfg_request_t) ++#define CTFCFG_MAX_ARG_SIZE 1024 ++ ++#define CTFCFG_CMD_SUSPEND 1 ++#define CTFCFG_CMD_RESUME 2 ++#define CTFCFG_CMD_TUPLE_VALID 3 ++#define CTFCFG_CMD_DEFAULT_FWD_GET 4 ++#define CTFCFG_CMD_DEFAULT_FWD_SET 5 ++ ++#define CTFCFG_STATUS_SUCCESS 1 ++#define CTFCFG_STATUS_FAILURE 2 ++#define CTFCFG_STATUS_TUPLE_INVALID 3 ++#define CTFCFG_STATUS_FLOW_ALREADY_SUSPENDED 4 ++#define CTFCFG_STATUS_FLOW_NOT_SUSPENDED 5 ++#define CTFCFG_STATUS_DEFAULT_FWD_INVALID 6 ++#define CTFCFG_STATUS_PROTOCOL_NOT_SUPPORTED 7 ++ ++typedef union ++{ ++ struct in_addr ip_v4; ++ struct in6_addr ip_v6; ++} ip_address_t; ++ ++typedef struct ++{ ++ int family; ++ ++ ip_address_t src_addr; ++ ip_address_t dst_addr; ++ ++ uint16_t src_port; ++ uint16_t dst_port; ++ ++ uint8_t protocol; ++} ctf_tuple_t; ++ ++typedef enum { ++ CTF_FWD_FASTPATH, ++ CTF_FWD_HOST, /* i.e. send to network stack */ ++} ctf_fwd_t; ++ ++typedef struct ctf_cfg_request ++{ ++ uint32_t command_id; ++ uint32_t status; /* Command status */ ++ uint32_t size; /* Size of the argument */ ++ uint8_t arg[CTFCFG_MAX_ARG_SIZE]; ++} ctf_cfg_request_t; ++ ++#endif /* _CTF_CFG_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h b/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h +new file mode 100755 +index 0000000..e4385dd +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/ctf/hndctf.h +@@ -0,0 +1,299 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: hndctf.h 418247 2013-08-14 11:16:42Z $ ++ */ ++ ++#ifndef _HNDCTF_H_ ++#define _HNDCTF_H_ ++ ++#include ++#include ++#include ++#include ++/* ++ * Define to enable couting VLAN tx and rx packets and bytes. This could be ++ * disabled if the functionality has impact on performance. ++ */ ++#define CTFVLSTATS ++ ++#define CTF_ENAB(ci) (((ci) != NULL) && (ci)->_ctf) ++ ++#define CTF_ACTION_TAG (1 << 0) ++#define CTF_ACTION_UNTAG (1 << 1) ++#define CTF_ACTION_SNAT (1 << 2) ++#define CTF_ACTION_DNAT (1 << 3) ++#define CTF_ACTION_SUSPEND (1 << 4) ++#define CTF_ACTION_TOS (1 << 5) ++#define CTF_ACTION_MARK (1 << 6) ++#define CTF_ACTION_BYTECNT (1 << 7) ++#define CTF_ACTION_PPPOE_ADD (1 << 8) ++#define CTF_ACTION_PPPOE_DEL (1 << 9) ++ ++#define CTF_SUSPEND_TCP (1 << 0) ++#define CTF_SUSPEND_UDP (1 << 1) ++ ++#define ctf_attach(osh, n, m, c, a) \ ++ (ctf_attach_fn ? ctf_attach_fn(osh, n, m, c, a) : NULL) ++#define ctf_forward(ci, p, d) (ci)->fn.forward(ci, p, d) ++#define ctf_isenabled(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isenabled(ci, d) : FALSE) ++#define ctf_isbridge(ci, d) (CTF_ENAB(ci) ? (ci)->fn.isbridge(ci, d) : FALSE) ++#define ctf_enable(ci, d, e, b) (CTF_ENAB(ci) ? (ci)->fn.enable(ci, d, e, b) : BCME_OK) ++#define ctf_brc_add(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_add(ci, b) : BCME_OK) ++#define ctf_brc_delete(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_delete(ci, e) : BCME_OK) ++#define ctf_brc_update(ci, b) (CTF_ENAB(ci) ? (ci)->fn.brc_update(ci, b) : BCME_OK) ++#define ctf_brc_lkup(ci, e) (CTF_ENAB(ci) ? (ci)->fn.brc_lkup(ci, e) : NULL) ++#define ctf_brc_release(ci, b) do { if (CTF_ENAB(ci)) (ci)->fn.brc_release(ci, b); } while (0) ++#define ctf_ipc_add(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.ipc_add(ci, i, v6) : BCME_OK) ++#define ctf_ipc_delete(ci, i, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete(ci, i, v6) : BCME_OK) ++#define ctf_ipc_count_get(ci, i) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_count_get(ci, i) : BCME_OK) ++#define ctf_ipc_delete_multi(ci, i, im, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_multi(ci, i, im, v6) : BCME_OK) ++#define ctf_ipc_delete_range(ci, s, e, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_delete_range(ci, s, e, v6) : BCME_OK) ++#define ctf_ipc_action(ci, s, e, am, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_action(ci, s, e, am, v6) : BCME_OK) ++#define ctf_ipc_lkup(ci, i, v6) \ ++ (CTF_ENAB(ci) ? (ci)->fn.ipc_lkup(ci, i, v6) : NULL) ++#ifdef CTF_IPV6 ++#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (CTF_ENAB(ci) && (ci)->fn.ipc_lkup_l4proto? \ ++ (ci)->fn.ipc_lkup_l4proto((uint8 *)iph, l4p) : NULL) ++#else ++#define ctf_ipc_lkup_l4proto(ci, iph, l4p) (NULL) ++#endif /* CTF_IPV6 */ ++#define ctf_ipc_release(ci, i) do { if (CTF_ENAB(ci)) (ci)->fn.ipc_release(ci, i); } while (0) ++#define ctf_dev_register(ci, d, b) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_register(ci, d, b) : BCME_OK) ++#define ctf_dev_vlan_add(ci, d, vid, vd) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_add(ci, d, vid, vd) : BCME_OK) ++#define ctf_dev_vlan_delete(ci, d, vid) \ ++ (CTF_ENAB(ci) ? (ci)->fn.dev_vlan_delete(ci, d, vid) : BCME_OK) ++#define ctf_detach(ci) if (CTF_ENAB(ci)) (ci)->fn.detach(ci) ++#define ctf_dump(ci, b) if (CTF_ENAB(ci)) (ci)->fn.dump(ci, b) ++#define ctf_cfg_req_process(ci, c) if (CTF_ENAB(ci)) (ci)->fn.cfg_req_process(ci, c) ++#define ctf_dev_unregister(ci, d) if (CTF_ENAB(ci)) (ci)->fn.dev_unregister(ci, d) ++#ifdef BCMFA ++#define ctf_fa_register(ci, d, i) if (CTF_ENAB(ci)) (ci)->fn.fa_register(ci, d, i) ++#define ctf_live(ci, i, v6) (CTF_ENAB(ci) ? (ci)->fn.live(ci, i, v6) : FALSE) ++#endif /* BCMFA */ ++ ++#define CTFCNTINCR(s) ((s)++) ++#define CTFCNTADD(s, c) ((s) += (c)) ++ ++#define PPPOE_ETYPE_OFFSET 12 ++#define PPPOE_VER_OFFSET 14 ++#define PPPOE_SESID_OFFSET 16 ++#define PPPOE_LEN_OFFSET 18 ++ ++#define PPPOE_HLEN 20 ++#define PPPOE_PPP_HLEN 8 ++ ++#define PPPOE_PROT_PPP 0x0021 ++#define PPPOE_PROT_PPP_IP6 0x0057 ++ ++ ++typedef struct ctf_pub ctf_t; ++typedef struct ctf_brc ctf_brc_t; ++typedef struct ctf_ipc ctf_ipc_t; ++typedef struct ctf_conn_tuple ctf_conn_tuple_t; ++typedef struct ctf_brc_hot ctf_brc_hot_t; ++ ++typedef void (*ctf_detach_cb_t)(ctf_t *ci, void *arg); ++typedef ctf_t * (*ctf_attach_t)(osl_t *osh, uint8 *name, uint32 *msg_level, ++ ctf_detach_cb_t cb, void *arg); ++typedef void (*ctf_detach_t)(ctf_t *ci); ++typedef int32 (*ctf_forward_t)(ctf_t *ci, void *p, void *rxifp); ++typedef bool (*ctf_isenabled_t)(ctf_t *ci, void *dev); ++typedef bool (*ctf_isbridge_t)(ctf_t *ci, void *dev); ++typedef int32 (*ctf_brc_add_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef int32 (*ctf_brc_delete_t)(ctf_t *ci, uint8 *ea); ++typedef int32 (*ctf_brc_update_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef ctf_brc_t * (*ctf_brc_lkup_t)(ctf_t *ci, uint8 *da); ++typedef void (*ctf_brc_release_t)(ctf_t *ci, ctf_brc_t *brc); ++typedef int32 (*ctf_ipc_add_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef int32 (*ctf_ipc_delete_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef int32 (*ctf_ipc_count_get_t)(ctf_t *ci); ++typedef int32 (*ctf_ipc_delete_multi_t)(ctf_t *ci, ctf_ipc_t *ipc, ++ ctf_ipc_t *ipcm, bool v6); ++typedef int32 (*ctf_ipc_delete_range_t)(ctf_t *ci, ctf_ipc_t *start, ++ ctf_ipc_t *end, bool v6); ++typedef int32 (*ctf_ipc_action_t)(ctf_t *ci, ctf_ipc_t *start, ++ ctf_ipc_t *end, uint32 action_mask, bool v6); ++typedef ctf_ipc_t * (*ctf_ipc_lkup_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++typedef uint8 * (*ctf_ipc_lkup_l4proto_t)(uint8 *iph, uint8 *proto_num); ++typedef void (*ctf_ipc_release_t)(ctf_t *ci, ctf_ipc_t *ipc); ++typedef int32 (*ctf_enable_t)(ctf_t *ci, void *dev, bool enable, ctf_brc_hot_t **brc_hot); ++typedef int32 (*ctf_dev_register_t)(ctf_t *ci, void *dev, bool br); ++typedef void (*ctf_dev_unregister_t)(ctf_t *ci, void *dev); ++typedef int32 (*ctf_dev_vlan_add_t)(ctf_t *ci, void *dev, uint16 vid, void *vldev); ++typedef int32 (*ctf_dev_vlan_delete_t)(ctf_t *ci, void *dev, uint16 vid); ++typedef void (*ctf_dump_t)(ctf_t *ci, struct bcmstrbuf *b); ++typedef void (*ctf_cfg_req_process_t)(ctf_t *ci, void *arg); ++#ifdef BCMFA ++typedef int (*ctf_fa_cb_t)(void *dev, ctf_ipc_t *ipc, bool v6, int cmd); ++ ++typedef int32 (*ctf_fa_register_t)(ctf_t *ci, ctf_fa_cb_t facb, void *fa); ++typedef void (*ctf_live_t)(ctf_t *ci, ctf_ipc_t *ipc, bool v6); ++#endif /* BCMFA */ ++ ++struct ctf_brc_hot { ++ struct ether_addr ea; /* Dest address */ ++ ctf_brc_t *brcp; /* BRC entry corresp to dest mac */ ++}; ++ ++typedef struct ctf_fn { ++ ctf_detach_t detach; ++ ctf_forward_t forward; ++ ctf_isenabled_t isenabled; ++ ctf_isbridge_t isbridge; ++ ctf_brc_add_t brc_add; ++ ctf_brc_delete_t brc_delete; ++ ctf_brc_update_t brc_update; ++ ctf_brc_lkup_t brc_lkup; ++ ctf_brc_release_t brc_release; ++ ctf_ipc_add_t ipc_add; ++ ctf_ipc_delete_t ipc_delete; ++ ctf_ipc_count_get_t ipc_count_get; ++ ctf_ipc_delete_multi_t ipc_delete_multi; ++ ctf_ipc_delete_range_t ipc_delete_range; ++ ctf_ipc_action_t ipc_action; ++ ctf_ipc_lkup_t ipc_lkup; ++ ctf_ipc_lkup_l4proto_t ipc_lkup_l4proto; ++ ctf_ipc_release_t ipc_release; ++ ctf_enable_t enable; ++ ctf_dev_register_t dev_register; ++ ctf_dev_unregister_t dev_unregister; ++ ctf_detach_cb_t detach_cb; ++ void *detach_cb_arg; ++ ctf_dev_vlan_add_t dev_vlan_add; ++ ctf_dev_vlan_delete_t dev_vlan_delete; ++ ctf_dump_t dump; ++ ctf_cfg_req_process_t cfg_req_process; ++#ifdef BCMFA ++ ctf_fa_register_t fa_register; ++ ctf_live_t live; ++#endif /* BCMFA */ ++} ctf_fn_t; ++ ++struct ctf_pub { ++ bool _ctf; /* Global CTF enable/disable */ ++ ctf_fn_t fn; /* Exported functions */ ++ void *nl_sk; /* Netlink socket */ ++ uint32 ipc_suspend; /* Global IPC suspend flags */ ++}; ++ ++struct ctf_mark; /* Connection Mark */ ++ ++struct ctf_brc { ++ struct ctf_brc *next; /* Pointer to brc entry */ ++ struct ether_addr dhost; /* MAC addr of host */ ++ uint16 vid; /* VLAN id to use on txif */ ++ void *txifp; /* Interface connected to host */ ++ uint32 action; /* Tag or untag the frames */ ++ uint32 live; /* Counter used to expire the entry */ ++ uint32 hits; /* Num frames matching brc entry */ ++ uint64 *bytecnt_ptr; /* Pointer to the byte counter */ ++}; ++ ++#ifdef CTF_IPV6 ++#define IPADDR_U32_SZ (IPV6_ADDR_LEN / sizeof(uint32)) ++#else ++#define IPADDR_U32_SZ 1 ++#endif ++ ++struct ctf_conn_tuple { ++ uint32 sip[IPADDR_U32_SZ], dip[IPADDR_U32_SZ]; ++ uint16 sp, dp; ++ uint8 proto; ++}; ++ ++typedef struct ctf_nat { ++ uint32 ip; ++ uint16 port; ++} ctf_nat_t; ++ ++#ifdef BCMFA ++#define CTF_FA_PEND_ADD_ENTRY 0x1 ++#define CTF_FA_ADD_ISPEND(ipc) ((ipc)->flags & CTF_FA_PEND_ADD_ENTRY) ++#define CTF_FA_SET_ADD_PEND(ipc) ((ipc)->flags |= CTF_FA_PEND_ADD_ENTRY) ++#define CTF_FA_CLR_ADD_PEND(ipc) ((ipc)->flags &= ~(CTF_FA_PEND_ADD_ENTRY)) ++#endif /* BCMFA */ ++ ++struct ctf_ipc { ++ struct ctf_ipc *next; /* Pointer to ipc entry */ ++ ctf_conn_tuple_t tuple; /* Tuple to uniquely id the flow */ ++ uint16 vid; /* VLAN id to use on txif */ ++ struct ether_addr dhost; /* Destination MAC address */ ++ struct ether_addr shost; /* Source MAC address */ ++ void *txif; /* Target interface to send */ ++ uint32 action; /* NAT and/or VLAN actions */ ++ ctf_brc_t *brcp; /* BRC entry corresp to source mac */ ++ uint32 live; /* Counter used to expire the entry */ ++ struct ctf_nat nat; /* Manip data for SNAT, DNAT */ ++ struct ether_addr sa; /* MAC address of sender */ ++ uint8 tos; /* IPv4 tos or IPv6 traff class excl ECN */ ++ uint16 pppoe_sid; /* PPPOE session to use */ ++ void *ppp_ifp; /* PPP interface handle */ ++ uint32 hits; /* Num frames matching ipc entry */ ++ uint64 *bytecnt_ptr; /* Pointer to the byte counter */ ++ struct ctf_mark mark; /* Mark value to use for the connection */ ++#ifdef BCMFA ++ void *rxif; /* Receive interface */ ++ void *pkt; /* Received packet */ ++ uint8 flags; /* Flags for multiple purpose */ ++#endif /* BCMFA */ ++}; ++ ++extern ctf_t *ctf_kattach(osl_t *osh, uint8 *name); ++extern void ctf_kdetach(ctf_t *kci); ++extern ctf_attach_t ctf_attach_fn; ++extern ctf_t *_ctf_attach(osl_t *osh, uint8 *name, uint32 *msg_level, ++ ctf_detach_cb_t cb, void *arg); ++extern ctf_t *kcih; ++ ++/* Hot bridge cache lkup */ ++#define MAXBRCHOT 4 ++#define MAXBRCHOTIF 4 ++#define CTF_BRC_HOT_HASH(da) ((((uint8 *)da)[4] ^ ((uint8 *)da)[5]) & (MAXBRCHOT - 1)) ++#define CTF_HOTBRC_CMP(hbrc, da, rxifp) \ ++({ \ ++ ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(da); \ ++ ((eacmp((bh)->ea.octet, (da)) == 0) && (bh->brcp->txifp != (rxifp))); \ ++}) ++ ++/* Header prep for packets matching hot bridge cache entry */ ++#define CTF_HOTBRC_L2HDR_PREP(osh, hbrc, prio, data, p) \ ++do { \ ++ uint8 *l2h; \ ++ ctf_brc_hot_t *bh = (hbrc) + CTF_BRC_HOT_HASH(data); \ ++ ASSERT(*(uint16 *)((data) + VLAN_TPID_OFFSET) == HTON16(ETHER_TYPE_8021Q)); \ ++ if (bh->brcp->action & CTF_ACTION_UNTAG) { \ ++ /* Remove vlan header */ \ ++ l2h = PKTPULL((osh), (p), VLAN_TAG_LEN); \ ++ ether_rcopy(l2h - VLAN_TAG_LEN + ETHER_ADDR_LEN, \ ++ l2h + ETHER_ADDR_LEN); \ ++ ether_rcopy(l2h - VLAN_TAG_LEN, l2h); \ ++ } else { \ ++ /* Update vlan header */ \ ++ l2h = (data); \ ++ *(uint16 *)(l2h + VLAN_TCI_OFFSET) = \ ++ HTON16((prio) << VLAN_PRI_SHIFT | bh->brcp->vid); \ ++ } \ ++} while (0) ++ ++ ++#endif /* _HNDCTF_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.h b/drivers/bcmdrivers/gmac/src/include/epivers.h +new file mode 100644 +index 0000000..6b067dd +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.h.in +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ ++ * ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION @EPI_MAJOR_VERSION@ ++ ++#define EPI_MINOR_VERSION @EPI_MINOR_VERSION@ ++ ++#define EPI_RC_NUMBER @EPI_RC_NUMBER@ ++ ++#define EPI_INCREMENTAL_NUMBER @EPI_INCREMENTAL_NUMBER@ ++ ++#define EPI_BUILD_NUMBER @EPI_BUILD_NUMBER@ ++ ++#define EPI_VERSION @EPI_VERSION@ ++ ++#define EPI_VERSION_NUM @EPI_VERSION_NUM@ ++ ++#define EPI_VERSION_DEV @EPI_VERSION_DEV@ ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef WLTEST ++#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@ WLTEST)" ++#else ++#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@)" ++#endif ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.sh b/drivers/bcmdrivers/gmac/src/include/epivers.sh +new file mode 100755 +index 0000000..4424501 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 $ ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION 6 ++ ++#define EPI_MINOR_VERSION 30 ++ ++#define EPI_RC_NUMBER 40 ++ ++#define EPI_INCREMENTAL_NUMBER 0 ++ ++#define EPI_BUILD_NUMBER 2 ++ ++#define EPI_VERSION 6, 30, 40, 0 ++ ++#define EPI_VERSION_NUM 0x061e2800 ++ ++#define EPI_VERSION_DEV 6.30.40 ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef WLTEST ++#define EPI_VERSION_STR "6.30.40 (TOB) (r WLTEST)" ++#else ++#define EPI_VERSION_STR "6.30.40 (TOB) (r)" ++#endif ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/epivers.h.in b/drivers/bcmdrivers/gmac/src/include/epivers.h.in +new file mode 100755 +index 0000000..790f8d4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/epivers.sh +@@ -0,0 +1,295 @@ ++#! /bin/bash ++# ++# Create the epivers.h file from epivers.h.in ++# ++# Epivers.h generation mechanism supports svn based checkouts ++# ++# $Id: epivers.sh 299409 2011-11-30 00:52:43Z $ ++# ++# GetCompVer.py return value and action needed ++# i. trunk => use current date as version string ++# ii. local => use SVNURL expanded by HeadURL keyword ++# iii. => use it as as is ++# (some components can override and say give me native ver) ++# iv. empty => ++# a) If TAG is specified use it ++# a) If no TAG is specified use date ++# ++ ++# If the version header file already exists, increment its build number. ++# Otherwise, create a new file. ++if [ -f epivers.h ]; then ++ ++ # If REUSE_VERSION is set, epivers iteration is not incremented ++ # This can be used precommit and continuous integration projects ++ if [ -n "$REUSE_VERSION" ]; then ++ echo "Previous epivers.h exists. Skipping version increment" ++ exit 0 ++ fi ++ ++ build=`grep EPI_BUILD_NUMBER epivers.h | sed -e "s,.*BUILD_NUMBER[ ]*,,"` ++ build=`expr ${build} + 1` ++ echo build=${build} ++ sed -e "s,.*_BUILD_NUMBER.*,#define EPI_BUILD_NUMBER ${build}," \ ++ < epivers.h > epivers.h.new ++ mv epivers.h epivers.h.prev ++ mv epivers.h.new epivers.h ++ exit 0 ++ ++else # epivers.h doesn't exist ++ ++ NULL="/dev/null" ++ svncmd="svn --non-interactive" ++ ++ # Check for the in file, if not there we're in the wrong directory ++ if [ ! -f epivers.h.in ]; then ++ echo "ERROR: No epivers.h.in found" ++ exit 1 ++ fi ++ ++ # Following SVNURL should be expanded on checkout ++ SVNURL='$HeadURL: http://svn.sj.broadcom.com/svn/wlansvn/users/kenlo/northstar/AARDVARK_TWIG_6_30_40/src/include/epivers.sh $' ++ ++ # If SVNURL isn't expanded, extract it from svn info ++ if echo "$SVNURL" | grep -vq '$.*HeadURL.*epivers.sh.*$'; then ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: SVN URL wasn't expanded. Getting it from svn info" ++ SVNURL=$($svncmd info epivers.sh 2> $NULL | egrep "^URL:") ++ fi ++ ++ if echo "${TAG}" | grep -q "_BRANCH_\|_TWIG_"; then ++ branchtag=$TAG ++ else ++ branchtag="" ++ fi ++ ++ # If this is a tagged build, use the tag to supply the numbers ++ # Tag should be in the form ++ # _REL__ ++ # or ++ # _REL___RC ++ # or ++ # _REL___RC_ ++ ++ SRCBASE=.. ++ MERGERLOG=${SRCBASE}/../merger_sources.log ++ GETCOMPVER=getcompver.py ++ GETCOMPVER_NET=/projects/hnd_software/gallery/src/tools/build/$GETCOMPVER ++ GETCOMPVER_NET_WIN=Z:${GETCOMPVER_NET} ++ ++ # ++ # If there is a local copy GETCOMPVER use it ahead of network copy ++ # ++ if [ -s "$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER" ++ elif [ -s "${SRCBASE}/../src/tools/build/$GETCOMPVER" ]; then ++ GETCOMPVER_PATH="${SRCBASE}/../src/tools/build/$GETCOMPVER" ++ elif [ -s "$GETCOMPVER_NET" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET" ++ elif [ -s "$GETCOMPVER_NET_WIN" ]; then ++ GETCOMPVER_PATH="$GETCOMPVER_NET_WIN" ++ fi ++ ++ # ++ # If $GETCOMPVER isn't found, fetch it from SVN ++ # (this should be very rare) ++ # ++ if [ ! -s "$GETCOMPVER_PATH" ]; then ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: Fetching $GETCOMPVER from trunk" ++ ++ $svncmd export -q \ ++ ^/proj/trunk/src/tools/build/${GETCOMPVER} \ ++ ${GETCOMPVER} 2> $NULL ++ ++ GETCOMPVER_PATH=$GETCOMPVER ++ fi ++ ++ # Now get tag for src/include from automerger log ++ [ -n "$VERBOSE" ] && \ ++ echo "DBG: python $GETCOMPVER_PATH $MERGERLOG src/include" ++ ++ COMPTAG=$(python $GETCOMPVER_PATH $MERGERLOG src/include 2> $NULL | sed -e 's/[[:space:]]*//g') ++ ++ echo "DBG: Component Tag String Derived = $COMPTAG" ++ ++ # Process COMPTAG values ++ # Rule: ++ # If trunk is returned, use date as component tag ++ # If LOCAL_COMPONENT is returned, use SVN URL to get native tag ++ # If component is returned or empty, assign it to SVNTAG ++ # GetCompVer.py return value and action needed ++ # i. trunk => use current date as version string ++ # ii. local => use SVNURL expanded by HeadURL keyword ++ # iii. => use it as as is ++ # iv. empty => ++ # a) If TAG is specified use it ++ # a) If no TAG is specified use SVNURL from HeadURL ++ ++ SVNURL_VER=false ++ ++ if [ "$COMPTAG" == "" ]; then ++ SVNURL_VER=true ++ elif [ "$COMPTAG" == "LOCAL_COMPONENT" ]; then ++ SVNURL_VER=true ++ elif [ "$COMPTAG" == "trunk" ]; then ++ SVNTAG=$(date '+TRUNKCOMP_REL_%Y_%m_%d') ++ else ++ SVNTAG=$COMPTAG ++ fi ++ ++ # Given SVNURL path conventions or naming conventions, derive SVNTAG ++ # TO-DO: SVNTAG derivation logic can move to a central common API ++ # TO-DO: ${SRCBASE}/tools/build/svnurl2tag.sh ++ if [ "$SVNURL_VER" == "true" ]; then ++ case "${SVNURL}" in ++ */branches/*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%.*/branches/\(.*\)/src.*%\1%g' | xargs printf "%s") ++ ;; ++ *_BRANCH_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _BRANCH_ | xargs printf "%s") ++ ;; ++ *_TWIG_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _TWIG_ | xargs printf "%s") ++ ;; ++ */tags/*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%.*/tags/.*/\(.*\)/src.*%\1%g' | xargs printf "%s") ++ ;; ++ *_REL_*) ++ SVNTAG=$(echo $SVNURL | sed -e 's%/%\n%g' | egrep _REL_ | xargs printf "%s") ++ ;; ++ */trunk/*) ++ SVNTAG=$(date '+TRUNKURL_REL_%Y_%m_%d') ++ ;; ++ *) ++ SVNTAG=$(date '+OTHER_REL_%Y_%m_%d') ++ ;; ++ esac ++ echo "DBG: Native Tag String Derived from URL: $SVNTAG" ++ else ++ echo "DBG: Native Tag String Derived: $SVNTAG" ++ fi ++ ++ TAG=${SVNTAG} ++ ++ # Normalize the branch name portion to "D11" in case it has underscores in it ++ branch_name=`expr match "$TAG" '\(.*\)_\(BRANCH\|TWIG\|REL\)_.*'` ++ TAG=`echo $TAG | sed -e "s%^$branch_name%D11%"` ++ ++ # Split the tag into an array on underbar or whitespace boundaries. ++ IFS="_ " tag=(${TAG}) ++ unset IFS ++ ++ tagged=1 ++ if [ ${#tag[*]} -eq 0 ]; then ++ tag=(`date '+TOT REL %Y %m %d 0 %y'`); ++ # reconstruct a TAG from the date ++ TAG=${tag[0]}_${tag[1]}_${tag[2]}_${tag[3]}_${tag[4]}_${tag[5]} ++ tagged=0 ++ fi ++ ++ # Allow environment variable to override values. ++ # Missing values default to 0 ++ # ++ maj=${EPI_MAJOR_VERSION:-${tag[2]:-0}} ++ min=${EPI_MINOR_VERSION:-${tag[3]:-0}} ++ rcnum=${EPI_RC_NUMBER:-${tag[4]:-0}} ++ ++ # If increment field is 0, set it to date suffix if on TOB ++ if [ -n "$branchtag" ]; then ++ [ "${tag[5]:-0}" -eq 0 ] && echo "Using date suffix for incr" ++ today=`date '+%Y%m%d'` ++ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-${today:-0}}} ++ else ++ incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} ++ fi ++ origincr=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} ++ build=${EPI_BUILD_NUMBER:-0} ++ ++ # Strip 'RC' from front of rcnum if present ++ rcnum=${rcnum/#RC/} ++ ++ # strip leading zero off the number (otherwise they look like octal) ++ maj=${maj/#0/} ++ min=${min/#0/} ++ rcnum=${rcnum/#0/} ++ incremental=${incremental/#0/} ++ origincr=${origincr/#0/} ++ build=${build/#0/} ++ ++ # some numbers may now be null. replace with with zero. ++ maj=${maj:-0} ++ min=${min:-0} ++ ++ rcnum=${rcnum:-0} ++ incremental=${incremental:-0} ++ origincr=${origincr:-0} ++ build=${build:-0} ++ ++ if [ ${tagged} -eq 1 ]; then ++ # vernum is 32chars max ++ vernum=`printf "0x%02x%02x%02x%02x" ${maj} ${min} ${rcnum} ${origincr}` ++ else ++ vernum=`printf "0x00%02x%02x%02x" ${tag[7]} ${min} ${rcnum}` ++ fi ++ ++ # make sure the size of vernum is under 32 bits. ++ # Otherwise, truncate. The string will keep full information. ++ vernum=${vernum:0:10} ++ ++ # build the string directly from the tag, irrespective of its length ++ # remove the name , the tag type, then replace all _ by . ++ tag_ver_str=${TAG/${tag[0]}_} ++ tag_ver_str=${tag_ver_str/${tag[1]}_} ++ tag_ver_str=${tag_ver_str//_/.} ++ ++ # record tag type ++ tagtype= ++ ++ if [ "${tag[1]}" = "BRANCH" -o "${tag[1]}" = "TWIG" ]; then ++ tagtype=" (TOB)" ++ echo "tag type: $tagtype" ++ fi ++ ++ echo "Effective version string: $tag_ver_str" ++ ++ if [ "$(uname -s)" == "Darwin" ]; then ++ # Mac does not like 2-digit numbers so convert the number to single ++ # digit. 5.100 becomes 5.1 ++ if [ $min -gt 99 ]; then ++ minmac=`expr $min / 100` ++ else ++ minmac=$min ++ fi ++ epi_ver_dev="${maj}.${minmac}.0" ++ else ++ epi_ver_dev="${maj}.${min}.${rcnum}" ++ fi ++ ++ # Finally get version control revision number of (if any) ++ vc_version_num=$($svncmd info ${SRCBASE} 2> $NULL | awk -F': ' '/^Revision: /{printf "%s", $2}') ++ ++ # OK, go do it ++ echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}" ++ ++ sed \ ++ -e "s;@EPI_MAJOR_VERSION@;${maj};" \ ++ -e "s;@EPI_MINOR_VERSION@;${min};" \ ++ -e "s;@EPI_RC_NUMBER@;${rcnum};" \ ++ -e "s;@EPI_INCREMENTAL_NUMBER@;${incremental};" \ ++ -e "s;@EPI_BUILD_NUMBER@;${build};" \ ++ -e "s;@EPI_VERSION@;${maj}, ${min}, ${rcnum}, ${incremental};" \ ++ -e "s;@EPI_VERSION_STR@;${tag_ver_str};" \ ++ -e "s;@EPI_VERSION_TYPE@;${tagtype};" \ ++ -e "s;@VERSION_TYPE@;${tagtype};" \ ++ -e "s;@EPI_VERSION_NUM@;${vernum};" \ ++ -e "s;@EPI_VERSION_DEV@;${epi_ver_dev};" \ ++ -e "s;@VC_VERSION_NUM@;r${vc_version_num};" \ ++ < epivers.h.in > epivers.h ++ ++ # In shared workspaces across different platforms, ensure that ++ # windows generated file is made platform neutral without CRLF ++ if uname -s | egrep -i -q "cygwin"; then ++ dos2unix epivers.h > $NULL 2>&1 ++ fi ++fi # epivers.h +diff --git a/drivers/bcmdrivers/gmac/src/include/etioctl.h b/drivers/bcmdrivers/gmac/src/include/etioctl.h +new file mode 100755 +index 0000000..2fbddf9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/etioctl.h +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM44XX Ethernet Windows device driver custom OID definitions. ++ * ++ * $Id: etioctl.h 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#ifndef _etioctl_h_ ++#define _etioctl_h_ ++ ++/* ++ * Minor kludge alert: ++ * Duplicate a few definitions that irelay requires from epiioctl.h here ++ * so caller doesn't have to include this file and epiioctl.h . ++ * If this grows any more, it would be time to move these irelay-specific ++ * definitions out of the epiioctl.h and into a separate driver common file. ++ */ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* common ioctl definitions */ ++#define ETCUP 0 ++#define ETCDOWN 1 ++#define ETCLOOP 2 ++#define ETCDUMP 3 ++#define ETCSETMSGLEVEL 4 ++#define ETCPROMISC 5 ++#define ETCVAR 6 ++#define ETCSPEED 7 ++#define ETCPHYRD 9 ++#define ETCPHYWR 10 ++#define ETCQOS 11 ++#define ETCPHYRD2 12 ++#define ETCPHYWR2 13 ++#define ETCROBORD 14 ++#define ETCROBOWR 15 ++ ++/* ++ * A set of iovars defined for ET set/get ++ */ ++#define IOV_ET_POWER_SAVE_MODE 1 ++#define IOV_ET_CLEAR_DUMP 2 ++#define IOV_ET_ROBO_DEVID 3 ++#define IOV_PKTC 4 ++#define IOV_PKTCBND 5 ++#define IOV_COUNTERS 6 ++#define IOV_DUMP_CTF 7 ++ ++#if defined(linux) || defined(__ECOS) ++#define SIOCSETCUP (SIOCDEVPRIVATE + ETCUP) ++#define SIOCSETCDOWN (SIOCDEVPRIVATE + ETCDOWN) ++#define SIOCSETCLOOP (SIOCDEVPRIVATE + ETCLOOP) ++#define SIOCGETCDUMP (SIOCDEVPRIVATE + ETCDUMP) ++#define SIOCSETCSETMSGLEVEL (SIOCDEVPRIVATE + ETCSETMSGLEVEL) ++#define SIOCSETCPROMISC (SIOCDEVPRIVATE + ETCPROMISC) ++#define SIOCSETGETVAR (SIOCDEVPRIVATE + ETCVAR) ++#define SIOCSETCSPEED (SIOCDEVPRIVATE + ETCSPEED) ++#define SIOCTXGEN (SIOCDEVPRIVATE + 8) ++#define SIOCGETCPHYRD (SIOCDEVPRIVATE + ETCPHYRD) ++#define SIOCSETCPHYWR (SIOCDEVPRIVATE + ETCPHYWR) ++#define SIOCSETCQOS (SIOCDEVPRIVATE + ETCQOS) ++#define SIOCGETCPHYRD2 (SIOCDEVPRIVATE + ETCPHYRD2) ++#define SIOCSETCPHYWR2 (SIOCDEVPRIVATE + ETCPHYWR2) ++#define SIOCGETCROBORD (SIOCDEVPRIVATE + ETCROBORD) ++#define SIOCSETCROBOWR (SIOCDEVPRIVATE + ETCROBOWR) ++ ++/* structure to send a generic var set/get */ ++typedef struct et_var_s { ++ uint cmd; ++ uint set; ++ void *buf; ++ uint len; ++} et_var_t; ++ ++/* arg to SIOCTXGEN */ ++struct txg { ++ uint32 num; /* number of frames to send */ ++ uint32 delay; /* delay in microseconds between sending each */ ++ uint32 size; /* size of ether frame to send */ ++ uchar buf[1514]; /* starting ether frame data */ ++}; ++#endif /* linux */ ++ ++ ++#if defined(__NetBSD__) ++#define SIOCSETCUP _IOW('e', 0, struct ifreq) ++#define SIOCSETCDOWN _IOW('e', 1, struct ifreq) ++#define SIOCSETCLOOP _IOW('e', 2, struct ifreq) ++#define SIOCGETCDUMP _IOWR('e', 3, struct ifreq) ++#define SIOCSETCSETMSGLEVEL _IOW('e', 4, struct ifreq) ++#define SIOCSETCPROMISC _IOW('e', 5, struct ifreq) ++#define SIOCSETCTXDOWN _IOW('e', 6, struct ifreq) /* obsolete */ ++#define SIOCSETCSPEED _IOW('e', 7, struct ifreq) ++#define SIOCTXGEN _IOW('e', 8, struct ifreq) ++#define SIOCGETCPHYRD _IOWR('e', 9, struct ifreq) ++#define SIOCSETCPHYWR _IOW('e', 10, struct ifreq) ++#define SIOCSETCQOS _IOW('e', 11, struct ifreq) ++#define SIOCGETCPHYRD2 _IOWR('e', 12, struct ifreq) ++#define SIOCSETCPHYWR2 _IOW('e', 13, struct ifreq) ++#define SIOCGETCROBORD _IOWR('e', 14, struct ifreq) ++#define SIOCSETCROBOWR _IOW('e', 15, struct ifreq) ++ ++/* arg to SIOCTXGEN */ ++struct txg { ++ uint32 num; /* number of frames to send */ ++ uint32 delay; /* delay in microseconds between sending each */ ++ uint32 size; /* size of ether frame to send */ ++ uchar buf[1514]; /* starting ether frame data */ ++}; ++#endif /* __NetBSD__ */ ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++#define ET_OID_BASE 0xFFE41400 /* OID Base for ET */ ++ ++#define OID_ET_UP (ET_OID_BASE + ETCUP) ++#define OID_ET_DOWN (ET_OID_BASE + ETCDOWN) ++#define OID_ET_LOOP (ET_OID_BASE + ETCLOOP) ++#define OID_ET_DUMP (ET_OID_BASE + ETCDUMP) ++#define OID_ET_SETMSGLEVEL (ET_OID_BASE + ETCSETMSGLEVEL) ++#define OID_ET_PROMISC (ET_OID_BASE + ETCPROMISC) ++#define OID_ET_TXDOWN (ET_OID_BASE + 6) ++#define OID_ET_SPEED (ET_OID_BASE + ETCSPEED) ++#define OID_ET_GETINSTANCE (ET_OID_BASE + 8) ++#define OID_ET_SETCALLBACK (ET_OID_BASE + 9) ++#define OID_ET_UNSETCALLBACK (ET_OID_BASE + 10) ++ ++#define IS_ET_OID(oid) (((oid) & 0xFFFFFF00) == 0xFFE41400) ++ ++#define ET_ISQUERYOID(oid) ((oid == OID_ET_DUMP) || (oid == OID_ET_GETINSTANCE)) ++ ++/* OID_ET_SETCALLBACK data type */ ++typedef struct et_cb { ++ void (*fn)(void *, int); /* Callback function */ ++ void *context; /* Passed to callback function */ ++} et_cb_t; ++ ++#endif /* _etioctl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/gmac_common.h b/drivers/bcmdrivers/gmac/src/include/gmac_common.h +new file mode 100755 +index 0000000..145e587 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/gmac_common.h +@@ -0,0 +1,560 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * gmacdefs - Broadcom gmac (Unimac) specific definitions ++ * ++ * $Id: gmac_common.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _gmac_common_core_h_ ++#define _gmac_common_core_h_ ++ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD XSTR(__LINE__) ++#endif ++ ++typedef volatile struct _gmac_commonregs { ++ uint32 stag0; ++ uint32 stag1; ++ uint32 stag2; ++ uint32 stag3; ++ uint32 PAD[4]; ++ uint32 parsercontrol; ++ uint32 mib_max_len; ++ uint32 PAD[54]; ++ uint32 phyaccess; ++ uint32 phycontrol; ++ uint32 PAD[2]; ++ uint32 gmac0_rgmii_cntl; ++ uint32 PAD[59]; ++ uint32 cfp_access; ++ uint32 PAD[3]; ++ uint32 cfp_tcam_data0; ++ uint32 cfp_tcam_data1; ++ uint32 cfp_tcam_data2; ++ uint32 cfp_tcam_data3; ++ uint32 cfp_tcam_data4; ++ uint32 cfp_tcam_data5; ++ uint32 cfp_tcam_data6; ++ uint32 cfp_tcam_data7; ++ uint32 cfp_tcam_mask0; ++ uint32 cfp_tcam_mask1; ++ uint32 cfp_tcam_mask2; ++ uint32 cfp_tcam_mask3; ++ uint32 cfp_tcam_mask4; ++ uint32 cfp_tcam_mask5; ++ uint32 cfp_tcam_mask6; ++ uint32 cfp_tcam_mask7; ++ uint32 cfp_action_data; ++ uint32 PAD[19]; ++ uint32 tcam_bist_cntl; ++ uint32 tcam_bist_status; ++ uint32 tcam_cmp_status; ++ uint32 tcam_disable; ++ uint32 PAD[16]; ++ uint32 tcam_test_cntl; ++ uint32 PAD[3]; ++ uint32 udf_0_a3_a0; ++ uint32 udf_0_a7_a4; ++ uint32 udf_0_a8; ++ uint32 PAD[1]; ++ uint32 udf_1_a3_a0; ++ uint32 udf_1_a7_a4; ++ uint32 udf_1_a8; ++ uint32 PAD[1]; ++ uint32 udf_2_a3_a0; ++ uint32 udf_2_a7_a4; ++ uint32 udf_2_a8; ++ uint32 PAD[1]; ++ uint32 udf_0_b3_b0; ++ uint32 udf_0_b7_b4; ++ uint32 udf_0_b8; ++ uint32 PAD[1]; ++ uint32 udf_1_b3_b0; ++ uint32 udf_1_b7_b4; ++ uint32 udf_1_b8; ++ uint32 PAD[1]; ++ uint32 udf_2_b3_b0; ++ uint32 udf_2_b7_b4; ++ uint32 udf_2_b8; ++ uint32 PAD[1]; ++ uint32 udf_0_c3_c0; ++ uint32 udf_0_c7_c4; ++ uint32 udf_0_c8; ++ uint32 PAD[1]; ++ uint32 udf_1_c3_c0; ++ uint32 udf_1_c7_c4; ++ uint32 udf_1_c8; ++ uint32 PAD[1]; ++ uint32 udf_2_c3_c0; ++ uint32 udf_2_c7_c4; ++ uint32 udf_2_c8; ++ uint32 PAD[1]; ++ uint32 udf_0_d3_d0; ++ uint32 udf_0_d7_d4; ++ uint32 udf_0_d11_d8; ++} gmac_commonregs_t; ++ ++/* stag0 offset0x0 */ ++#define STAG0_TPID_SHIFT 0 ++#define STAG0_TPID_MASK 0xffff ++ ++/* stag1 offset0x4 */ ++#define STAG1_TPID_SHIFT 0 ++#define STAG1_TPID_MASK 0xffff ++ ++/* stag2 offset0x8 */ ++#define STAG2_TPID_SHIFT 0 ++#define STAG2_TPID_MASK 0xffff ++ ++/* stag3 offset0xc */ ++#define STAG3_TPID_SHIFT 0 ++#define STAG3_TPID_MASK 0xffff ++ ++/* parsercontrol offset0x20 */ ++#define PARSERCONTROL_MAX_PARSER_LEN_TH_SHIFT 0 ++#define PARSERCONTROL_MAX_PARSER_LEN_TH_MASK 0x3fff ++ ++/* mib_max_len offset0x24 */ ++#define MIB_MAX_LEN_MIB_MAX_LEN_SHIFT 0 ++#define MIB_MAX_LEN_MIB_MAX_LEN_MASK 0x3fff ++ ++/* phyaccess offset0x100 */ ++#define PHYACCESS_TRIGGER_SHIFT 30 ++#define PHYACCESS_TRIGGER_MASK 0x40000000 ++#define PHYACCESS_WR_CMD_SHIFT 29 ++#define PHYACCESS_WR_CMD_MASK 0x20000000 ++#define PHYACCESS_CPU_REG_ADDR_SHIFT 24 ++#define PHYACCESS_CPU_REG_ADDR_MASK 0x1f000000 ++#define PHYACCESS_CPU_PHY_ADDR_SHIFT 16 ++#define PHYACCESS_CPU_PHY_ADDR_MASK 0x1f0000 ++#define PHYACCESS_ACC_DATA_SHIFT 0 ++#define PHYACCESS_ACC_DATA_MASK 0xffff ++ ++/* phycontrol offset0x104 */ ++#define PHYCONTROL_SD_ACCESS_EN_SHIFT 25 ++#define PHYCONTROL_SD_ACCESS_EN_MASK 0x2000000 ++#define PHYCONTROL_NWAY_AUTO_POLLING_EN_SHIFT 24 ++#define PHYCONTROL_NWAY_AUTO_POLLING_EN_MASK 0x1000000 ++#define PHYCONTROL_MDC_TRANSITION_EN_SHIFT 23 ++#define PHYCONTROL_MDC_TRANSITION_EN_MASK 0x800000 ++#define PHYCONTROL_MDC_CYCLE_TH_SHIFT 16 ++#define PHYCONTROL_MDC_CYCLE_TH_MASK 0x7f0000 ++#define PHYCONTROL_EXT_PHY_ADDR_SHIFT 0 ++#define PHYCONTROL_EXT_PHY_ADDR_MASK 0x1f ++ ++/* gmac0_rgmii_cntl offset0x110 */ ++#define GMAC0_RGMII_CNTL_TIMING_SEL_SHIFT 0 ++#define GMAC0_RGMII_CNTL_TIMING_SEL_MASK 0x1 ++#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_SHIFT 1 ++#define GMAC0_RGMII_CNTL_RGMII_DLL_RXC_BYPASS_MASK 0x2 ++#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_SHIFT 2 ++#define GMAC0_RGMII_CNTL_BYPASS_2NS_DEL_MASK 0x4 ++#define GMAC0_RGMII_CNTL_DEL_STRB_SHIFT 3 ++#define GMAC0_RGMII_CNTL_DEL_STRB_MASK 0x8 ++#define GMAC0_RGMII_CNTL_DEL_VALUE_SHIFT 4 ++#define GMAC0_RGMII_CNTL_DEL_VALUE_MASK 0x70 ++#define GMAC0_RGMII_CNTL_DEL_ADDR_SHIFT 7 ++#define GMAC0_RGMII_CNTL_DEL_ADDR_MASK 0x780 ++ ++/* cfp_access offset0x200 */ ++#define CFP_ACCESS_OP_START_DONE_SHIFT 0 ++#define CFP_ACCESS_OP_START_DONE_MASK 0x1 ++#define CFP_ACCESS_OP_SEL_SHIFT 1 ++#define CFP_ACCESS_OP_SEL_MASK 0xe ++#define CFP_ACCESS_CFP_RAM_CLEAR_SHIFT 4 ++#define CFP_ACCESS_CFP_RAM_CLEAR_MASK 0x10 ++#define CFP_ACCESS_RESERVED1_SHIFT 5 ++#define CFP_ACCESS_RESERVED1_MASK 0x3e0 ++#define CFP_ACCESS_RAM_SEL_SHIFT 10 ++#define CFP_ACCESS_RAM_SEL_MASK 0x7c00 ++#define CFP_ACCESS_TCAM_RESET_SHIFT 15 ++#define CFP_ACCESS_TCAM_RESET_MASK 0x8000 ++#define CFP_ACCESS_XCESS_ADDR_SHIFT 16 ++#define CFP_ACCESS_XCESS_ADDR_MASK 0x1ff0000 ++#define CFP_ACCESS_RESERVED0_SHIFT 25 ++#define CFP_ACCESS_RESERVED0_MASK 0xe000000 ++#define CFP_ACCESS_RD_STATUS_SHIFT 28 ++#define CFP_ACCESS_RD_STATUS_MASK 0xf0000000 ++ ++/* cfp_tcam_data0 offset0x210 */ ++#define CFP_TCAM_DATA0_DATA_SHIFT 0 ++#define CFP_TCAM_DATA0_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data1 offset0x214 */ ++#define CFP_TCAM_DATA1_DATA_SHIFT 0 ++#define CFP_TCAM_DATA1_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data2 offset0x218 */ ++#define CFP_TCAM_DATA2_DATA_SHIFT 0 ++#define CFP_TCAM_DATA2_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data3 offset0x21c */ ++#define CFP_TCAM_DATA3_DATA_SHIFT 0 ++#define CFP_TCAM_DATA3_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data4 offset0x220 */ ++#define CFP_TCAM_DATA4_DATA_SHIFT 0 ++#define CFP_TCAM_DATA4_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data5 offset0x224 */ ++#define CFP_TCAM_DATA5_DATA_SHIFT 0 ++#define CFP_TCAM_DATA5_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data6 offset0x228 */ ++#define CFP_TCAM_DATA6_DATA_SHIFT 0 ++#define CFP_TCAM_DATA6_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_data7 offset0x22c */ ++#define CFP_TCAM_DATA7_DATA_SHIFT 0 ++#define CFP_TCAM_DATA7_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask0 offset0x230 */ ++#define CFP_TCAM_MASK0_DATA_SHIFT 0 ++#define CFP_TCAM_MASK0_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask1 offset0x234 */ ++#define CFP_TCAM_MASK1_DATA_SHIFT 0 ++#define CFP_TCAM_MASK1_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask2 offset0x238 */ ++#define CFP_TCAM_MASK2_DATA_SHIFT 0 ++#define CFP_TCAM_MASK2_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask3 offset0x23c */ ++#define CFP_TCAM_MASK3_DATA_SHIFT 0 ++#define CFP_TCAM_MASK3_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask4 offset0x240 */ ++#define CFP_TCAM_MASK4_DATA_SHIFT 0 ++#define CFP_TCAM_MASK4_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask5 offset0x244 */ ++#define CFP_TCAM_MASK5_DATA_SHIFT 0 ++#define CFP_TCAM_MASK5_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask6 offset0x248 */ ++#define CFP_TCAM_MASK6_DATA_SHIFT 0 ++#define CFP_TCAM_MASK6_DATA_MASK 0xffffffff ++ ++/* cfp_tcam_mask7 offset0x24c */ ++#define CFP_TCAM_MASK7_DATA_SHIFT 0 ++#define CFP_TCAM_MASK7_DATA_MASK 0xffffffff ++ ++/* cfp_action_data offset0x250 */ ++#define CFP_ACTION_DATA_CHAINID_SHIFT 0 ++#define CFP_ACTION_DATA_CHAINID_MASK 0xff ++#define CFP_ACTION_DATA_CHANNELID_SHIFT 8 ++#define CFP_ACTION_DATA_CHANNELID_MASK 0xf00 ++#define CFP_ACTION_DATA_DROP_SHIFT 12 ++#define CFP_ACTION_DATA_DROP_MASK 0x1000 ++#define CFP_ACTION_DATA_RESERVED_SHIFT 13 ++#define CFP_ACTION_DATA_RESERVED_MASK 0xffffe000 ++ ++/* tcam_bist_cntl offset0x2a0 */ ++#define TCAM_BIST_CNTL_TCAM_BIST_EN_SHIFT 0 ++#define TCAM_BIST_CNTL_TCAM_BIST_EN_MASK 0x1 ++#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_SHIFT 1 ++#define TCAM_BIST_CNTL_TCAM_BIST_TCAM_SEL_MASK 0x6 ++#define TCAM_BIST_CNTL_RESERVED1_SHIFT 3 ++#define TCAM_BIST_CNTL_RESERVED1_MASK 0x8 ++#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_SHIFT 4 ++#define TCAM_BIST_CNTL_TCAM_BIST_STATUS_SEL_MASK 0xf0 ++#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_SHIFT 8 ++#define TCAM_BIST_CNTL_TCAM_BIST_SKIP_ERR_CNT_MASK 0xff00 ++#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_SHIFT 16 ++#define TCAM_BIST_CNTL_TCAM_TEST_COMPARE_MASK 0x10000 ++#define TCAM_BIST_CNTL_RESERVED_SHIFT 17 ++#define TCAM_BIST_CNTL_RESERVED_MASK 0x7ffe0000 ++#define TCAM_BIST_CNTL_TCAM_BIST_DONE_SHIFT 31 ++#define TCAM_BIST_CNTL_TCAM_BIST_DONE_MASK 0x80000000 ++ ++/* tcam_bist_status offset0x2a4 */ ++#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_SHIFT 0 ++#define TCAM_BIST_STATUS_TCAM_BIST_STATUS_MASK 0xffff ++#define TCAM_BIST_STATUS_RESERVED_SHIFT 16 ++#define TCAM_BIST_STATUS_RESERVED_MASK 0xffff0000 ++ ++/* tcam_cmp_status offset0x2a8 */ ++#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_SHIFT 0 ++#define TCAM_CMP_STATUS_TCAM_HIT_ADDR_MASK 0x1ff ++#define TCAM_CMP_STATUS_RESERVED2_SHIFT 9 ++#define TCAM_CMP_STATUS_RESERVED2_MASK 0x7e00 ++#define TCAM_CMP_STATUS_TCAM_HIT_SHIFT 15 ++#define TCAM_CMP_STATUS_TCAM_HIT_MASK 0x8000 ++#define TCAM_CMP_STATUS_RESERVED1_SHIFT 16 ++#define TCAM_CMP_STATUS_RESERVED1_MASK 0xffff0000 ++ ++/* tcam_disable offset0x2ac */ ++#define TCAM_DISABLE_TCAM_DISABLE_SHIFT 0 ++#define TCAM_DISABLE_TCAM_DISABLE_MASK 0xf ++#define TCAM_DISABLE_RESERVED_SHIFT 4 ++#define TCAM_DISABLE_RESERVED_MASK 0xfffffff0 ++ ++/* tcam_test_cntl offset0x2f0 */ ++#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_SHIFT 0 ++#define TCAM_TEST_CNTL_TCAM_TEST_CNTL_MASK 0x7ff ++#define TCAM_TEST_CNTL_RESERVED_SHIFT 11 ++#define TCAM_TEST_CNTL_RESERVED_MASK 0xfffff800 ++ ++/* udf_0_a3_a0 offset0x300 */ ++#define UDF_0_A3_A0_CFG_UDF_0_A0_SHIFT 0 ++#define UDF_0_A3_A0_CFG_UDF_0_A0_MASK 0xff ++#define UDF_0_A3_A0_CFG_UDF_0_A1_SHIFT 8 ++#define UDF_0_A3_A0_CFG_UDF_0_A1_MASK 0xff00 ++#define UDF_0_A3_A0_CFG_UDF_0_A2_SHIFT 16 ++#define UDF_0_A3_A0_CFG_UDF_0_A2_MASK 0xff0000 ++#define UDF_0_A3_A0_CFG_UDF_0_A3_SHIFT 24 ++#define UDF_0_A3_A0_CFG_UDF_0_A3_MASK 0xff000000 ++ ++/* udf_0_a7_a4 offset0x304 */ ++#define UDF_0_A7_A4_CFG_UDF_0_A4_SHIFT 0 ++#define UDF_0_A7_A4_CFG_UDF_0_A4_MASK 0xff ++#define UDF_0_A7_A4_CFG_UDF_0_A5_SHIFT 8 ++#define UDF_0_A7_A4_CFG_UDF_0_A5_MASK 0xff00 ++#define UDF_0_A7_A4_CFG_UDF_0_A6_SHIFT 16 ++#define UDF_0_A7_A4_CFG_UDF_0_A6_MASK 0xff0000 ++#define UDF_0_A7_A4_CFG_UDF_0_A7_SHIFT 24 ++#define UDF_0_A7_A4_CFG_UDF_0_A7_MASK 0xff000000 ++ ++/* udf_0_a8 offset0x308 */ ++#define UDF_0_A8_CFG_UDF_0_A8_SHIFT 0 ++#define UDF_0_A8_CFG_UDF_0_A8_MASK 0xff ++ ++/* udf_1_a3_a0 offset0x310 */ ++#define UDF_1_A3_A0_CFG_UDF_1_A0_SHIFT 0 ++#define UDF_1_A3_A0_CFG_UDF_1_A0_MASK 0xff ++#define UDF_1_A3_A0_CFG_UDF_1_A1_SHIFT 8 ++#define UDF_1_A3_A0_CFG_UDF_1_A1_MASK 0xff00 ++#define UDF_1_A3_A0_CFG_UDF_1_A2_SHIFT 16 ++#define UDF_1_A3_A0_CFG_UDF_1_A2_MASK 0xff0000 ++#define UDF_1_A3_A0_CFG_UDF_1_A3_SHIFT 24 ++#define UDF_1_A3_A0_CFG_UDF_1_A3_MASK 0xff000000 ++ ++/* udf_1_a7_a4 offset0x314 */ ++#define UDF_1_A7_A4_CFG_UDF_1_A4_SHIFT 0 ++#define UDF_1_A7_A4_CFG_UDF_1_A4_MASK 0xff ++#define UDF_1_A7_A4_CFG_UDF_1_A5_SHIFT 8 ++#define UDF_1_A7_A4_CFG_UDF_1_A5_MASK 0xff00 ++#define UDF_1_A7_A4_CFG_UDF_1_A6_SHIFT 16 ++#define UDF_1_A7_A4_CFG_UDF_1_A6_MASK 0xff0000 ++#define UDF_1_A7_A4_CFG_UDF_1_A7_SHIFT 24 ++#define UDF_1_A7_A4_CFG_UDF_1_A7_MASK 0xff000000 ++ ++/* udf_1_a8 offset0x318 */ ++#define UDF_1_A8_CFG_UDF_1_A8_SHIFT 0 ++#define UDF_1_A8_CFG_UDF_1_A8_MASK 0xff ++ ++/* udf_2_a3_a0 offset0x320 */ ++#define UDF_2_A3_A0_CFG_UDF_2_A0_SHIFT 0 ++#define UDF_2_A3_A0_CFG_UDF_2_A0_MASK 0xff ++#define UDF_2_A3_A0_CFG_UDF_2_A1_SHIFT 8 ++#define UDF_2_A3_A0_CFG_UDF_2_A1_MASK 0xff00 ++#define UDF_2_A3_A0_CFG_UDF_2_A2_SHIFT 16 ++#define UDF_2_A3_A0_CFG_UDF_2_A2_MASK 0xff0000 ++#define UDF_2_A3_A0_CFG_UDF_2_A3_SHIFT 24 ++#define UDF_2_A3_A0_CFG_UDF_2_A3_MASK 0xff000000 ++ ++/* udf_2_a7_a4 offset0x324 */ ++#define UDF_2_A7_A4_CFG_UDF_2_A4_SHIFT 0 ++#define UDF_2_A7_A4_CFG_UDF_2_A4_MASK 0xff ++#define UDF_2_A7_A4_CFG_UDF_2_A5_SHIFT 8 ++#define UDF_2_A7_A4_CFG_UDF_2_A5_MASK 0xff00 ++#define UDF_2_A7_A4_CFG_UDF_2_A6_SHIFT 16 ++#define UDF_2_A7_A4_CFG_UDF_2_A6_MASK 0xff0000 ++#define UDF_2_A7_A4_CFG_UDF_2_A7_SHIFT 24 ++#define UDF_2_A7_A4_CFG_UDF_2_A7_MASK 0xff000000 ++ ++/* udf_2_a8 offset0x328 */ ++#define UDF_2_A8_CFG_UDF_2_A8_SHIFT 0 ++#define UDF_2_A8_CFG_UDF_2_A8_MASK 0xff ++ ++/* udf_0_b3_b0 offset0x330 */ ++#define UDF_0_B3_B0_CFG_UDF_0_B0_SHIFT 0 ++#define UDF_0_B3_B0_CFG_UDF_0_B0_MASK 0xff ++#define UDF_0_B3_B0_CFG_UDF_0_B1_SHIFT 8 ++#define UDF_0_B3_B0_CFG_UDF_0_B1_MASK 0xff00 ++#define UDF_0_B3_B0_CFG_UDF_0_B2_SHIFT 16 ++#define UDF_0_B3_B0_CFG_UDF_0_B2_MASK 0xff0000 ++#define UDF_0_B3_B0_CFG_UDF_0_B3_SHIFT 24 ++#define UDF_0_B3_B0_CFG_UDF_0_B3_MASK 0xff000000 ++ ++/* udf_0_b7_b4 offset0x334 */ ++#define UDF_0_B7_B4_CFG_UDF_0_B4_SHIFT 0 ++#define UDF_0_B7_B4_CFG_UDF_0_B4_MASK 0xff ++#define UDF_0_B7_B4_CFG_UDF_0_B5_SHIFT 8 ++#define UDF_0_B7_B4_CFG_UDF_0_B5_MASK 0xff00 ++#define UDF_0_B7_B4_CFG_UDF_0_B6_SHIFT 16 ++#define UDF_0_B7_B4_CFG_UDF_0_B6_MASK 0xff0000 ++#define UDF_0_B7_B4_CFG_UDF_0_B7_SHIFT 24 ++#define UDF_0_B7_B4_CFG_UDF_0_B7_MASK 0xff000000 ++ ++/* udf_0_b8 offset0x338 */ ++#define UDF_0_B8_CFG_UDF_0_B8_SHIFT 0 ++#define UDF_0_B8_CFG_UDF_0_B8_MASK 0xff ++ ++/* udf_1_b3_b0 offset0x340 */ ++#define UDF_1_B3_B0_CFG_UDF_1_B0_SHIFT 0 ++#define UDF_1_B3_B0_CFG_UDF_1_B0_MASK 0xff ++#define UDF_1_B3_B0_CFG_UDF_1_B1_SHIFT 8 ++#define UDF_1_B3_B0_CFG_UDF_1_B1_MASK 0xff00 ++#define UDF_1_B3_B0_CFG_UDF_1_B2_SHIFT 16 ++#define UDF_1_B3_B0_CFG_UDF_1_B2_MASK 0xff0000 ++#define UDF_1_B3_B0_CFG_UDF_1_B3_SHIFT 24 ++#define UDF_1_B3_B0_CFG_UDF_1_B3_MASK 0xff000000 ++ ++/* udf_1_b7_b4 offset0x344 */ ++#define UDF_1_B7_B4_CFG_UDF_1_B4_SHIFT 0 ++#define UDF_1_B7_B4_CFG_UDF_1_B4_MASK 0xff ++#define UDF_1_B7_B4_CFG_UDF_1_B5_SHIFT 8 ++#define UDF_1_B7_B4_CFG_UDF_1_B5_MASK 0xff00 ++#define UDF_1_B7_B4_CFG_UDF_1_B6_SHIFT 16 ++#define UDF_1_B7_B4_CFG_UDF_1_B6_MASK 0xff0000 ++#define UDF_1_B7_B4_CFG_UDF_1_B7_SHIFT 24 ++#define UDF_1_B7_B4_CFG_UDF_1_B7_MASK 0xff000000 ++ ++/* udf_1_b8 offset0x348 */ ++#define UDF_1_B8_CFG_UDF_1_B8_SHIFT 0 ++#define UDF_1_B8_CFG_UDF_1_B8_MASK 0xff ++ ++/* udf_2_b3_b0 offset0x350 */ ++#define UDF_2_B3_B0_CFG_UDF_2_B0_SHIFT 0 ++#define UDF_2_B3_B0_CFG_UDF_2_B0_MASK 0xff ++#define UDF_2_B3_B0_CFG_UDF_2_B1_SHIFT 8 ++#define UDF_2_B3_B0_CFG_UDF_2_B1_MASK 0xff00 ++#define UDF_2_B3_B0_CFG_UDF_2_B2_SHIFT 16 ++#define UDF_2_B3_B0_CFG_UDF_2_B2_MASK 0xff0000 ++#define UDF_2_B3_B0_CFG_UDF_2_B3_SHIFT 24 ++#define UDF_2_B3_B0_CFG_UDF_2_B3_MASK 0xff000000 ++ ++/* udf_2_b7_b4 offset0x354 */ ++#define UDF_2_B7_B4_CFG_UDF_2_B4_SHIFT 0 ++#define UDF_2_B7_B4_CFG_UDF_2_B4_MASK 0xff ++#define UDF_2_B7_B4_CFG_UDF_2_B5_SHIFT 8 ++#define UDF_2_B7_B4_CFG_UDF_2_B5_MASK 0xff00 ++#define UDF_2_B7_B4_CFG_UDF_2_B6_SHIFT 16 ++#define UDF_2_B7_B4_CFG_UDF_2_B6_MASK 0xff0000 ++#define UDF_2_B7_B4_CFG_UDF_2_B7_SHIFT 24 ++#define UDF_2_B7_B4_CFG_UDF_2_B7_MASK 0xff000000 ++ ++/* udf_2_b8 offset0x358 */ ++#define UDF_2_B8_CFG_UDF_2_B8_SHIFT 0 ++#define UDF_2_B8_CFG_UDF_2_B8_MASK 0xff ++ ++/* udf_0_c3_c0 offset0x360 */ ++#define UDF_0_C3_C0_CFG_UDF_0_C0_SHIFT 0 ++#define UDF_0_C3_C0_CFG_UDF_0_C0_MASK 0xff ++#define UDF_0_C3_C0_CFG_UDF_0_C1_SHIFT 8 ++#define UDF_0_C3_C0_CFG_UDF_0_C1_MASK 0xff00 ++#define UDF_0_C3_C0_CFG_UDF_0_C2_SHIFT 16 ++#define UDF_0_C3_C0_CFG_UDF_0_C2_MASK 0xff0000 ++#define UDF_0_C3_C0_CFG_UDF_0_C3_SHIFT 24 ++#define UDF_0_C3_C0_CFG_UDF_0_C3_MASK 0xff000000 ++ ++/* udf_0_c7_c4 offset0x364 */ ++#define UDF_0_C7_C4_CFG_UDF_0_C4_SHIFT 0 ++#define UDF_0_C7_C4_CFG_UDF_0_C4_MASK 0xff ++#define UDF_0_C7_C4_CFG_UDF_0_C5_SHIFT 8 ++#define UDF_0_C7_C4_CFG_UDF_0_C5_MASK 0xff00 ++#define UDF_0_C7_C4_CFG_UDF_0_C6_SHIFT 16 ++#define UDF_0_C7_C4_CFG_UDF_0_C6_MASK 0xff0000 ++#define UDF_0_C7_C4_CFG_UDF_0_C7_SHIFT 24 ++#define UDF_0_C7_C4_CFG_UDF_0_C7_MASK 0xff000000 ++ ++/* udf_0_c8 offset0x368 */ ++#define UDF_0_C8_CFG_UDF_0_C8_SHIFT 0 ++#define UDF_0_C8_CFG_UDF_0_C8_MASK 0xff ++ ++/* udf_1_c3_c0 offset0x370 */ ++#define UDF_1_C3_C0_CFG_UDF_1_C0_SHIFT 0 ++#define UDF_1_C3_C0_CFG_UDF_1_C0_MASK 0xff ++#define UDF_1_C3_C0_CFG_UDF_1_C1_SHIFT 8 ++#define UDF_1_C3_C0_CFG_UDF_1_C1_MASK 0xff00 ++#define UDF_1_C3_C0_CFG_UDF_1_C2_SHIFT 16 ++#define UDF_1_C3_C0_CFG_UDF_1_C2_MASK 0xff0000 ++#define UDF_1_C3_C0_CFG_UDF_1_C3_SHIFT 24 ++#define UDF_1_C3_C0_CFG_UDF_1_C3_MASK 0xff000000 ++ ++/* udf_1_c7_c4 offset0x374 */ ++#define UDF_1_C7_C4_CFG_UDF_1_C4_SHIFT 0 ++#define UDF_1_C7_C4_CFG_UDF_1_C4_MASK 0xff ++#define UDF_1_C7_C4_CFG_UDF_1_C5_SHIFT 8 ++#define UDF_1_C7_C4_CFG_UDF_1_C5_MASK 0xff00 ++#define UDF_1_C7_C4_CFG_UDF_1_C6_SHIFT 16 ++#define UDF_1_C7_C4_CFG_UDF_1_C6_MASK 0xff0000 ++#define UDF_1_C7_C4_CFG_UDF_1_C7_SHIFT 24 ++#define UDF_1_C7_C4_CFG_UDF_1_C7_MASK 0xff000000 ++ ++/* udf_1_c8 offset0x378 */ ++#define UDF_1_C8_CFG_UDF_1_C8_SHIFT 0 ++#define UDF_1_C8_CFG_UDF_1_C8_MASK 0xff ++ ++/* udf_2_c3_c0 offset0x380 */ ++#define UDF_2_C3_C0_CFG_UDF_2_C0_SHIFT 0 ++#define UDF_2_C3_C0_CFG_UDF_2_C0_MASK 0xff ++#define UDF_2_C3_C0_CFG_UDF_2_C1_SHIFT 8 ++#define UDF_2_C3_C0_CFG_UDF_2_C1_MASK 0xff00 ++#define UDF_2_C3_C0_CFG_UDF_2_C2_SHIFT 16 ++#define UDF_2_C3_C0_CFG_UDF_2_C2_MASK 0xff0000 ++#define UDF_2_C3_C0_CFG_UDF_2_C3_SHIFT 24 ++#define UDF_2_C3_C0_CFG_UDF_2_C3_MASK 0xff000000 ++ ++/* udf_2_c7_c4 offset0x384 */ ++#define UDF_2_C7_C4_CFG_UDF_2_C4_SHIFT 0 ++#define UDF_2_C7_C4_CFG_UDF_2_C4_MASK 0xff ++#define UDF_2_C7_C4_CFG_UDF_2_C5_SHIFT 8 ++#define UDF_2_C7_C4_CFG_UDF_2_C5_MASK 0xff00 ++#define UDF_2_C7_C4_CFG_UDF_2_C6_SHIFT 16 ++#define UDF_2_C7_C4_CFG_UDF_2_C6_MASK 0xff0000 ++#define UDF_2_C7_C4_CFG_UDF_2_C7_SHIFT 24 ++#define UDF_2_C7_C4_CFG_UDF_2_C7_MASK 0xff000000 ++ ++/* udf_2_c8 offset0x388 */ ++#define UDF_2_C8_CFG_UDF_2_C8_SHIFT 0 ++#define UDF_2_C8_CFG_UDF_2_C8_MASK 0xff ++ ++/* udf_0_d3_d0 offset0x390 */ ++#define UDF_0_D3_D0_CFG_UDF_0_D0_SHIFT 0 ++#define UDF_0_D3_D0_CFG_UDF_0_D0_MASK 0xff ++#define UDF_0_D3_D0_CFG_UDF_0_D1_SHIFT 8 ++#define UDF_0_D3_D0_CFG_UDF_0_D1_MASK 0xff00 ++#define UDF_0_D3_D0_CFG_UDF_0_D2_SHIFT 16 ++#define UDF_0_D3_D0_CFG_UDF_0_D2_MASK 0xff0000 ++#define UDF_0_D3_D0_CFG_UDF_0_D3_SHIFT 24 ++#define UDF_0_D3_D0_CFG_UDF_0_D3_MASK 0xff000000 ++ ++/* udf_0_d7_d4 offset0x394 */ ++#define UDF_0_D7_D4_CFG_UDF_0_D4_SHIFT 0 ++#define UDF_0_D7_D4_CFG_UDF_0_D4_MASK 0xff ++#define UDF_0_D7_D4_CFG_UDF_0_D5_SHIFT 8 ++#define UDF_0_D7_D4_CFG_UDF_0_D5_MASK 0xff00 ++#define UDF_0_D7_D4_CFG_UDF_0_D6_SHIFT 16 ++#define UDF_0_D7_D4_CFG_UDF_0_D6_MASK 0xff0000 ++#define UDF_0_D7_D4_CFG_UDF_0_D7_SHIFT 24 ++#define UDF_0_D7_D4_CFG_UDF_0_D7_MASK 0xff000000 ++ ++/* udf_0_d11_d8 offset0x398 */ ++#define UDF_0_D11_D8_CFG_UDF_0_D8_SHIFT 0 ++#define UDF_0_D11_D8_CFG_UDF_0_D8_MASK 0xff ++#define UDF_0_D11_D8_CFG_UDF_0_D9_SHIFT 8 ++#define UDF_0_D11_D8_CFG_UDF_0_D9_MASK 0xff00 ++#define UDF_0_D11_D8_CFG_UDF_0_D10_SHIFT 16 ++#define UDF_0_D11_D8_CFG_UDF_0_D10_MASK 0xff0000 ++#define UDF_0_D11_D8_CFG_UDF_0_D11_SHIFT 24 ++#define UDF_0_D11_D8_CFG_UDF_0_D11_MASK 0xff000000 ++ ++#endif /* _gmac_common_core_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/gmac_core.h b/drivers/bcmdrivers/gmac/src/include/gmac_core.h +new file mode 100755 +index 0000000..090c327 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/gmac_core.h +@@ -0,0 +1,302 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * gmacdefs - Broadcom gmac (Unimac) specific definitions ++ * ++ * $Id: gmac_core.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _gmac_core_h_ ++#define _gmac_core_h_ ++ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* We have 4 DMA TX channels */ ++#define GMAC_NUM_DMA_TX 4 ++ ++typedef volatile struct { ++ dma64regs_t dmaxmt; /* dma tx */ ++ uint32 PAD[2]; ++ dma64regs_t dmarcv; /* dma rx */ ++ uint32 PAD[2]; ++} dma64_t; ++ ++/* ++ * Host Interface Registers ++ */ ++typedef volatile struct _gmacregs { ++ uint32 devcontrol; /* 0x000 */ ++ uint32 devstatus; /* 0x004 */ ++ uint32 PAD; ++ uint32 biststatus; /* 0x00c */ ++ uint32 PAD[4]; ++ uint32 intstatus; /* 0x020 */ ++ uint32 intmask; /* 0x024 */ ++ uint32 gptimer; /* 0x028 */ ++ uint32 PAD[53]; ++ uint32 intrecvlazy; /* 0x100 */ ++ uint32 flowctlthresh; /* 0x104 */ ++ uint32 wrrthresh; /* 0x108 */ ++ uint32 gmac_idle_cnt_thresh; /* 0x10c */ ++ uint32 PAD[28]; ++ uint32 phyaccess; /* 0x180 */ ++ uint32 PAD; ++ uint32 phycontrol; /* 0x188 */ ++ uint32 txqctl; /* 0x18c */ ++ uint32 rxqctl; /* 0x190 */ ++ uint32 gpioselect; /* 0x194 */ ++ uint32 gpio_output_en; /* 0x198 */ ++ uint32 PAD; /* 0x19c */ ++ uint32 txq_rxq_mem_ctl; /* 0x1a0 */ ++ uint32 memory_ecc_status; /* 0x1a4 */ ++ uint32 serdes_ctl; /* 0x1a8 */ ++ uint32 serdes_status0; /* 0x1ac */ ++ uint32 serdes_status1; /* 0x1b0 */ ++ uint32 PAD[11]; /* 0x1b4-1dc */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; /* 0x1e4 */ ++ uint32 pwrctl; /* 0x1e8 */ ++ uint32 PAD[5]; ++ ++ dma64_t dmaregs[GMAC_NUM_DMA_TX]; ++ ++ /* GAMC MIB counters */ ++ gmacmib_t mib; ++ uint32 PAD[245]; ++ ++ uint32 unimacversion; /* 0x800 */ ++ uint32 hdbkpctl; /* 0x804 */ ++ uint32 cmdcfg; /* 0x808 */ ++ uint32 macaddrhigh; /* 0x80c */ ++ uint32 macaddrlow; /* 0x810 */ ++ uint32 rxmaxlength; /* 0x814 */ ++ uint32 pausequanta; /* 0x818 */ ++ uint32 PAD[10]; ++ uint32 macmode; /* 0x844 */ ++ uint32 outertag; /* 0x848 */ ++ uint32 innertag; /* 0x84c */ ++ uint32 PAD[3]; ++ uint32 txipg; /* 0x85c */ ++ uint32 PAD[180]; ++ uint32 pausectl; /* 0xb30 */ ++ uint32 txflush; /* 0xb34 */ ++ uint32 rxstatus; /* 0xb38 */ ++ uint32 txstatus; /* 0xb3c */ ++} gmacregs_t; ++ ++#define GM_MIB_BASE 0x300 ++#define GM_MIB_LIMIT 0x800 ++ ++/* ++ * register-specific flag definitions ++ */ ++ ++/* device control */ ++#define DC_TSM 0x00000002 ++#define DC_CFCO 0x00000004 ++#define DC_RLSS 0x00000008 ++#define DC_MROR 0x00000010 ++#define DC_FCM_MASK 0x00000060 ++#define DC_FCM_SHIFT 5 ++#define DC_NAE 0x00000080 ++#define DC_TF 0x00000100 ++#define DC_RDS_MASK 0x00030000 ++#define DC_RDS_SHIFT 16 ++#define DC_TDS_MASK 0x000c0000 ++#define DC_TDS_SHIFT 18 ++ ++/* device status */ ++#define DS_RBF 0x00000001 ++#define DS_RDF 0x00000002 ++#define DS_RIF 0x00000004 ++#define DS_TBF 0x00000008 ++#define DS_TDF 0x00000010 ++#define DS_TIF 0x00000020 ++#define DS_PO 0x00000040 ++#define DS_MM_MASK 0x00000300 ++#define DS_MM_SHIFT 8 ++ ++/* bist status */ ++#define BS_MTF 0x00000001 ++#define BS_MRF 0x00000002 ++#define BS_TDB 0x00000004 ++#define BS_TIB 0x00000008 ++#define BS_TBF 0x00000010 ++#define BS_RDB 0x00000020 ++#define BS_RIB 0x00000040 ++#define BS_RBF 0x00000080 ++#define BS_URTF 0x00000100 ++#define BS_UTF 0x00000200 ++#define BS_URF 0x00000400 ++ ++/* interrupt status and mask registers */ ++#define I_MRO 0x00000001 ++#define I_MTO 0x00000002 ++#define I_TFD 0x00000004 ++#define I_LS 0x00000008 ++#define I_MDIO 0x00000010 ++#define I_MR 0x00000020 ++#define I_MT 0x00000040 ++#define I_TO 0x00000080 ++#define I_PDEE 0x00000400 ++#define I_PDE 0x00000800 ++#define I_DE 0x00001000 ++#define I_RDU 0x00002000 ++#define I_RFO 0x00004000 ++#define I_XFU 0x00008000 ++#define I_RI 0x00010000 ++#define I_XI0 0x01000000 ++#define I_XI1 0x02000000 ++#define I_XI2 0x04000000 ++#define I_XI3 0x08000000 ++#define I_INTMASK 0x0f01fcff ++#define I_ERRMASK 0x0000fc00 ++ ++/* interrupt receive lazy */ ++#define IRL_TO_MASK 0x00ffffff ++#define IRL_FC_MASK 0xff000000 ++#define IRL_FC_SHIFT 24 ++ ++/* flow control thresholds */ ++#define FCT_TT_MASK 0x00000fff ++#define FCT_RT_MASK 0x0fff0000 ++#define FCT_RT_SHIFT 16 ++ ++/* txq aribter wrr thresholds */ ++#define WRRT_Q0T_MASK 0x000000ff ++#define WRRT_Q1T_MASK 0x0000ff00 ++#define WRRT_Q1T_SHIFT 8 ++#define WRRT_Q2T_MASK 0x00ff0000 ++#define WRRT_Q2T_SHIFT 16 ++#define WRRT_Q3T_MASK 0xff000000 ++#define WRRT_Q3T_SHIFT 24 ++ ++/* phy access */ ++#define PA_DATA_MASK 0x0000ffff ++#define PA_ADDR_MASK 0x001f0000 ++#define PA_ADDR_SHIFT 16 ++#define PA_REG_MASK 0x1f000000 ++#define PA_REG_SHIFT 24 ++#define PA_WRITE 0x20000000 ++#define PA_START 0x40000000 ++ ++/* phy control */ ++#define PC_EPA_MASK 0x0000001f ++#define PC_MCT_MASK 0x007f0000 ++#define PC_MCT_SHIFT 16 ++#define PC_MTE 0x00800000 ++ ++/* rxq control */ ++#define RC_DBT_MASK 0x00000fff ++#define RC_DBT_SHIFT 0 ++#define RC_PTE 0x00001000 ++#define RC_MDP_MASK 0x3f000000 ++#define RC_MDP_SHIFT 24 ++ ++#define RC_MAC_DATA_PERIOD 9 ++ ++/* txq control */ ++#define TC_DBT_MASK 0x00000fff ++#define TC_DBT_SHIFT 0 ++ ++/* gpio select */ ++#define GS_GSC_MASK 0x0000000f ++#define GS_GSC_SHIFT 0 ++ ++/* gpio output enable */ ++#define GS_GOE_MASK 0x0000ffff ++#define GS_GOE_SHIFT 0 ++ ++/* gpio output enable */ ++#define SC_TX1G_FIFO_RST_MASK 0x00f00000 ++#define SC_TX1G_FIFO_RST_VAL 0x00f00000 ++#define SC_FORCE_SPD_STRAP_MASK 0x00060000 ++#define SC_FORCE_SPD_STRAP_VAL 0x00040000 ++#define SC_REF_TERM_SEL_MASK 0x00001000 ++#define SC_REFSEL_MASK 0x00000c00 ++#define SC_REFSEL_VAL 0x00000400 ++#define SC_REFDIV_MASK 0x00000300 ++#define SC_REFDIV_VAL 0x00000000 ++#define SC_LCREF_EN_MASK 0x00000040 ++#define SC_RSTB_PLL_MASK 0x00000010 ++#define SC_RSTB_MDIOREGS_MASK 0x00000008 ++#define SC_RSTB_HW_MASK 0x00000004 ++#define SC_IDDQ_MASK 0x00000002 ++#define SC_PWR_DOWN_MASK 0x00000001 ++ ++/* clk control status */ ++#define CS_FA 0x00000001 ++#define CS_FH 0x00000002 ++#define CS_FI 0x00000004 ++#define CS_AQ 0x00000008 ++#define CS_HQ 0x00000010 ++#define CS_FC 0x00000020 ++#define CS_ER 0x00000100 ++#define CS_AA 0x00010000 ++#define CS_HA 0x00020000 ++#define CS_BA 0x00040000 ++#define CS_BH 0x00080000 ++#define CS_ES 0x01000000 ++ ++/* command config */ ++#define CC_TE 0x00000001 ++#define CC_RE 0x00000002 ++#define CC_ES_MASK 0x0000000c ++#define CC_ES_SHIFT 2 ++#define CC_PROM 0x00000010 ++#define CC_PAD_EN 0x00000020 ++#define CC_CF 0x00000040 ++#define CC_PF 0x00000080 ++#define CC_RPI 0x00000100 ++#define CC_TAI 0x00000200 ++#define CC_HD 0x00000400 ++#define CC_HD_SHIFT 10 ++#define CC_SR 0x00002000 ++#define CC_ML 0x00008000 ++#define CC_OT 0x00020000 ++#define CC_OR 0x00040000 ++#define CC_AE 0x00400000 ++#define CC_CFE 0x00800000 ++#define CC_NLC 0x01000000 ++#define CC_RL 0x02000000 ++#define CC_RED 0x04000000 ++#define CC_PE 0x08000000 ++#define CC_TPI 0x10000000 ++#define CC_AT 0x20000000 ++ ++/* mac addr high */ ++#define MH_HI_MASK 0xffff ++#define MH_HI_SHIFT 16 ++#define MH_MID_MASK 0xffff ++#define MH_MID_SHIFT 0 ++ ++/* mac addr low */ ++#define ML_LO_MASK 0xffff ++#define ML_LO_SHIFT 0 ++ ++/* Core specific control flags */ ++#define SICF_SWCLKE 0x0004 ++#define SICF_SWRST 0x0008 ++ ++/* Core specific status flags */ ++#define SISF_SW_ATTACHED 0x0800 ++ ++#endif /* _gmac_core_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndarm.h b/drivers/bcmdrivers/gmac/src/include/hndarm.h +new file mode 100755 +index 0000000..c105b958 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndarm.h +@@ -0,0 +1,96 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane ARM core software interface. ++ * ++ * $Id: hndarm.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _hndarm_h_ ++#define _hndarm_h_ ++ ++#include ++ ++extern void *hndarm_armr; ++extern uint32 hndarm_rev; ++ ++ ++extern void si_arm_init(si_t *sih); ++ ++#ifdef __ARM_ARCH_7A__ ++extern uint32 si_memc_get_ncdl(si_t *sih); ++#endif ++ ++extern void enable_arm_ints(uint32 which); ++extern void disable_arm_ints(uint32 which); ++ ++extern uint32 get_arm_cyclecount(void); ++extern void set_arm_cyclecount(uint32 ticks); ++ ++#ifdef __ARM_ARCH_7R__ ++extern uint32 get_arm_perfcount_enable(void); ++extern void set_arm_perfcount_enable(uint32 which); ++extern uint32 set_arm_perfcount_disable(void); ++ ++extern uint32 get_arm_perfcount_sel(void); ++extern void set_arm_perfcount_sel(uint32 which); ++ ++extern uint32 get_arm_perfcount_event(void); ++extern void set_arm_perfcount_event(uint32 which); ++ ++extern uint32 get_arm_perfcount(void); ++extern void set_arm_perfcount(uint32 which); ++ ++extern void enable_arm_cyclecount(void); ++extern void disable_arm_cyclecount(void); ++#endif /* __ARM_ARCH_7R__ */ ++ ++extern uint32 get_arm_inttimer(void); ++extern void set_arm_inttimer(uint32 ticks); ++ ++extern uint32 get_arm_intmask(void); ++extern void set_arm_intmask(uint32 ticks); ++ ++extern uint32 get_arm_intstatus(void); ++extern void set_arm_intstatus(uint32 ticks); ++ ++extern uint32 get_arm_firqmask(void); ++extern void set_arm_firqmask(uint32 ticks); ++ ++extern uint32 get_arm_firqstatus(void); ++extern void set_arm_firqstatus(uint32 ticks); ++ ++extern void arm_wfi(si_t *sih); ++extern void arm_jumpto(void *addr); ++ ++extern void traptest(void); ++ ++#ifdef BCMOVLHW ++#define BCMOVLHW_ENAB(sih) TRUE ++ ++extern int si_arm_ovl_remap(si_t *sih, void *virt, void *phys, uint size); ++extern int si_arm_ovl_reset(si_t *sih); ++extern bool si_arm_ovl_vaildaddr(si_t *sih, void *virt); ++extern bool si_arm_ovl_isenab(si_t *sih); ++extern bool si_arm_ovl_int(si_t *sih, uint32 pc); ++#else ++#define BCMOVLHW_ENAB(sih) FALSE ++ ++#define si_arm_ovl_remap(a, b, c, d) do {} while (0) ++#define si_arm_ovl_reset(a) do {} while (0) ++#define si_arm_ovl_int(a, b) FALSE ++#endif ++ ++#endif /* _hndarm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndchipc.h b/drivers/bcmdrivers/gmac/src/include/hndchipc.h +new file mode 100755 +index 0000000..878276f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndchipc.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane chipcommon support. ++ * ++ * $Id: hndchipc.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _hndchipc_h_ ++#define _hndchipc_h_ ++ ++typedef void (*si_serial_init_fn)(void *regs, uint irq, uint baud_base, uint reg_shift); ++ ++extern void si_serial_init(si_t *sih, si_serial_init_fn add); ++ ++extern void *hnd_jtagm_init(si_t *sih, uint clkd, bool exttap); ++extern void hnd_jtagm_disable(si_t *sih, void *h); ++extern uint32 jtag_scan(si_t *sih, void *h, uint irsz, uint32 ir0, uint32 ir1, ++ uint drsz, uint32 dr0, uint32 *dr1, bool rti); ++ ++typedef void (*cc_isr_fn)(void* cbdata, uint32 ccintst); ++ ++extern bool si_cc_register_isr(si_t *sih, cc_isr_fn isr, uint32 ccintmask, void *cbdata); ++extern void si_cc_isr(si_t *sih, chipcregs_t *regs); ++ ++#endif /* _hndchipc_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndcpu.h b/drivers/bcmdrivers/gmac/src/include/hndcpu.h +new file mode 100755 +index 0000000..8a4ee4c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndcpu.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SiliconBackplane MIPS/ARM cores software interface. ++ * ++ * $Id: hndcpu.h 258983 2011-05-11 09:59:25Z $ ++ */ ++ ++#ifndef _hndcpu_h_ ++#define _hndcpu_h_ ++ ++#if defined(mips) ++#include ++#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) ++#include ++#endif ++ ++extern uint si_irq(si_t *sih); ++extern uint32 si_cpu_clock(si_t *sih); ++extern uint32 si_mem_clock(si_t *sih); ++extern void hnd_cpu_wait(si_t *sih); ++extern void hnd_cpu_jumpto(void *addr); ++extern void hnd_cpu_reset(si_t *sih); ++extern void hnd_cpu_deadman_timer(si_t *sih, uint32 val); ++extern void si_router_coma(si_t *sih, int reset, int delay); ++extern void si_dmc_phyctl(si_t *sih, uint32 phyctl_val); ++ ++#endif /* _hndcpu_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hnddma.h b/drivers/bcmdrivers/gmac/src/include/hnddma.h +new file mode 100755 +index 0000000..64f0349 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hnddma.h +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: hnddma.h 321146 2012-03-14 08:27:23Z $ ++ */ ++ ++#ifndef _hnddma_h_ ++#define _hnddma_h_ ++ ++#ifndef _hnddma_pub_ ++#define _hnddma_pub_ ++typedef const struct hnddma_pub hnddma_t; ++#endif /* _hnddma_pub_ */ ++ ++/* range param for dma_getnexttxp() and dma_txreclaim */ ++typedef enum txd_range { ++ HNDDMA_RANGE_ALL = 1, ++ HNDDMA_RANGE_TRANSMITTED, ++ HNDDMA_RANGE_TRANSFERED ++} txd_range_t; ++ ++/* dma parameters id */ ++enum dma_param_id { ++ HNDDMA_PID_TX_MULTI_OUTSTD_RD = 0, ++ HNDDMA_PID_TX_PREFETCH_CTL, ++ HNDDMA_PID_TX_PREFETCH_THRESH, ++ HNDDMA_PID_TX_BURSTLEN, ++ ++ HNDDMA_PID_RX_PREFETCH_CTL = 0x100, ++ HNDDMA_PID_RX_PREFETCH_THRESH, ++ HNDDMA_PID_RX_BURSTLEN ++}; ++ ++/* dma function type */ ++typedef void (*di_detach_t)(hnddma_t *dmah); ++typedef bool (*di_txreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxreset_t)(hnddma_t *dmah); ++typedef bool (*di_rxidle_t)(hnddma_t *dmah); ++typedef void (*di_txinit_t)(hnddma_t *dmah); ++typedef bool (*di_txenabled_t)(hnddma_t *dmah); ++typedef void (*di_rxinit_t)(hnddma_t *dmah); ++typedef void (*di_txsuspend_t)(hnddma_t *dmah); ++typedef void (*di_txresume_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspended_t)(hnddma_t *dmah); ++typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah); ++#ifdef WL_MULTIQUEUE ++typedef void (*di_txflush_t)(hnddma_t *dmah); ++typedef void (*di_txflush_clear_t)(hnddma_t *dmah); ++#endif /* WL_MULTIQUEUE */ ++typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit); ++typedef int (*di_txunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); ++typedef int (*di_rxunframed_t)(hnddma_t *dmah, void *p, uint len, bool commit); ++typedef void* (*di_getpos_t)(hnddma_t *di, bool direction); ++typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah); ++typedef bool (*di_txstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxstopped_t)(hnddma_t *dmah); ++typedef bool (*di_rxenable_t)(hnddma_t *dmah); ++typedef bool (*di_rxenabled_t)(hnddma_t *dmah); ++typedef void* (*di_rx_t)(hnddma_t *dmah); ++typedef bool (*di_rxfill_t)(hnddma_t *dmah); ++typedef void (*di_txreclaim_t)(hnddma_t *dmah, txd_range_t range); ++typedef void (*di_rxreclaim_t)(hnddma_t *dmah); ++typedef uintptr (*di_getvar_t)(hnddma_t *dmah, const char *name); ++typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, txd_range_t range); ++typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall); ++typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah); ++typedef void* (*di_peekntxp_t)(hnddma_t *dmah, int *len, void *txps[], txd_range_t range); ++typedef void* (*di_peeknextrxp_t)(hnddma_t *dmah); ++typedef void (*di_rxparam_get_t)(hnddma_t *dmah, uint16 *rxoffset, uint16 *rxbufsize); ++typedef void (*di_txblock_t)(hnddma_t *dmah); ++typedef void (*di_txunblock_t)(hnddma_t *dmah); ++typedef uint (*di_txactive_t)(hnddma_t *dmah); ++typedef void (*di_txrotate_t)(hnddma_t *dmah); ++typedef void (*di_counterreset_t)(hnddma_t *dmah); ++typedef uint (*di_ctrlflags_t)(hnddma_t *dmah, uint mask, uint flags); ++typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); ++typedef uint (*di_rxactive_t)(hnddma_t *dmah); ++typedef uint (*di_txpending_t)(hnddma_t *dmah); ++typedef uint (*di_txcommitted_t)(hnddma_t *dmah); ++typedef int (*di_pktpool_set_t)(hnddma_t *dmah, pktpool_t *pool); ++typedef bool (*di_rxtxerror_t)(hnddma_t *dmah, bool istx); ++typedef void (*di_burstlen_set_t)(hnddma_t *dmah, uint8 rxburstlen, uint8 txburstlen); ++typedef uint (*di_avoidancecnt_t)(hnddma_t *dmah); ++typedef void (*di_param_set_t)(hnddma_t *dmah, uint16 paramid, uint16 paramval); ++typedef bool (*dma_glom_enable_t) (hnddma_t *dmah, uint32 val); ++typedef uint (*dma_active_rxbuf_t) (hnddma_t *dmah); ++/* dma opsvec */ ++typedef struct di_fcn_s { ++ di_detach_t detach; ++ di_txinit_t txinit; ++ di_txreset_t txreset; ++ di_txenabled_t txenabled; ++ di_txsuspend_t txsuspend; ++ di_txresume_t txresume; ++ di_txsuspended_t txsuspended; ++ di_txsuspendedidle_t txsuspendedidle; ++#ifdef WL_MULTIQUEUE ++ di_txflush_t txflush; ++ di_txflush_clear_t txflush_clear; ++#endif /* WL_MULTIQUEUE */ ++ di_txfast_t txfast; ++ di_txunframed_t txunframed; ++ di_getpos_t getpos; ++ di_txstopped_t txstopped; ++ di_txreclaim_t txreclaim; ++ di_getnexttxp_t getnexttxp; ++ di_peeknexttxp_t peeknexttxp; ++ di_peekntxp_t peekntxp; ++ di_txblock_t txblock; ++ di_txunblock_t txunblock; ++ di_txactive_t txactive; ++ di_txrotate_t txrotate; ++ ++ di_rxinit_t rxinit; ++ di_rxreset_t rxreset; ++ di_rxidle_t rxidle; ++ di_rxstopped_t rxstopped; ++ di_rxenable_t rxenable; ++ di_rxenabled_t rxenabled; ++ di_rx_t rx; ++ di_rxfill_t rxfill; ++ di_rxreclaim_t rxreclaim; ++ di_getnextrxp_t getnextrxp; ++ di_peeknextrxp_t peeknextrxp; ++ di_rxparam_get_t rxparam_get; ++ ++ di_fifoloopbackenable_t fifoloopbackenable; ++ di_getvar_t d_getvar; ++ di_counterreset_t counterreset; ++ di_ctrlflags_t ctrlflags; ++ di_dump_t dump; ++ di_dumptx_t dumptx; ++ di_dumprx_t dumprx; ++ di_rxactive_t rxactive; ++ di_txpending_t txpending; ++ di_txcommitted_t txcommitted; ++ di_pktpool_set_t pktpool_set; ++ di_rxtxerror_t rxtxerror; ++ di_burstlen_set_t burstlen_set; ++ di_avoidancecnt_t avoidancecnt; ++ di_param_set_t param_set; ++ dma_glom_enable_t glom_enab; ++ di_rxunframed_t rxunframed; ++ dma_active_rxbuf_t dma_activerxbuf; ++ uint endnum; ++} di_fcn_t; ++ ++/* ++ * Exported data structure (read-only) ++ */ ++/* export structure */ ++struct hnddma_pub { ++ const di_fcn_t *di_fn; /* DMA function pointers */ ++ uint txavail; /* # free tx descriptors */ ++ uint dmactrlflags; /* dma control flags */ ++ ++ /* rx error counters */ ++ uint rxgiants; /* rx giant frames */ ++ uint rxnobuf; /* rx out of dma descriptors */ ++ /* tx error counters */ ++ uint txnobuf; /* tx out of dma descriptors */ ++ uint txnodesc; /* tx out of dma descriptors running count */ ++}; ++ ++ ++extern hnddma_t * dma_attach(osl_t *osh, const char *name, si_t *sih, ++ volatile void *dmaregstx, volatile void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, ++ uint rxoffset, uint *msg_level); ++#ifdef BCMDMA32 ++ ++#define dma_detach(di) ((di)->di_fn->detach(di)) ++#define dma_txreset(di) ((di)->di_fn->txreset(di)) ++#define dma_rxreset(di) ((di)->di_fn->rxreset(di)) ++#define dma_rxidle(di) ((di)->di_fn->rxidle(di)) ++#define dma_txinit(di) ((di)->di_fn->txinit(di)) ++#define dma_txenabled(di) ((di)->di_fn->txenabled(di)) ++#define dma_rxinit(di) ((di)->di_fn->rxinit(di)) ++#define dma_txsuspend(di) ((di)->di_fn->txsuspend(di)) ++#define dma_txresume(di) ((di)->di_fn->txresume(di)) ++#define dma_txsuspended(di) ((di)->di_fn->txsuspended(di)) ++#define dma_txsuspendedidle(di) ((di)->di_fn->txsuspendedidle(di)) ++#ifdef WL_MULTIQUEUE ++#define dma_txflush(di) ((di)->di_fn->txflush(di)) ++#define dma_txflush_clear(di) ((di)->di_fn->txflush_clear(di)) ++#endif /* WL_MULTIQUEUE */ ++#define dma_txfast(di, p, commit) ((di)->di_fn->txfast(di, p, commit)) ++#define dma_fifoloopbackenable(di) ((di)->di_fn->fifoloopbackenable(di)) ++#define dma_txstopped(di) ((di)->di_fn->txstopped(di)) ++#define dma_rxstopped(di) ((di)->di_fn->rxstopped(di)) ++#define dma_rxenable(di) ((di)->di_fn->rxenable(di)) ++#define dma_rxenabled(di) ((di)->di_fn->rxenabled(di)) ++#define dma_rx(di) ((di)->di_fn->rx(di)) ++#define dma_rxfill(di) ((di)->di_fn->rxfill(di)) ++#define dma_txreclaim(di, range) ((di)->di_fn->txreclaim(di, range)) ++#define dma_rxreclaim(di) ((di)->di_fn->rxreclaim(di)) ++#define dma_getvar(di, name) ((di)->di_fn->d_getvar(di, name)) ++#define dma_getnexttxp(di, range) ((di)->di_fn->getnexttxp(di, range)) ++#define dma_getnextrxp(di, forceall) ((di)->di_fn->getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) ((di)->di_fn->peeknexttxp(di)) ++#define dma_peekntxp(di, l, t, r) ((di)->di_fn->peekntxp(di, l, t, r)) ++#define dma_peeknextrxp(di) ((di)->di_fn->peeknextrxp(di)) ++#define dma_rxparam_get(di, off, bufs) ((di)->di_fn->rxparam_get(di, off, bufs)) ++ ++#define dma_txblock(di) ((di)->di_fn->txblock(di)) ++#define dma_txunblock(di) ((di)->di_fn->txunblock(di)) ++#define dma_txactive(di) ((di)->di_fn->txactive(di)) ++#define dma_rxactive(di) ((di)->di_fn->rxactive(di)) ++#define dma_txrotate(di) ((di)->di_fn->txrotate(di)) ++#define dma_counterreset(di) ((di)->di_fn->counterreset(di)) ++#define dma_ctrlflags(di, mask, flags) ((di)->di_fn->ctrlflags((di), (mask), (flags))) ++#define dma_txpending(di) ((di)->di_fn->txpending(di)) ++#define dma_txcommitted(di) ((di)->di_fn->txcommitted(di)) ++#define dma_pktpool_set(di, pool) ((di)->di_fn->pktpool_set((di), (pool))) ++#if defined(BCMDBG) ++#define dma_dump(di, buf, dumpring) ((di)->di_fn->dump(di, buf, dumpring)) ++#define dma_dumptx(di, buf, dumpring) ((di)->di_fn->dumptx(di, buf, dumpring)) ++#define dma_dumprx(di, buf, dumpring) ((di)->di_fn->dumprx(di, buf, dumpring)) ++#endif ++#define dma_rxtxerror(di, istx) ((di)->di_fn->rxtxerror(di, istx)) ++#define dma_burstlen_set(di, rxlen, txlen) ((di)->di_fn->burstlen_set(di, rxlen, txlen)) ++#define dma_avoidance_cnt(di) ((di)->di_fn->avoidancecnt(di)) ++#define dma_param_set(di, paramid, paramval) ((di)->di_fn->param_set(di, paramid, paramval)) ++#define dma_activerxbuf(di) ((di)->di_fn->dma_activerxbuf(di)) ++ ++#else /* BCMDMA32 */ ++extern const di_fcn_t dma64proc; ++ ++#define dma_detach(di) (dma64proc.detach(di)) ++#define dma_txreset(di) (dma64proc.txreset(di)) ++#define dma_rxreset(di) (dma64proc.rxreset(di)) ++#define dma_rxidle(di) (dma64proc.rxidle(di)) ++#define dma_txinit(di) (dma64proc.txinit(di)) ++#define dma_txenabled(di) (dma64proc.txenabled(di)) ++#define dma_rxinit(di) (dma64proc.rxinit(di)) ++#define dma_txsuspend(di) (dma64proc.txsuspend(di)) ++#define dma_txresume(di) (dma64proc.txresume(di)) ++#define dma_txsuspended(di) (dma64proc.txsuspended(di)) ++#define dma_txsuspendedidle(di) (dma64proc.txsuspendedidle(di)) ++#ifdef WL_MULTIQUEUE ++#define dma_txflush(di) (dma64proc.txflush(di)) ++#define dma_txflush_clear(di) (dma64proc.txflush_clear(di)) ++#endif /* WL_MULTIQUEUE */ ++#define dma_txfast(di, p, commit) (dma64proc.txfast(di, p, commit)) ++#define dma_txunframed(di, p, l, commit)(dma64proc.txunframed(di, p, l, commit)) ++#define dma_getpos(di, dir) (dma64proc.getpos(di, dir)) ++#define dma_fifoloopbackenable(di) (dma64proc.fifoloopbackenable(di)) ++#define dma_txstopped(di) (dma64proc.txstopped(di)) ++#define dma_rxstopped(di) (dma64proc.rxstopped(di)) ++#define dma_rxenable(di) (dma64proc.rxenable(di)) ++#define dma_rxenabled(di) (dma64proc.rxenabled(di)) ++#define dma_rx(di) (dma64proc.rx(di)) ++#define dma_rxfill(di) (dma64proc.rxfill(di)) ++#define dma_txreclaim(di, range) (dma64proc.txreclaim(di, range)) ++#define dma_rxreclaim(di) (dma64proc.rxreclaim(di)) ++#define dma_getvar(di, name) (dma64proc.d_getvar(di, name)) ++#define dma_getnexttxp(di, range) (dma64proc.getnexttxp(di, range)) ++#define dma_getnextrxp(di, forceall) (dma64proc.getnextrxp(di, forceall)) ++#define dma_peeknexttxp(di) (dma64proc.peeknexttxp(di)) ++#define dma_peekntxp(di, l, t, r) (dma64proc.peekntxp(di, l, t, r)) ++#define dma_peeknextrxp(di) (dma64proc.peeknextrxp(di)) ++#define dma_rxparam_get(di, off, bufs) (dma64proc.rxparam_get(di, off, bufs)) ++ ++#define dma_txblock(di) (dma64proc.txblock(di)) ++#define dma_txunblock(di) (dma64proc.txunblock(di)) ++#define dma_txactive(di) (dma64proc.txactive(di)) ++#define dma_rxactive(di) (dma64proc.rxactive(di)) ++#define dma_txrotate(di) (dma64proc.txrotate(di)) ++#define dma_counterreset(di) (dma64proc.counterreset(di)) ++#define dma_ctrlflags(di, mask, flags) (dma64proc.ctrlflags((di), (mask), (flags))) ++#define dma_txpending(di) (dma64proc.txpending(di)) ++#define dma_txcommitted(di) (dma64proc.txcommitted(di)) ++#define dma_pktpool_set(di, pool) (dma64proc.pktpool_set((di), (pool))) ++#define dma_rxunframed(di, p, l, commit)(dma64proc.rxunframed(di, p, l, commit)) ++#if defined(BCMDBG) ++#define dma_dump(di, buf, dumpring) (dma64proc.dump(di, buf, dumpring)) ++#define dma_dumptx(di, buf, dumpring) (dma64proc.dumptx(di, buf, dumpring)) ++#define dma_dumprx(di, buf, dumpring) (dma64proc.dumprx(di, buf, dumpring)) ++#endif ++#define dma_rxtxerror(di, istx) (dma64proc.rxtxerror(di, istx)) ++#define dma_burstlen_set(di, rxlen, txlen) (dma64proc.burstlen_set(di, rxlen, txlen)) ++#define dma_avoidance_cnt(di) (dma64proc.avoidancecnt(di)) ++#define dma_param_set(di, paramid, paramval) (dma64proc.param_set(di, paramid, paramval)) ++ ++#define dma_glom_enable(di, val) (dma64proc.glom_enab(di, val)) ++#define dma_activerxbuf(di) (dma64proc.dma_activerxbuf(di)) ++ ++#endif /* BCMDMA32 */ ++ ++/* return addresswidth allowed ++ * This needs to be done after SB attach but before dma attach. ++ * SB attach provides ability to probe backplane and dma core capabilities ++ * This info is needed by DMA_ALLOC_CONSISTENT in dma attach ++ */ ++extern uint dma_addrwidth(si_t *sih, void *dmaregs); ++ ++/* pio helpers */ ++extern void dma_txpioloopback(osl_t *osh, dma32regs_t *); ++ ++#endif /* _hnddma_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndfwd.h b/drivers/bcmdrivers/gmac/src/include/hndfwd.h +new file mode 100755 +index 0000000..1502804 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndfwd.h +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND GMAC Forwarder ++ * When multiple ports from a switch to a dual core host processor are available ++ * each Wl MAC instance (wl0 and wl1) may be tied to each core. A forwarding ++ * driver would recieve/transmit packets from/to switch on behalf of the Wl ++ * driver per core, essentially translating each core of the host processor to ++ * be a WL MAC that is becomes just another "W"-LAN port on the switch. ++ * ++ * hndfwd.h provides the API for the Fwder network device driver and wl driver ++ * to register their respective transmit handlers as a per cpu object. ++ * ++ * HND Fwder in SMP assumes "dual" core: ++ * Core1: wl0=11ac ++ * Core0: wl1=11n + eth0 ++ * HND Fwder in Uniprocessor mode would use 2 units. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _hndfwd_h_ ++#define _hndfwd_h_ ++ ++#if defined(GMAC3) ++ ++/* ++ * Multiple GMAC to Host SMP Model: The ethernet driver operates as a ++ * FWD: Forwarder to MAC Interface such as wl0, wl1 ++ * NTK: Ethernet Network Interface binding to network stack (via CTF) ++ */ ++#define DEV_FWDER_NAME "fwd" ++#define DEV_NTKIF(etc) ((etc)->gmac_fwd == FALSE) ++#define DEV_FWDER(etc) ((etc)->gmac_fwd == TRUE) ++ ++#if defined(CONFIG_SMP) ++#define _FWDER_LOCK(fwder) spin_lock_bh(&(fwder)->lock) ++#define _FWDER_UNLOCK(fwder) spin_unlock_bh(&(fwder)->lock) ++#else /* !CONFIG_SMP */ ++#define _FWDER_LOCK(fwder) local_bh_disable() ++#define _FWDER_UNLOCK(fwder) local_bh_enable() ++#endif /* !CONFIG_SMP */ ++ ++#define FWDER_FAILURE 1 ++#define FWDER_SUCCESS 0 ++ ++#define FWDER_DEBUG ++#define FWDER_MAX_UNITS 2 ++ ++/* hard start xmit handler of a network device driver */ ++typedef int (* fwder_start_t)(struct sk_buff * buff, struct net_device * dev, ++ int cnt); ++ ++typedef enum fwder_dir { ++ FWD_UPSTREAM, /* WL##(RX) -> GMAC(TX) Start Xmit Handler */ ++ FWD_DNSTREAM, /* GMAC(RX) -> Wl##(TX) Start Xmit Handler */ ++ FWD_MAX_DIRS ++} fwder_dir_t; ++ ++typedef struct fwder { ++ struct net_device * dev; ++ fwder_start_t forward; ++ int unit; ++ unsigned int error; ++#if defined(CONFIG_SMP) ++ spinlock_t lock; ++#endif /* CONFIG_SMP */ ++} fwder_t; ++ ++#if defined(CONFIG_SMP) ++DECLARE_PER_CPU(struct fwder, fwd_upstream); /* Per Core GMAC Transmit */ ++DECLARE_PER_CPU(struct fwder, fwd_dnstream); /* Per Core Wl## Transmit */ ++#else /* !CONFIG_SMP */ ++extern struct fwder fwd_upstream[FWDER_MAX_UNITS]; ++extern struct fwder fwd_dnstream[FWDER_MAX_UNITS]; ++#endif /* !CONFIG_SMP */ ++ ++extern int fwder_init(void); /* Invoked in eth0 module_init */ ++ ++/* Register a transmit handler and return the reverse dir handler */ ++extern struct fwder * fwder_attach(fwder_start_t forward, ++ const struct net_device * dev, const int unit, const enum fwder_dir dir); ++ ++/* Deregister a transmit handler */ ++extern struct fwder * fwder_dettach(struct fwder * fwder_p); ++ ++extern void fwder_dump(const struct fwder * fwder_p); ++extern void fwder_dump_all(void); ++ ++static inline int ++fwder_transmit(struct sk_buff * skb, struct net_device * dev, ++ struct fwder * fwder_p, int cnt) ++{ ++ int ret; ++ ++ ASSERT(fwder_p != (struct fwder*)NULL); ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ if (dev == (struct net_device *)NULL) { ++ skb->dev = (struct net_device *)fwder_p->dev; ++ } ++ ++ ret = fwder_p->forward(skb, skb->dev, cnt); ++ ++#if defined(FWDER_DEBUG) ++ if (ret == FWDER_FAILURE) ++ fwder_p->error++; ++#endif ++ ++ _FWDER_UNLOCK(fwder_p); /* --LOCK */ ++ ++ return ret; ++} ++ ++#else /* !GMAC3 */ ++ ++#define DEV_FWDER_NAME "eth" ++#define DEV_NTKIF(etc) 1 ++#define DEV_FWDER(etc) 0 ++ ++#endif /* !GMAC3 */ ++ ++#endif /* _hndfwd_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndsoc.h b/drivers/bcmdrivers/gmac/src/include/hndsoc.h +new file mode 100755 +index 0000000..ae3d3c3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndsoc.h +@@ -0,0 +1,269 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom HND chip & on-chip-interconnect-related definitions. ++ * ++ * $Id: hndsoc.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _HNDSOC_H ++#define _HNDSOC_H ++ ++/* Include the soci specific files */ ++#include ++#include ++ ++/* ++ * SOC Interconnect Address Map. ++ * All regions may not exist on all chips. ++ */ ++#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */ ++#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI_MEM_SZ (64 * 1024 * 1024) ++#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */ ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++#define SI_ENUM_BASE (sii->pub.si_enum_base) ++#else ++#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ ++#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ ++#define SI_MAXCORES 20 /* Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ ++ ++#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ ++#define SI_FASTRAM_SWAPPED 0x19800000 ++ ++#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ ++#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ ++#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ ++#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ ++#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ ++ ++#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */ ++#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */ ++#define SI_NS_NORFLASH_SZ 0x02000000 /* Size of NorthStar NOR flash region */ ++#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */ ++ ++#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ ++#define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ ++#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ ++#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ ++#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ ++#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ ++ ++#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ ++#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), low 32 bits ++ */ ++#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define SI_NS_CUR 0x1800B000 /* NorthStar CUR base */ ++ ++#if defined(CONFIG_MACH_NS) ++#define SI_NS_CHIPCB_SRAB 0x18007000 /* NorthStar Chip Common B SRAB base */ ++#else ++#define SI_NS_CHIPCB_SRAB 0x18036000 /* NorthStar+ Chip Common B SRAB base */ ++#endif ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++ ++#define ACPHY_CORE_ID 0x83b /* Dot11 ACPHY */ ++#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */ ++#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */ ++#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */ ++#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */ ++#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */ ++#define EROM_CORE_ID 0x366 /* EROM core ID */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all ++ * unused address ranges ++ */ ++ ++#define CC_4706_CORE_ID 0x500 /* chipcommon core */ ++#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++#define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ ++#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID ++#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */ ++#define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ ++#define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ ++#define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ ++#define ALTA_CORE_ID 0x534 /* I2S core */ ++#define DDR23_PHY_CORE_ID 0x5dd ++ ++#define SI_PCI1_MEM 0x40000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI1_CFG 0x44000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */ ++#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */ ++#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */ ++ ++/* There are TWO constants on all HND chips: SI_ENUM_BASE above, ++ * and chipcommon being the first core: ++ */ ++#define SI_CC_IDX 0 ++ ++/* SOC Interconnect types (aka chip types) */ ++#define SOCI_SB 0 ++#define SOCI_AI 1 ++#define SOCI_UBUS 2 ++#define SOCI_NS 3 ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++/* Common core status flags */ ++#define SISF_BIST_DONE 0x8000 ++#define SISF_BIST_ERROR 0x4000 ++#define SISF_GATED_CLK 0x2000 ++#define SISF_DMA64 0x1000 ++#define SISF_CORE_BITS 0x0fff ++ ++/* Norstar core status flags */ ++#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */ ++#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */ ++#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */ ++#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */ ++#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ ++#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ ++ ++/* A register that is common to all cores to ++ * communicate w/PMU regarding clock control. ++ */ ++#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ ++ ++/* clk_ctl_st register */ ++#define CCS_FORCEALP 0x00000001 /* force ALP request */ ++#define CCS_FORCEHT 0x00000002 /* force HT request */ ++#define CCS_FORCEILP 0x00000004 /* force ILP request */ ++#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ ++#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ ++#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ ++#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */ ++#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */ ++#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ ++#define CCS_ERSRC_REQ_SHIFT 8 ++#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ ++#define CCS_HTAVAIL 0x00020000 /* HT is available */ ++#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */ ++#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */ ++#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ ++#define CCS_ERSRC_STS_SHIFT 24 ++ ++#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ ++ ++/* Not really related to SOC Interconnect, but a couple of software ++ * conventions for the use the flash space: ++ */ ++ ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++/* A boot/binary may have an embedded block that describes its size */ ++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ ++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ ++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ ++#define BISZ_TXTST_IDX 1 /* 1: text start */ ++#define BISZ_TXTEND_IDX 2 /* 2: text end */ ++#define BISZ_DATAST_IDX 3 /* 3: data start */ ++#define BISZ_DATAEND_IDX 4 /* 4: data end */ ++#define BISZ_BSSST_IDX 5 /* 5: bss start */ ++#define BISZ_BSSEND_IDX 6 /* 6: bss end */ ++#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ ++ ++#endif /* _HNDSOC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/hndtcam.h b/drivers/bcmdrivers/gmac/src/include/hndtcam.h +new file mode 100755 +index 0000000..da7acf8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/hndtcam.h +@@ -0,0 +1,95 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND SOCRAM TCAM software interface. ++ * ++ * $Id: hndtcam.h 317281 2012-02-27 11:23:27Z $ ++ */ ++#ifndef _hndtcam_h_ ++#define _hndtcam_h_ ++ ++/* ++ * 0 - 1 ++ * 1 - 2 Consecutive locations are patched ++ * 2 - 4 Consecutive locations are patched ++ * 3 - 8 Consecutive locations are patched ++ * 4 - 16 Consecutive locations are patched ++ * Define default to patch 2 locations ++ */ ++ ++#ifdef PATCHCOUNT ++#define SRPC_PATCHCOUNT PATCHCOUNT ++#else ++#define PATCHCOUNT 0 ++#define SRPC_PATCHCOUNT PATCHCOUNT ++#endif ++ ++#if defined(__ARM_ARCH_7R__) ++#ifndef PATCHCOUNT ++#define PATCHCOUNT 1 ++#endif ++#define ARMCR4_TCAMPATCHCOUNT PATCHCOUNT ++#define ARMCR4_TCAMADDR_MASK (~((1 << (ARMCR4_TCAMPATCHCOUNT + 2))-1)) ++#define ARMCR4_PATCHNLOC (1 << ARMCR4_TCAMPATCHCOUNT) ++#endif /* defined(__ARM_ARCH_7R__) */ ++ ++/* N Consecutive location to patch */ ++#define SRPC_PATCHNLOC (1 << (SRPC_PATCHCOUNT)) ++ ++#define PATCHHDR(_p) __attribute__ ((__section__ (".patchhdr."#_p))) _p ++#define PATCHENTRY(_p) __attribute__ ((__section__ (".patchentry."#_p))) _p ++ ++#if defined(__ARM_ARCH_7R__) ++typedef struct { ++ uint32 data[ARMCR4_PATCHNLOC]; ++} patch_entry_t; ++#else ++typedef struct { ++ uint32 data[SRPC_PATCHNLOC]; ++} patch_entry_t; ++#endif ++ ++typedef struct { ++ void *addr; /* patch address */ ++ uint32 len; /* bytes to patch in entry */ ++ patch_entry_t *entry; /* patch entry data */ ++} patch_hdr_t; ++ ++/* patch values and address structure */ ++typedef struct patchaddrvalue { ++ uint32 addr; ++ uint32 value; ++} patchaddrvalue_t; ++ ++extern void *socram_regs; ++extern uint32 socram_rev; ++ ++extern void *arm_regs; ++ ++extern void hnd_patch_init(void *srp); ++extern void hnd_tcam_write(void *srp, uint16 idx, uint32 data); ++extern void hnd_tcam_read(void *srp, uint16 idx, uint32 *content); ++void * hnd_tcam_init(void *srp, int no_addrs); ++extern void hnd_tcam_disablepatch(void *srp); ++extern void hnd_tcam_enablepatch(void *srp); ++#ifdef CONFIG_XIP ++extern void hnd_tcam_bootloader_load(void *srp, char *pvars); ++#else ++extern void hnd_tcam_load(void *srp, const patchaddrvalue_t *patchtbl); ++#endif /* CONFIG_XIP */ ++extern void BCMATTACHFN(hnd_tcam_load_default)(void); ++extern void hnd_tcam_reclaim(void); ++ ++#endif /* _hndtcam_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/linux_osl.h b/drivers/bcmdrivers/gmac/src/include/linux_osl.h +new file mode 100755 +index 0000000..e49878b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/linux_osl.h +@@ -0,0 +1,979 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux OS Independent Layer ++ * ++ * $Id: linux_osl.h 329351 2012-04-25 01:48:39Z $ ++ */ ++ ++#ifndef _linux_osl_h_ ++#define _linux_osl_h_ ++ ++#include ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ ++/* Reuse some of existing code of CTFPOOL */ ++#ifndef CTFPOOL ++#define CTFPOOL ++#endif ++ ++/* #define SKB_RECYCLING_DEBUG */ ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ ++/* Linux Kernel: File Operations: start */ ++extern void * osl_os_open_image(char * filename); ++extern int osl_os_get_image_block(char * buf, int len, void * image); ++extern void osl_os_close_image(void * image); ++extern int osl_os_image_size(void *image); ++/* Linux Kernel: File Operations: end */ ++ ++#ifdef BCMDRIVER ++ ++/* OSL initialization */ ++extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); ++extern void osl_detach(osl_t *osh); ++ ++/* Global ASSERT type */ ++extern uint32 g_assert_type; ++ ++/* ASSERT */ ++ #ifdef __GNUC__ ++ #define GCC_VERSION \ ++ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) ++ #if GCC_VERSION > 30100 ++ #define ASSERT(exp) do {} while (0) ++ #else ++ /* ASSERT could cause segmentation fault on GCC3.1, use empty instead */ ++ #define ASSERT(exp) ++ #endif /* GCC_VERSION > 30100 */ ++ #endif /* __GNUC__ */ ++ ++/* microsecond delay */ ++#define OSL_DELAY(usec) osl_delay(usec) ++extern void osl_delay(uint usec); ++ ++#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_read_attr((osh), (offset), (buf), (size)) ++#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_write_attr((osh), (offset), (buf), (size)) ++extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); ++extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); ++ ++/* PCI configuration space access macros */ ++#define OSL_PCI_READ_CONFIG(osh, offset, size) \ ++ osl_pci_read_config((osh), (offset), (size)) ++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ ++ osl_pci_write_config((osh), (offset), (size), (val)) ++extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size); ++extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); ++ ++/* PCI device bus # and slot # */ ++#define OSL_PCI_BUS(osh) osl_pci_bus(osh) ++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) ++extern uint osl_pci_bus(osl_t *osh); ++extern uint osl_pci_slot(osl_t *osh); ++extern struct pci_dev *osl_pci_device(osl_t *osh); ++ ++/* Pkttag flag should be part of public information */ ++typedef struct { ++ bool pkttag; ++ bool mmbus; /* Bus supports memory-mapped register accesses */ ++ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ ++ void *tx_ctx; /* Context to the callback function */ ++#ifdef OSLREGOPS ++ osl_rreg_fn_t rreg_fn; /* Read Register function */ ++ osl_wreg_fn_t wreg_fn; /* Write Register function */ ++ void *reg_ctx; /* Context to the reg callback functions */ ++#else ++ void *unused[3]; ++#endif ++} osl_pubinfo_t; ++ ++#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ ++ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ ++ } while (0) ++ ++#ifdef OSLREGOPS ++#define REGOPSSET(osh, rreg, wreg, ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->rreg_fn = rreg; \ ++ ((osl_pubinfo_t*)osh)->wreg_fn = wreg; \ ++ ((osl_pubinfo_t*)osh)->reg_ctx = ctx; \ ++ } while (0) ++#endif /* OSLREGOPS */ ++ ++/* host/bus architecture-specific byte swap */ ++// #define BUS_SWAP32(v) (v) /* JIRA:LINUXDEV-16 */ ++#ifdef IL_BIGENDIAN ++#define BUS_SWAP32(v) bcmswap32(v) ++#else ++#define BUS_SWAP32(v) (v) ++#endif /* IL_BIGENDIAN */ ++ ++ #define MALLOC(osh, size) osl_malloc((osh), (size)) ++ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) ++ #define MALLOCED(osh) osl_malloced((osh)) ++ extern void *osl_malloc(osl_t *osh, uint size); ++ extern void osl_mfree(osl_t *osh, void *addr, uint size); ++ extern uint osl_malloced(osl_t *osh); ++ ++#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC) ++#define NATIVE_MFREE(osh, addr, size) kfree(addr) ++#ifdef USBAP ++#include ++#define VMALLOC(osh, size) vmalloc(size) ++#define VFREE(osh, addr, size) vfree(addr) ++#endif /* USBAP */ ++ ++#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) ++extern uint osl_malloc_failed(osl_t *osh); ++ ++/* allocate/free shared (dma-able) consistent memory */ ++#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align() ++#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \ ++ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap)) ++#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ ++ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) ++extern uint osl_dma_consistent_align(void); ++extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap); ++extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); ++ ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ ++ ++/* map/unmap shared (dma-able) memory */ ++#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ ++ osl_dma_unmap((osh), (pa), (size), (direction)) ++extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah); ++extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); ++ ++/* API for DMA addressing capability */ ++#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) ++ ++/* register access macros */ ++ ++ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op ++ #define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op ++ ++#define OSL_ERROR(bcmerror) osl_error(bcmerror) ++extern int osl_error(int bcmerror); ++ ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ * Macros expand to calls to functions defined in linux_osl.c . ++ */ ++#ifndef BINOSL ++#include /* use current 2.4.x calling conventions */ ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++ ++#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) ++#define printf(fmt, args...) printk(fmt , ## args) ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++/* bcopy's: Linux kernel doesn't provide these (anymore) */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++ ++/* register access macros */ ++#if defined(OSLREGOPS) ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((osh), (volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((osh), (volatile uint16*)(r)) : \ ++ osl_readl((osh), (volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): osl_writeb((osh), (volatile uint8*)(r), (uint8)(v)); break; \ ++ case sizeof(uint16): osl_writew((osh), (volatile uint16*)(r), (uint16)(v)); break; \ ++ case sizeof(uint32): osl_writel((osh), (volatile uint32*)(r), (uint32)(v)); break; \ ++ } \ ++} while (0) ++ ++extern uint8 osl_readb(osl_t *osh, volatile uint8 *r); ++extern uint16 osl_readw(osl_t *osh, volatile uint16 *r); ++extern uint32 osl_readl(osl_t *osh, volatile uint32 *r); ++extern void osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v); ++extern void osl_writew(osl_t *osh, volatile uint16 *r, uint16 v); ++extern void osl_writel(osl_t *osh, volatile uint32 *r, uint32 v); ++#else /* OSLREGOPS */ ++ ++#ifndef IL_BIGENDIAN ++#ifndef __mips__ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++#else /* __mips__ */ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ __asm__ __volatile__("sync"); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v; \ ++ }), \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v = OSL_READ_REG(osh, r); \ ++ __asm__ __volatile__("sync"); \ ++ __osl_v; \ ++ })) \ ++) ++#endif /* __mips__ */ ++ ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++#else /* IL_BIGENDIAN */ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)((uintptr)(r)^3)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)((uintptr)(r)^2)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), \ ++ (volatile uint8*)((uintptr)(r)^3)); break; \ ++ case sizeof(uint16): writew((uint16)(v), \ ++ (volatile uint16*)((uintptr)(r)^2)); break; \ ++ case sizeof(uint32): writel((uint32)(v), \ ++ (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++#endif /* IL_BIGENDIAN */ ++#endif /* OSLREGOPS */ ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++ ++/* bcopy, bcmp, and bzero functions */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++/* uncached/cached virtual address */ ++#ifdef __mips__ ++#include ++#define OSL_UNCACHED(va) ((void *)KSEG1ADDR((va))) ++#define OSL_CACHED(va) ((void *)KSEG0ADDR((va))) ++#else ++#define OSL_UNCACHED(va) ((void *)va) ++#define OSL_CACHED(va) ((void *)va) ++ ++/* ARM NorthStar */ ++#define OSL_CACHE_FLUSH(va, len) ++ ++#endif /* mips */ ++ ++#ifdef __mips__ ++#define OSL_PREF_RANGE_LD(va, sz) prefetch_range_PREF_LOAD_RETAINED(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) prefetch_range_PREF_STORE_RETAINED(va, sz) ++#else /* __mips__ */ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++#endif /* __mips__ */ ++ ++/* get processor cycle count */ ++#if defined(mips) ++#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) ++#elif defined(__i386__) ++#define OSL_GETCYCLES(x) rdtscl((x)) ++#else ++#define OSL_GETCYCLES(x) ((x) = 0) ++#endif /* defined(mips) */ ++ ++/* dereference an address that may cause a bus exception */ ++#ifdef mips ++#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) ++#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into"\ ++ " a module") ++#else ++#define BUSPROBE(val, addr) get_dbe((val), (addr)) ++#include ++#endif /* defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) */ ++#else ++#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) ++#endif /* mips */ ++ ++/* map/unmap physical to virtual I/O */ ++#if !defined(CONFIG_MMC_MSM7X00A) ++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) ++#else ++#define REG_MAP(pa, size) (void *)(0) ++#endif /* !defined(CONFIG_MMC_MSM7X00A */ ++#define REG_UNMAP(va) iounmap((va)) ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) memset((r), '\0', (len)) ++ ++/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for ++ * performance reasons), we need the Linux headers. ++ */ ++#include /* use current 2.4.x calling conventions */ ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#ifdef DHD_USE_STATIC_BUF ++#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) ++#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) ++#endif /* DHD_USE_STATIC_BUF */ ++#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) ++#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) ++#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) ++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) ++#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) ++#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) ++#define PKTSETLEN(osh, skb, len) __pskb_trim((struct sk_buff*)(skb), (len)) ++#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) ++#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++#define PKTSHRINK(osh, m) (m) ++ ++#ifdef CTFPOOL ++#define CTFPOOL_REFILL_THRESH 3 ++typedef struct ctfpool { ++ void *head; ++ spinlock_t lock; ++ uint max_obj; ++ uint curr_obj; ++ uint obj_size; ++ uint refills; ++ uint fast_allocs; ++ uint fast_frees; ++ uint slow_allocs; ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ int unit; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++} ctfpool_t; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && defined CONFIG_BCM_CTF2 ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags) ++#else ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define FASTBUF (0xFFF00000) ++#else ++#define FASTBUF (1 << 4) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#define CTFBUF (1 << 5) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->ctfpool_tag) == FASTBUF) ++#else ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->ctfpool_tag) ++#else ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif /* 2.6.36 */ ++ ++#else ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) ++#endif /* 2.6.22 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) ++#else ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) ++#else ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++#endif ++ ++extern void *osl_ctfpool_add(osl_t *osh); ++extern void osl_ctfpool_replenish(osl_t *osh, uint thresh); ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++extern int32 osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size); ++#else ++extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size); ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++extern void osl_ctfpool_cleanup(osl_t *osh); ++extern void osl_ctfpool_stats(osl_t *osh, void *b); ++#else ++#define FASTBUF (1 << 16) ++#define CTFBUF (1 << 17) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#endif /* CTFPOOL */ ++ ++#ifdef CTFMAP ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->sp) ++#else /* 2.6.14 */ ++#define CTFMAPPTR(osh, skb) (((struct sk_buff*)(skb))->list) ++#endif /* 2.6.14 */ ++ ++#define PKTCTFMAP(osh, p) \ ++do { \ ++ if (PKTISCTF(osh, p)) { \ ++ int32 sz; \ ++ sz = (uint32)(((struct sk_buff *)p)->end) - \ ++ (uint32)CTFMAPPTR(osh, p); \ ++ /* map the remaining unmapped area */ \ ++ if (sz > 0) { \ ++ _DMA_MAP(osh, (void *)CTFMAPPTR(osh, p), \ ++ sz, DMA_RX, p, NULL); \ ++ } \ ++ /* clear ctf buf flag */ \ ++ PKTCLRCTF(osh, p); \ ++ CTFMAPPTR(osh, p) = NULL; \ ++ } \ ++} while (0) ++#endif /* CTFMAP */ ++ ++#ifdef HNDCTF ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++#define SKIPCT (1 << 2) ++#define CHAINED (1 << 3) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED) ++#else ++#define SKIPCT (1 << 18) ++#define CHAINED (1 << 19) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED) ++#endif /* 2.6.36 */ ++#else /* 2.6.22 */ ++#define SKIPCT (1 << 2) ++#define CHAINED (1 << 3) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT) ++#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused |= CHAINED) ++#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~CHAINED)) ++#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED) ++#endif /* 2.6.22 */ ++typedef struct ctf_mark { ++ uint32 value; ++} ctf_mark_t; ++#define CTF_MARK(m) (m.value) ++#else /* HNDCTF */ ++#define PKTSETSKIPCT(osh, skb) ++#define PKTCLRSKIPCT(osh, skb) ++#define PKTSKIPCT(osh, skb) ++#define PKTCLRCHAINED(osh, skb) ++#define PKTSETCHAINED(osh, skb) ++#define CTF_MARK(m) 0 ++#endif /* HNDCTF */ ++ ++#ifdef BCMFA ++#ifdef BCMFA_HW_HASH ++#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx) ++#else ++#define PKTSETFAHIDX(skb, idx) ++#endif /* BCMFA_SW_HASH */ ++#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx) ++#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp) ++#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev) ++ ++#define AUX_TCP_FIN_RST (1 << 0) ++#define AUX_FREED (1 << 1) ++#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST) ++#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST)) ++#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST) ++#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED) ++#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED)) ++#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED) ++#define PKTISFABRIDGED(skb) PKTISFAAUX(skb) ++#else ++#define PKTISFAAUX(skb) (FALSE) ++#define PKTISFABRIDGED(skb) (FALSE) ++#define PKTISFAFREED(skb) (FALSE) ++ ++#define PKTCLRFAAUX(skb) ++#define PKTSETFAFREED(skb) ++#define PKTCLRFAFREED(skb) ++#endif /* BCMFA */ ++ ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern void *osl_pktget_static(osl_t *osh, uint len); ++extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); ++ ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) ++ ++#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) ++#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) ++#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) ++#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) ++#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) ++#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ ++ ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) ++/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ ++#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) ++ ++#ifdef CONFIG_NF_CONNTRACK_MARK ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define PKTMARK(p) (((struct sk_buff *)(p))->mark) ++#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m) ++#else /* !2.6.0 */ ++#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) ++#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) ++#endif /* 2.6.0 */ ++#else /* CONFIG_NF_CONNTRACK_MARK */ ++#define PKTMARK(p) 0 ++#define PKTSETMARK(p, m) ++#endif /* CONFIG_NF_CONNTRACK_MARK */ ++ ++#else /* BINOSL */ ++ ++/* Where to get the declarations for mem, str, printf, bcopy's? Two basic approaches. ++ * ++ * First, use the Linux header files and the C standard library replacmenent versions ++ * built-in to the kernel. Use this approach when compiling non hybrid code or compling ++ * the OS port files. The second approach is to use our own defines/prototypes and ++ * functions we have provided in the Linux OSL, i.e. linux_osl.c. Use this approach when ++ * compiling the files that make up the hybrid binary. We are ensuring we ++ * don't directly link to the kernel replacement routines from the hybrid binary. ++ * ++ * NOTE: The issue we are trying to avoid is any questioning of whether the ++ * hybrid binary is derived from Linux. The wireless common code (wlc) is designed ++ * to be OS independent through the use of the OSL API and thus the hybrid binary doesn't ++ * derive from the Linux kernel at all. But since we defined our OSL API to include ++ * a small collection of standard C library routines and these routines are provided in ++ * the kernel we want to avoid even the appearance of deriving at all even though clearly ++ * usage of a C standard library API doesn't represent a derivation from Linux. Lastly ++ * note at the time of this checkin 4 references to memcpy/memset could not be eliminated ++ * from the binary because they are created internally by GCC as part of things like ++ * structure assignment. I don't think the compiler should be doing this but there is ++ * no options to disable it on Intel architectures (there is for MIPS so somebody must ++ * agree with me). I may be able to even remove these references eventually with ++ * a GNU binutil such as objcopy via a symbol rename (i.e. memcpy to osl_memcpy). ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++ #define printf(fmt, args...) printk(fmt , ## args) ++ #include /* for vsn/printf's */ ++ #include /* for mem*, str* */ ++ /* bcopy's: Linux kernel doesn't provide these (anymore) */ ++ #define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++ #define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++ #define bzero(b, len) memset((b), '\0', (len)) ++ ++ /* These are provided only because when compiling linux_osl.c there ++ * must be an explicit prototype (separate from the definition) because ++ * we are compiling with GCC option -Wstrict-prototypes. Conversely ++ * these could be placed directly in linux_osl.c. ++ */ ++ extern int osl_printf(const char *format, ...); ++ extern int osl_sprintf(char *buf, const char *format, ...); ++ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); ++ extern int osl_vsprintf(char *buf, const char *format, va_list ap); ++ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); ++ extern int osl_strcmp(const char *s1, const char *s2); ++ extern int osl_strncmp(const char *s1, const char *s2, uint n); ++ extern int osl_strlen(const char *s); ++ extern char* osl_strcpy(char *d, const char *s); ++ extern char* osl_strncpy(char *d, const char *s, uint n); ++ extern char* osl_strchr(const char *s, int c); ++ extern char* osl_strrchr(const char *s, int c); ++ extern void *osl_memset(void *d, int c, size_t n); ++ extern void *osl_memcpy(void *d, const void *s, size_t n); ++ extern void *osl_memmove(void *d, const void *s, size_t n); ++ extern int osl_memcmp(const void *s1, const void *s2, size_t n); ++#else ++ ++ /* In the below defines we undefine the macro first in case it is ++ * defined. This shouldn't happen because we are not using Linux ++ * header files but because our Linux 2.4 make includes modversions.h ++ * through a GCC -include compile option, they get defined to point ++ * at the appropriate versioned symbol name. Note this doesn't ++ * happen with our Linux 2.6 makes. ++ */ ++ ++ /* *printf functions */ ++ #include /* va_list needed for v*printf */ ++ #include /* size_t needed for *nprintf */ ++ #undef printf ++ #undef sprintf ++ #undef snprintf ++ #undef vsprintf ++ #undef vsnprintf ++ #define printf(fmt, args...) osl_printf((fmt) , ## args) ++ #define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt) , ## args) ++ #define snprintf(buf, n, fmt, args...) osl_snprintf((buf), (n), (fmt) , ## args) ++ #define vsprintf(buf, fmt, ap) osl_vsprintf((buf), (fmt), (ap)) ++ #define vsnprintf(buf, n, fmt, ap) osl_vsnprintf((buf), (n), (fmt), (ap)) ++ extern int osl_printf(const char *format, ...); ++ extern int osl_sprintf(char *buf, const char *format, ...); ++ extern int osl_snprintf(char *buf, size_t n, const char *format, ...); ++ extern int osl_vsprintf(char *buf, const char *format, va_list ap); ++ extern int osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap); ++ ++ /* str* functions */ ++ #undef strcmp ++ #undef strncmp ++ #undef strlen ++ #undef strcpy ++ #undef strncpy ++ #undef strchr ++ #undef strrchr ++ #define strcmp(s1, s2) osl_strcmp((s1), (s2)) ++ #define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n)) ++ #define strlen(s) osl_strlen((s)) ++ #define strcpy(d, s) osl_strcpy((d), (s)) ++ #define strncpy(d, s, n) osl_strncpy((d), (s), (n)) ++ #define strchr(s, c) osl_strchr((s), (c)) ++ #define strrchr(s, c) osl_strrchr((s), (c)) ++ extern int osl_strcmp(const char *s1, const char *s2); ++ extern int osl_strncmp(const char *s1, const char *s2, uint n); ++ extern int osl_strlen(const char *s); ++ extern char* osl_strcpy(char *d, const char *s); ++ extern char* osl_strncpy(char *d, const char *s, uint n); ++ extern char* osl_strchr(const char *s, int c); ++ extern char* osl_strrchr(const char *s, int c); ++ ++ /* mem* functions */ ++ #undef memset ++ #undef memcpy ++ #undef memcmp ++ #define memset(d, c, n) osl_memset((d), (c), (n)) ++ #define memcpy(d, s, n) osl_memcpy((d), (s), (n)) ++ #define memmove(d, s, n) osl_memmove((d), (s), (n)) ++ #define memcmp(s1, s2, n) osl_memcmp((s1), (s2), (n)) ++ extern void *osl_memset(void *d, int c, size_t n); ++ extern void *osl_memcpy(void *d, const void *s, size_t n); ++ extern void *osl_memmove(void *d, const void *s, size_t n); ++ extern int osl_memcmp(const void *s1, const void *s2, size_t n); ++ ++ /* bcopy, bcmp, and bzero functions */ ++ #undef bcopy ++ #undef bcmp ++ #undef bzero ++ #define bcopy(src, dst, len) osl_memcpy((dst), (src), (len)) ++ #define bcmp(b1, b2, len) osl_memcmp((b1), (b2), (len)) ++ #define bzero(b, len) osl_memset((b), '\0', (len)) ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++/* register access macros */ ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \ ++ osl_readl((volatile uint32*)(r)) \ ++) ++#define W_REG(osh, r, v) do { \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ } \ ++} while (0) ++ ++/* else added by johnvb to make sdio and jtag work with BINOSL, at least compile ... UNTESTED */ ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++extern uint8 osl_readb(volatile uint8 *r); ++extern uint16 osl_readw(volatile uint16 *r); ++extern uint32 osl_readl(volatile uint32 *r); ++extern void osl_writeb(uint8 v, volatile uint8 *r); ++extern void osl_writew(uint16 v, volatile uint16 *r); ++extern void osl_writel(uint32 v, volatile uint32 *r); ++ ++/* system up time in ms */ ++#define OSL_SYSUPTIME() osl_sysuptime() ++extern uint32 osl_sysuptime(void); ++ ++/* uncached/cached virtual address */ ++#define OSL_UNCACHED(va) osl_uncached((va)) ++extern void *osl_uncached(void *va); ++#define OSL_CACHED(va) osl_cached((va)) ++extern void *osl_cached(void *va); ++ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++ ++/* get processor cycle count */ ++#define OSL_GETCYCLES(x) ((x) = osl_getcycles()) ++extern uint osl_getcycles(void); ++ ++/* dereference an address that may target abort */ ++#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr)) ++extern int osl_busprobe(uint32 *val, uint32 addr); ++ ++/* map/unmap physical to virtual */ ++#define REG_MAP(pa, size) osl_reg_map((pa), (size)) ++#define REG_UNMAP(va) osl_reg_unmap((va)) ++extern void *osl_reg_map(uint32 pa, uint size); ++extern void osl_reg_unmap(void *va); ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) bzero((r), (len)) ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#define PKTDATA(osh, skb) osl_pktdata((osh), (skb)) ++#define PKTLEN(osh, skb) osl_pktlen((osh), (skb)) ++#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb)) ++#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb)) ++#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb)) ++#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x)) ++#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len)) ++#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes)) ++#define PKTTAG(skb) osl_pkttag((skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt)) ++#define PKTLINK(skb) osl_pktlink((skb)) ++#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x)) ++#define PKTPRIO(skb) osl_pktprio((skb)) ++#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x)) ++#define PKTSHARED(skb) osl_pktshared((skb)) ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++ ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern uchar *osl_pktdata(osl_t *osh, void *skb); ++extern uint osl_pktlen(osl_t *osh, void *skb); ++extern uint osl_pktheadroom(osl_t *osh, void *skb); ++extern uint osl_pkttailroom(osl_t *osh, void *skb); ++extern void *osl_pktnext(osl_t *osh, void *skb); ++extern void osl_pktsetnext(void *skb, void *x); ++extern void osl_pktsetlen(osl_t *osh, void *skb, uint len); ++extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes); ++extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes); ++extern void *osl_pkttag(void *skb); ++extern void *osl_pktlink(void *skb); ++extern void osl_pktsetlink(void *skb, void *x); ++extern uint osl_pktprio(void *skb); ++extern void osl_pktsetprio(void *skb, uint x); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++extern bool osl_pktshared(void *skb); ++ ++ ++#endif /* BINOSL */ ++ ++#define PKTALLOCED(osh) osl_pktalloced(osh) ++extern uint osl_pktalloced(osl_t *osh); ++ ++#ifdef CTFMAP ++#include ++#define CTFMAPSZ 320 ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++({ \ ++ typeof(size) sz = (size); \ ++ if (PKTISCTF((osh), (p))) { \ ++ sz = CTFMAPSZ; \ ++ CTFMAPPTR((osh), (p)) = (void *)(((uint8 *)(va)) + CTFMAPSZ); \ ++ } \ ++ osl_dma_map((osh), (va), sz, (direction), (p), (dmah)); \ ++}) ++#define _DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++#else /* CTFMAP */ ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++#endif /* CTFMAP */ ++ ++#ifdef PKTC ++/* Use 8 bytes of skb tstamp field to store below info */ ++struct chain_node { ++ struct sk_buff *link; ++ unsigned int flags:3, pkts:9, bytes:20; ++}; ++ ++#define CHAIN_NODE(skb) ((struct chain_node*)(((struct sk_buff*)skb)->pktc_cb)) ++ ++#define PKTCSETATTR(s, f, p, b) ({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \ ++ CHAIN_NODE(s)->bytes = (b);}) ++#define PKTCCLRATTR(s) ({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \ ++ CHAIN_NODE(s)->bytes = 0;}) ++#define PKTCGETATTR(s) (CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \ ++ CHAIN_NODE(s)->bytes) ++#define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts) ++#define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes) ++#define PKTCGETFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETFLAGS(skb, f) (CHAIN_NODE(skb)->flags = (f)) ++#define PKTCCLRFLAGS(skb) (CHAIN_NODE(skb)->flags = 0) ++#define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c)) ++#define PKTCINCRCNT(skb) (CHAIN_NODE(skb)->pkts++) ++#define PKTCADDCNT(skb, c) (CHAIN_NODE(skb)->pkts += (c)) ++#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l)) ++#define PKTCADDLEN(skb, l) (CHAIN_NODE(skb)->bytes += (l)) ++#define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb)) ++#define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb)) ++#define PKTCLINK(skb) (CHAIN_NODE(skb)->link) ++#define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x)) ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for (; (skb) != NULL; (skb) = (nskb)) \ ++ if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \ ++ PKTSETCLINK((skb), NULL), 1) ++#define PKTCFREE(osh, skb, send) \ ++do { \ ++ void *nskb; \ ++ ASSERT((skb) != NULL); \ ++ FOREACH_CHAINED_PKT((skb), nskb) { \ ++ PKTCLRCHAINED((osh), (skb)); \ ++ PKTCCLRFLAGS((skb)); \ ++ PKTFREE((osh), (skb), (send)); \ ++ } \ ++} while (0) ++#define PKTCENQTAIL(h, t, p) \ ++do { \ ++ if ((t) == NULL) { \ ++ (h) = (t) = (p); \ ++ } else { \ ++ PKTSETCLINK((t), (p)); \ ++ (t) = (p); \ ++ } \ ++} while (0) ++#endif /* PKTC */ ++ ++#else /* ! BCMDRIVER */ ++ ++ ++/* ASSERT */ ++ #define ASSERT(exp) do {} while (0) ++ ++/* MALLOC and MFREE */ ++#define MALLOC(o, l) malloc(l) ++#define MFREE(o, p, l) free(p) ++#include ++ ++/* str* and mem* functions */ ++#include ++ ++/* *printf functions */ ++#include ++ ++/* bcopy, bcmp, and bzero */ ++extern void bcopy(const void *src, void *dst, size_t len); ++extern int bcmp(const void *b1, const void *b2, size_t len); ++extern void bzero(void *b, size_t len); ++#endif /* ! BCMDRIVER */ ++ ++#endif /* _linux_osl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/linuxver.h b/drivers/bcmdrivers/gmac/src/include/linuxver.h +new file mode 100755 +index 0000000..6150c05 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/linuxver.h +@@ -0,0 +1,662 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux-specific abstractions to gain some independence from linux kernel versions. ++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. ++ * ++ * $Id: linuxver.h 312774 2012-02-03 22:20:14Z $ ++ */ ++ ++#ifndef _linuxver_h_ ++#define _linuxver_h_ ++ ++#include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#include ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) ++#include ++#else ++#include ++#endif ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) ++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ ++#ifdef __UNDEF_NO_VERSION__ ++#undef __NO_VERSION__ ++#else ++#define __NO_VERSION__ ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) ++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") ++#define module_param_string(_name_, _string_, _size_, _perm_) \ ++ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) ++#endif ++ ++/* linux/malloc.h is deprecated, use linux/slab.h instead. */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#include ++#else ++#include ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) ++#undef IP_TOS ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */ ++#include ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) ++#include ++#else ++#include ++#ifndef work_struct ++#define work_struct tq_struct ++#endif ++#ifndef INIT_WORK ++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) ++#endif ++#ifndef schedule_work ++#define schedule_work(_work) schedule_task((_work)) ++#endif ++#ifndef flush_scheduled_work ++#define flush_scheduled_work() flush_scheduled_tasks() ++#endif ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func) ++#else ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work) ++typedef void (*work_func_t)(void *work); ++#endif /* >= 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* Some distributions have their own 2.6.x compatibility layers */ ++#ifndef IRQ_NONE ++typedef void irqreturn_t; ++#define IRQ_NONE ++#define IRQ_HANDLED ++#define IRQ_RETVAL(x) ++#endif ++#else ++typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) ++#define IRQF_SHARED SA_SHIRQ ++#endif /* < 2.6.18 */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) ++#ifdef CONFIG_NET_RADIO ++#define CONFIG_WIRELESS_EXT ++#endif ++#endif /* < 2.6.17 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) ++#define MOD_INC_USE_COUNT ++#define MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#include ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ ++ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) ++#include ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++#include ++#include ++#endif ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)) ++/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which ++ * does this, but it's not in 2.4 so we do our own for now. ++ */ ++static inline void ++cs_error(client_handle_t handle, int func, int ret) ++{ ++ error_info_t err = { func, ret }; ++ CardServices(ReportError, handle, &err); ++} ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 16)) ++ ++typedef struct pcmcia_device dev_link_t; ++ ++#endif ++ ++#endif /* CONFIG_PCMCIA */ ++ ++#ifndef __exit ++#define __exit ++#endif ++#ifndef __devexit ++#define __devexit ++#endif ++#ifndef __devinit ++#define __devinit __init ++#endif ++#ifndef __devinitdata ++#define __devinitdata ++#endif ++#ifndef __devexit_p ++#define __devexit_p(x) x ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) ++ ++#define pci_get_drvdata(dev) (dev)->sysdata ++#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) ++ ++/* ++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration ++ */ ++ ++struct pci_device_id { ++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ ++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ ++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ ++ unsigned long driver_data; /* Data private to the driver */ ++}; ++ ++struct pci_driver { ++ struct list_head node; ++ char *name; ++ const struct pci_device_id *id_table; /* NULL if wants all devices */ ++ int (*probe)(struct pci_dev *dev, ++ const struct pci_device_id *id); /* New device inserted */ ++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug ++ * capable driver) ++ */ ++ void (*suspend)(struct pci_dev *dev); /* Device suspended */ ++ void (*resume)(struct pci_dev *dev); /* Device woken up */ ++}; ++ ++#define MODULE_DEVICE_TABLE(type, name) ++#define PCI_ANY_ID (~0) ++ ++/* compatpci.c */ ++#define pci_module_init pci_register_driver ++extern int pci_register_driver(struct pci_driver *drv); ++extern void pci_unregister_driver(struct pci_driver *drv); ++ ++#endif /* PCI registration */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) ++#define pci_module_init pci_register_driver ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) ++#ifdef MODULE ++#define module_init(x) int init_module(void) { return x(); } ++#define module_exit(x) void cleanup_module(void) { x(); } ++#else ++#define module_init(x) __initcall(x); ++#define module_exit(x) __exitcall(x); ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) ++#define WL_USE_NETDEV_OPS ++#else ++#undef WL_USE_NETDEV_OPS ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL) ++#define WL_CONFIG_RFKILL ++#else ++#undef WL_CONFIG_RFKILL ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) ++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) ++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) ++#define pci_enable_device(dev) do { } while (0) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) ++#define net_device device ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) ++ ++/* ++ * DMA mapping ++ * ++ * See linux/Documentation/DMA-mapping.txt ++ */ ++ ++#ifndef PCI_DMA_TODEVICE ++#define PCI_DMA_TODEVICE 1 ++#define PCI_DMA_FROMDEVICE 2 ++#endif ++ ++typedef u32 dma_addr_t; ++ ++/* Pure 2^n version of get_order */ ++static inline int get_order(unsigned long size) ++{ ++ int order; ++ ++ size = (size-1) >> (PAGE_SHIFT-1); ++ order = -1; ++ do { ++ size >>= 1; ++ order++; ++ } while (size); ++ return order; ++} ++ ++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ++ dma_addr_t *dma_handle) ++{ ++ void *ret; ++ int gfp = GFP_ATOMIC | GFP_DMA; ++ ++ ret = (void *)__get_free_pages(gfp, get_order(size)); ++ ++ if (ret != NULL) { ++ memset(ret, 0, size); ++ *dma_handle = virt_to_bus(ret); ++ } ++ return ret; ++} ++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, ++ void *vaddr, dma_addr_t dma_handle) ++{ ++ free_pages((unsigned long)vaddr, get_order(size)); ++} ++#ifdef ILSIM ++extern uint pci_map_single(void *dev, void *va, uint size, int direction); ++extern void pci_unmap_single(void *dev, uint pa, uint size, int direction); ++#else ++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) ++#define pci_unmap_single(cookie, address, size, dir) ++#endif ++ ++#endif /* DMA mapping */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) ++ ++#define dev_kfree_skb_any(a) dev_kfree_skb(a) ++#define netif_down(dev) do { (dev)->start = 0; } while (0) ++ ++/* pcmcia-cs provides its own netdevice compatibility layer */ ++#ifndef _COMPAT_NETDEVICE_H ++ ++/* ++ * SoftNet ++ * ++ * For pre-softnet kernels we need to tell the upper layer not to ++ * re-enter start_xmit() while we are in there. However softnet ++ * guarantees not to enter while we are in there so there is no need ++ * to do the netif_stop_queue() dance unless the transmit queue really ++ * gets stuck. This should also improve performance according to tests ++ * done by Aman Singla. ++ */ ++ ++#define dev_kfree_skb_irq(a) dev_kfree_skb(a) ++#define netif_wake_queue(dev) \ ++ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) ++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) ++ ++static inline void netif_start_queue(struct net_device *dev) ++{ ++ dev->tbusy = 0; ++ dev->interrupt = 0; ++ dev->start = 1; ++} ++ ++#define netif_queue_stopped(dev) (dev)->tbusy ++#define netif_running(dev) (dev)->start ++ ++#endif /* _COMPAT_NETDEVICE_H */ ++ ++#define netif_device_attach(dev) netif_start_queue(dev) ++#define netif_device_detach(dev) netif_stop_queue(dev) ++ ++/* 2.4.x renamed bottom halves to tasklets */ ++#define tasklet_struct tq_struct ++static inline void tasklet_schedule(struct tasklet_struct *tasklet) ++{ ++ queue_task(tasklet, &tq_immediate); ++ mark_bh(IMMEDIATE_BH); ++} ++ ++static inline void tasklet_init(struct tasklet_struct *tasklet, ++ void (*func)(unsigned long), ++ unsigned long data) ++{ ++ tasklet->next = NULL; ++ tasklet->sync = 0; ++ tasklet->routine = (void (*)(void *))func; ++ tasklet->data = (void *)data; ++} ++#define tasklet_kill(tasklet) { do {} while (0); } ++ ++/* 2.4.x introduced del_timer_sync() */ ++#define del_timer_sync(timer) del_timer(timer) ++ ++#else ++ ++#define netif_down(dev) ++ ++#endif /* SoftNet */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) ++ ++/* ++ * Emit code to initialise a tq_struct's routine and data pointers ++ */ ++#define PREPARE_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ (_tq)->routine = _routine; \ ++ (_tq)->data = _data; \ ++ } while (0) ++ ++/* ++ * Emit code to initialise all of a tq_struct ++ */ ++#define INIT_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ INIT_LIST_HEAD(&(_tq)->list); \ ++ (_tq)->sync = 0; \ ++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ ++ } while (0) ++ ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */ ++ ++/* Power management related macro & routines */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9) ++#define PCI_SAVE_STATE(a, b) pci_save_state(a) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a) ++#else ++#define PCI_SAVE_STATE(a, b) pci_save_state(a, b) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) ++static inline int ++pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_read_config_dword(dev, i * 4, &buffer[i]); ++ } ++ return 0; ++} ++ ++static inline int ++pci_restore_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_write_config_dword(dev, i * 4, buffer[i]); ++ } ++ /* ++ * otherwise, write the context information we know from bootup. ++ * This works around a problem where warm-booting from Windows ++ * combined with a D3(hot)->D0 transition causes PCI config ++ * header data to be forgotten. ++ */ ++ else { ++ for (i = 0; i < 6; i ++) ++ pci_write_config_dword(dev, ++ PCI_BASE_ADDRESS_0 + (i * 4), ++ pci_resource_start(dev, i)); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ } ++ return 0; ++} ++#endif /* PCI power management */ ++ ++/* Old cp0 access macros deprecated in 2.4.19 */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) ++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) ++#endif ++ ++/* Module refcount handled internally in 2.6.x */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#else ++#define OLD_MOD_INC_USE_COUNT do {} while (0) ++#define OLD_MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#endif ++#ifndef MOD_INC_USE_COUNT ++#define MOD_INC_USE_COUNT do {} while (0) ++#endif ++#ifndef MOD_DEC_USE_COUNT ++#define MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++ ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) do {} while (0) ++#endif ++ ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(dev) kfree(dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* struct packet_type redefined in 2.6.x */ ++#define af_packet_priv data ++#endif ++ ++/* suspend args */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) ++#define DRV_SUSPEND_STATE_TYPE pm_message_t ++#else ++#define DRV_SUSPEND_STATE_TYPE uint32 ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define CHECKSUM_HW CHECKSUM_PARTIAL ++#endif ++ ++typedef struct { ++ void *parent; /* some external entity that the thread supposed to work for */ ++ struct task_struct *p_task; ++ long thr_pid; ++ int prio; /* priority */ ++ struct semaphore sema; ++ int terminated; ++ struct completion completed; ++} tsk_ctl_t; ++ ++ ++/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */ ++/* note this macro assumes there may be only one context waiting on thread's completion */ ++#ifdef DHD_DEBUG ++#define DBG_THR(x) printk x ++#else ++#define DBG_THR(x) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) ++#else ++#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) ++#endif ++ ++ ++#define PROC_START(thread_func, owner, tsk_ctl, flags) \ ++{ \ ++ sema_init(&((tsk_ctl)->sema), 0); \ ++ init_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->parent = owner; \ ++ (tsk_ctl)->terminated = FALSE; \ ++ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ ++ if ((tsk_ctl)->thr_pid > 0) \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++} ++ ++#define PROC_STOP(tsk_ctl) \ ++{ \ ++ (tsk_ctl)->terminated = TRUE; \ ++ smp_wmb(); \ ++ up(&((tsk_ctl)->sema)); \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++ (tsk_ctl)->thr_pid = -1; \ ++} ++ ++/* ----------------------- */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) ++#define KILL_PROC(nr, sig) \ ++{ \ ++struct task_struct *tsk; \ ++struct pid *pid; \ ++pid = find_get_pid((pid_t)nr); \ ++tsk = pid_task(pid, PIDTYPE_PID); \ ++if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ ++ KERNEL_VERSION(2, 6, 30)) ++#define KILL_PROC(pid, sig) \ ++{ \ ++ struct task_struct *tsk; \ ++ tsk = find_task_by_vpid(pid); \ ++ if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#define KILL_PROC(pid, sig) \ ++{ \ ++ kill_proc(pid, sig, 1); \ ++} ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#include ++#include ++#else ++#include ++ ++#define __wait_event_interruptible_timeout(wq, condition, ret) \ ++do { \ ++ wait_queue_t __wait; \ ++ init_waitqueue_entry(&__wait, current); \ ++ \ ++ add_wait_queue(&wq, &__wait); \ ++ for (;;) { \ ++ set_current_state(TASK_INTERRUPTIBLE); \ ++ if (condition) \ ++ break; \ ++ if (!signal_pending(current)) { \ ++ ret = schedule_timeout(ret); \ ++ if (!ret) \ ++ break; \ ++ continue; \ ++ } \ ++ ret = -ERESTARTSYS; \ ++ break; \ ++ } \ ++ current->state = TASK_RUNNING; \ ++ remove_wait_queue(&wq, &__wait); \ ++} while (0) ++ ++#define wait_event_interruptible_timeout(wq, condition, timeout) \ ++({ \ ++ long __ret = timeout; \ ++ if (!(condition)) \ ++ __wait_event_interruptible_timeout(wq, condition, __ret); \ ++ __ret; \ ++}) ++ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ ++ ++/* ++For < 2.6.24, wl creates its own netdev but doesn't ++align the priv area like the genuine alloc_netdev(). ++Since netdev_priv() always gives us the aligned address, it will ++not match our unaligned address for < 2.6.24 ++*/ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#define DEV_PRIV(dev) (dev->priv) ++#else ++#define DEV_PRIV(dev) netdev_priv(dev) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++#define WL_ISR(i, d, p) wl_isr((i), (d)) ++#else ++#define WL_ISR(i, d, p) wl_isr((i), (d), (p)) ++#endif /* < 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define netdev_priv(dev) dev->priv ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++ ++#endif /* _linuxver_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/osl.h b/drivers/bcmdrivers/gmac/src/include/osl.h +new file mode 100755 +index 0000000..6b961d9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/osl.h +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OS Abstraction Layer ++ * ++ * $Id: osl.h 321101 2012-03-14 02:53:01Z $ ++ */ ++ ++#ifndef _osl_h_ ++#define _osl_h_ ++ ++/* osl handle type forward declaration */ ++typedef struct osl_info osl_t; ++typedef struct osl_dmainfo osldma_t; ++ ++#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ ++ ++/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ ++typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); ++ ++/* Drivers use REGOPSSET() to register register read/write funcitons */ ++typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size); ++typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size); ++ ++#ifdef __mips__ ++#define PREF_LOAD 0 ++#define PREF_STORE 1 ++#define PREF_LOAD_STREAMED 4 ++#define PREF_STORE_STREAMED 5 ++#define PREF_LOAD_RETAINED 6 ++#define PREF_STORE_RETAINED 7 ++#define PREF_WBACK_INV 25 ++#define PREF_PREPARE4STORE 30 ++ ++ ++#define MAKE_PREFETCH_FN(hint) \ ++static inline void prefetch_##hint(const void *addr) \ ++{ \ ++ __asm__ __volatile__(\ ++ " .set mips4 \n" \ ++ " pref %0, (%1) \n" \ ++ " .set mips0 \n" \ ++ : \ ++ : "i" (hint), "r" (addr)); \ ++} ++ ++#define MAKE_PREFETCH_RANGE_FN(hint) \ ++static inline void prefetch_range_##hint(const void *addr, int len) \ ++{ \ ++ int size = len; \ ++ while (size > 0) { \ ++ prefetch_##hint(addr); \ ++ size -= 32; \ ++ } \ ++} ++ ++MAKE_PREFETCH_FN(PREF_LOAD) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD) ++MAKE_PREFETCH_FN(PREF_STORE) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE) ++MAKE_PREFETCH_FN(PREF_LOAD_STREAMED) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD_STREAMED) ++MAKE_PREFETCH_FN(PREF_STORE_STREAMED) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE_STREAMED) ++MAKE_PREFETCH_FN(PREF_LOAD_RETAINED) ++MAKE_PREFETCH_RANGE_FN(PREF_LOAD_RETAINED) ++MAKE_PREFETCH_FN(PREF_STORE_RETAINED) ++MAKE_PREFETCH_RANGE_FN(PREF_STORE_RETAINED) ++#endif /* __mips__ */ ++ ++#if defined(linux) ++#include ++#else ++#error "Unsupported OSL requested" ++#endif ++ ++#ifndef PKTDBG_TRACE ++#define PKTDBG_TRACE(osh, pkt, bit) ++#endif ++ ++#ifndef PKTCTFMAP ++#define PKTCTFMAP(osh, p) ++#endif /* PKTCTFMAP */ ++ ++/* -------------------------------------------------------------------------- ++** Register manipulation macros. ++*/ ++ ++#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) ++ ++#ifndef AND_REG ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#endif /* !AND_REG */ ++ ++#ifndef OR_REG ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++#endif /* !OR_REG */ ++ ++#if !defined(OSL_SYSUPTIME) ++#define OSL_SYSUPTIME() (0) ++#define OSL_SYSUPTIME_SUPPORT FALSE ++#else ++#define OSL_SYSUPTIME_SUPPORT TRUE ++#endif /* OSL_SYSUPTIME */ ++ ++#if !defined(linux) || !defined(PKTC) ++#define PKTCGETATTR(s) (0) ++#define PKTCSETATTR(skb, f, p, b) ++#define PKTCCLRATTR(skb) ++#define PKTCCNT(skb) (1) ++#define PKTCLEN(skb) PKTLEN(NULL, skb) ++#define PKTCGETFLAGS(skb) (0) ++#define PKTCSETFLAGS(skb, f) ++#define PKTCCLRFLAGS(skb) ++#define PKTCFLAGS(skb) (0) ++#define PKTCSETCNT(skb, c) ++#define PKTCINCRCNT(skb) ++#define PKTCADDCNT(skb, c) ++#define PKTCSETLEN(skb, l) ++#define PKTCADDLEN(skb, l) ++#define PKTCSETFLAG(skb, fb) ++#define PKTCCLRFLAG(skb, fb) ++#define PKTCLINK(skb) NULL ++#define PKTSETCLINK(skb, x) ++#undef PKTISCHAINED ++#define PKTISCHAINED(skb) FALSE ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) ++#define PKTCFREE PKTFREE ++#endif ++ ++ ++#endif /* _osl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/packed_section_end.h b/drivers/bcmdrivers/gmac/src/include/packed_section_end.h +new file mode 100755 +index 0000000..44c83f8 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/packed_section_end.h +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is NOT defined at this ++ * point, then there is a missing include of packed_section_start.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #undef BWL_PACKED_SECTION ++#else ++ #error "BWL_PACKED_SECTION is NOT defined!" ++#endif ++ ++ ++#if defined(_MSC_VER) ++ /* Disable compiler warning about pragma pack changing alignment. */ ++ #pragma warning(disable:4103) ++ ++ /* The Microsoft compiler uses pragmas for structure packing. Other ++ * compilers use structure attribute modifiers. Refer to ++ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined in ++ * typedefs.h ++ */ ++ #if defined(BWL_DEFAULT_PACKING) ++ /* require default structure packing */ ++ #pragma pack(pop) ++ #undef BWL_DEFAULT_PACKING ++ #else /* BWL_PACKED_SECTION */ ++ #pragma pack() ++ #endif /* BWL_PACKED_SECTION */ ++#endif /* _MSC_VER */ ++ ++ ++/* Compiler-specific directives for structure packing are declared in ++ * packed_section_start.h. This marks the end of the structure packing section, ++ * so, undef them here. ++ */ ++#undef BWL_PRE_PACKED_STRUCT ++#undef BWL_POST_PACKED_STRUCT +diff --git a/drivers/bcmdrivers/gmac/src/include/packed_section_start.h b/drivers/bcmdrivers/gmac/src/include/packed_section_start.h +new file mode 100755 +index 0000000..1899125 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/packed_section_start.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is already defined at this ++ * point, then there is a missing include of packed_section_end.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #error "BWL_PACKED_SECTION is already defined!" ++#else ++ #define BWL_PACKED_SECTION ++#endif ++ ++ ++#if defined(_MSC_VER) ++ /* Disable compiler warning about pragma pack changing alignment. */ ++ #pragma warning(disable:4103) ++ ++ /* The Microsoft compiler uses pragmas for structure packing. Other ++ * compilers use structure attribute modifiers. Refer to ++ * BWL_PRE_PACKED_STRUCT and BWL_POST_PACKED_STRUCT defined below. ++ */ ++ #if defined(BWL_DEFAULT_PACKING) ++ /* Default structure packing */ ++ #pragma pack(push, 8) ++ #else /* BWL_PACKED_SECTION */ ++ #pragma pack(1) ++ #endif /* BWL_PACKED_SECTION */ ++#endif /* _MSC_VER */ ++ ++ ++/* Declare compiler-specific directives for structure packing. */ ++#if defined(_MSC_VER) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT ++#elif defined(__GNUC__) || defined(__lint) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed)) ++#elif defined(__CC_ARM) ++ #define BWL_PRE_PACKED_STRUCT __packed ++ #define BWL_POST_PACKED_STRUCT ++#else ++ #error "Unknown compiler!" ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/include/pcicfg.h b/drivers/bcmdrivers/gmac/src/include/pcicfg.h +new file mode 100755 +index 0000000..fa01982 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/pcicfg.h +@@ -0,0 +1,569 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * pcicfg.h: PCI configuration constants and structures. ++ * ++ * $Id: pcicfg.h 316716 2012-02-23 04:39:13Z $ ++ */ ++ ++#ifndef _h_pcicfg_ ++#define _h_pcicfg_ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* The following inside ifndef's so we don't collide with NTDDK.H */ ++#ifndef PCI_MAX_BUS ++#define PCI_MAX_BUS 0x100 ++#endif ++#ifndef PCI_MAX_DEVICES ++#define PCI_MAX_DEVICES 0x20 ++#endif ++#ifndef PCI_MAX_FUNCTION ++#define PCI_MAX_FUNCTION 0x8 ++#endif ++ ++#ifndef PCI_INVALID_VENDORID ++#define PCI_INVALID_VENDORID 0xffff ++#endif ++#ifndef PCI_INVALID_DEVICEID ++#define PCI_INVALID_DEVICEID 0xffff ++#endif ++ ++ ++/* Convert between bus-slot-function-register and config addresses */ ++ ++#define PCICFG_BUS_SHIFT 16 /* Bus shift */ ++#define PCICFG_SLOT_SHIFT 11 /* Slot shift */ ++#define PCICFG_FUN_SHIFT 8 /* Function shift */ ++#define PCICFG_OFF_SHIFT 0 /* Register shift */ ++ ++#define PCICFG_BUS_MASK 0xff /* Bus mask */ ++#define PCICFG_SLOT_MASK 0x1f /* Slot mask */ ++#define PCICFG_FUN_MASK 7 /* Function mask */ ++#define PCICFG_OFF_MASK 0xff /* Bus mask */ ++ ++#define PCI_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCICFG_BUS_MASK) << PCICFG_BUS_SHIFT) \ ++ | (((s) & PCICFG_SLOT_MASK) << PCICFG_SLOT_SHIFT) \ ++ | (((f) & PCICFG_FUN_MASK) << PCICFG_FUN_SHIFT) \ ++ | (((o) & PCICFG_OFF_MASK) << PCICFG_OFF_SHIFT)) ++ ++#define PCI_CONFIG_BUS(a) (((a) >> PCICFG_BUS_SHIFT) & PCICFG_BUS_MASK) ++#define PCI_CONFIG_SLOT(a) (((a) >> PCICFG_SLOT_SHIFT) & PCICFG_SLOT_MASK) ++#define PCI_CONFIG_FUN(a) (((a) >> PCICFG_FUN_SHIFT) & PCICFG_FUN_MASK) ++#define PCI_CONFIG_OFF(a) (((a) >> PCICFG_OFF_SHIFT) & PCICFG_OFF_MASK) ++ ++/* PCIE Config space accessing MACROS */ ++ ++#define PCIECFG_BUS_SHIFT 24 /* Bus shift */ ++#define PCIECFG_SLOT_SHIFT 19 /* Slot/Device shift */ ++#define PCIECFG_FUN_SHIFT 16 /* Function shift */ ++#define PCIECFG_OFF_SHIFT 0 /* Register shift */ ++ ++#define PCIECFG_BUS_MASK 0xff /* Bus mask */ ++#define PCIECFG_SLOT_MASK 0x1f /* Slot/Device mask */ ++#define PCIECFG_FUN_MASK 7 /* Function mask */ ++#define PCIECFG_OFF_MASK 0xfff /* Register mask */ ++ ++#define PCIE_CONFIG_ADDR(b, s, f, o) \ ++ ((((b) & PCIECFG_BUS_MASK) << PCIECFG_BUS_SHIFT) \ ++ | (((s) & PCIECFG_SLOT_MASK) << PCIECFG_SLOT_SHIFT) \ ++ | (((f) & PCIECFG_FUN_MASK) << PCIECFG_FUN_SHIFT) \ ++ | (((o) & PCIECFG_OFF_MASK) << PCIECFG_OFF_SHIFT)) ++ ++#define PCIE_CONFIG_BUS(a) (((a) >> PCIECFG_BUS_SHIFT) & PCIECFG_BUS_MASK) ++#define PCIE_CONFIG_SLOT(a) (((a) >> PCIECFG_SLOT_SHIFT) & PCIECFG_SLOT_MASK) ++#define PCIE_CONFIG_FUN(a) (((a) >> PCIECFG_FUN_SHIFT) & PCIECFG_FUN_MASK) ++#define PCIE_CONFIG_OFF(a) (((a) >> PCIECFG_OFF_SHIFT) & PCIECFG_OFF_MASK) ++ ++/* The actual config space */ ++ ++#define PCI_BAR_MAX 6 ++ ++#define PCI_ROM_BAR 8 ++ ++#define PCR_RSVDA_MAX 2 ++ ++/* Bits in PCI bars' flags */ ++ ++#define PCIBAR_FLAGS 0xf ++#define PCIBAR_IO 0x1 ++#define PCIBAR_MEM1M 0x2 ++#define PCIBAR_MEM64 0x4 ++#define PCIBAR_PREFETCH 0x8 ++#define PCIBAR_MEM32_MASK 0xFFFFFF80 ++ ++/* pci config status reg has a bit to indicate that capability ptr is present */ ++ ++#define PCI_CAPPTR_PRESENT 0x0010 ++ ++typedef struct _pci_config_regs { ++ uint16 vendor; ++ uint16 device; ++ uint16 command; ++ uint16 status; ++ uint8 rev_id; ++ uint8 prog_if; ++ uint8 sub_class; ++ uint8 base_class; ++ uint8 cache_line_size; ++ uint8 latency_timer; ++ uint8 header_type; ++ uint8 bist; ++ uint32 base[PCI_BAR_MAX]; ++ uint32 cardbus_cis; ++ uint16 subsys_vendor; ++ uint16 subsys_id; ++ uint32 baserom; ++ uint32 rsvd_a[PCR_RSVDA_MAX]; ++ uint8 int_line; ++ uint8 int_pin; ++ uint8 min_gnt; ++ uint8 max_lat; ++ uint8 dev_dep[192]; ++} pci_config_regs; ++ ++#define SZPCR (sizeof (pci_config_regs)) ++#define MINSZPCR 64 /* offsetof (dev_dep[0] */ ++ ++#endif /* !LINUX_POSTMOGRIFY_REMOVAL */ ++/* A structure for the config registers is nice, but in most ++ * systems the config space is not memory mapped, so we need ++ * field offsetts. :-( ++ */ ++#define PCI_CFG_VID 0 ++#define PCI_CFG_DID 2 ++#define PCI_CFG_CMD 4 ++#define PCI_CFG_STAT 6 ++#define PCI_CFG_REV 8 ++#define PCI_CFG_PROGIF 9 ++#define PCI_CFG_SUBCL 0xa ++#define PCI_CFG_BASECL 0xb ++#define PCI_CFG_CLSZ 0xc ++#define PCI_CFG_LATTIM 0xd ++#define PCI_CFG_HDR 0xe ++#define PCI_CFG_BIST 0xf ++#define PCI_CFG_BAR0 0x10 ++#define PCI_CFG_BAR1 0x14 ++#define PCI_CFG_BAR2 0x18 ++#define PCI_CFG_BAR3 0x1c ++#define PCI_CFG_BAR4 0x20 ++#define PCI_CFG_BAR5 0x24 ++#define PCI_CFG_CIS 0x28 ++#define PCI_CFG_SVID 0x2c ++#define PCI_CFG_SSID 0x2e ++#define PCI_CFG_ROMBAR 0x30 ++#define PCI_CFG_CAPPTR 0x34 ++#define PCI_CFG_INT 0x3c ++#define PCI_CFG_PIN 0x3d ++#define PCI_CFG_MINGNT 0x3e ++#define PCI_CFG_MAXLAT 0x3f ++#define PCI_CFG_DEVCTRL 0xd8 ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++#ifdef __NetBSD__ ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_MEMORY ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_INPUT ++#undef PCI_CLASS_DOCK ++#endif /* __NetBSD__ */ ++ ++#ifdef EFI ++#undef PCI_CLASS_BRIDGE ++#undef PCI_CLASS_OLD ++#undef PCI_CLASS_DISPLAY ++#undef PCI_CLASS_SERIAL ++#undef PCI_CLASS_SATELLITE ++#endif /* EFI */ ++ ++/* Classes and subclasses */ ++ ++typedef enum { ++ PCI_CLASS_OLD = 0, ++ PCI_CLASS_DASDI, ++ PCI_CLASS_NET, ++ PCI_CLASS_DISPLAY, ++ PCI_CLASS_MMEDIA, ++ PCI_CLASS_MEMORY, ++ PCI_CLASS_BRIDGE, ++ PCI_CLASS_COMM, ++ PCI_CLASS_BASE, ++ PCI_CLASS_INPUT, ++ PCI_CLASS_DOCK, ++ PCI_CLASS_CPU, ++ PCI_CLASS_SERIAL, ++ PCI_CLASS_INTELLIGENT = 0xe, ++ PCI_CLASS_SATELLITE, ++ PCI_CLASS_CRYPT, ++ PCI_CLASS_DSP, ++ PCI_CLASS_XOR = 0xfe ++} pci_classes; ++ ++typedef enum { ++ PCI_DASDI_SCSI, ++ PCI_DASDI_IDE, ++ PCI_DASDI_FLOPPY, ++ PCI_DASDI_IPI, ++ PCI_DASDI_RAID, ++ PCI_DASDI_OTHER = 0x80 ++} pci_dasdi_subclasses; ++ ++typedef enum { ++ PCI_NET_ETHER, ++ PCI_NET_TOKEN, ++ PCI_NET_FDDI, ++ PCI_NET_ATM, ++ PCI_NET_OTHER = 0x80 ++} pci_net_subclasses; ++ ++typedef enum { ++ PCI_DISPLAY_VGA, ++ PCI_DISPLAY_XGA, ++ PCI_DISPLAY_3D, ++ PCI_DISPLAY_OTHER = 0x80 ++} pci_display_subclasses; ++ ++typedef enum { ++ PCI_MMEDIA_VIDEO, ++ PCI_MMEDIA_AUDIO, ++ PCI_MMEDIA_PHONE, ++ PCI_MEDIA_OTHER = 0x80 ++} pci_mmedia_subclasses; ++ ++typedef enum { ++ PCI_MEMORY_RAM, ++ PCI_MEMORY_FLASH, ++ PCI_MEMORY_OTHER = 0x80 ++} pci_memory_subclasses; ++ ++typedef enum { ++ PCI_BRIDGE_HOST, ++ PCI_BRIDGE_ISA, ++ PCI_BRIDGE_EISA, ++ PCI_BRIDGE_MC, ++ PCI_BRIDGE_PCI, ++ PCI_BRIDGE_PCMCIA, ++ PCI_BRIDGE_NUBUS, ++ PCI_BRIDGE_CARDBUS, ++ PCI_BRIDGE_RACEWAY, ++ PCI_BRIDGE_OTHER = 0x80 ++} pci_bridge_subclasses; ++ ++typedef enum { ++ PCI_COMM_UART, ++ PCI_COMM_PARALLEL, ++ PCI_COMM_MULTIUART, ++ PCI_COMM_MODEM, ++ PCI_COMM_OTHER = 0x80 ++} pci_comm_subclasses; ++ ++typedef enum { ++ PCI_BASE_PIC, ++ PCI_BASE_DMA, ++ PCI_BASE_TIMER, ++ PCI_BASE_RTC, ++ PCI_BASE_PCI_HOTPLUG, ++ PCI_BASE_OTHER = 0x80 ++} pci_base_subclasses; ++ ++typedef enum { ++ PCI_INPUT_KBD, ++ PCI_INPUT_PEN, ++ PCI_INPUT_MOUSE, ++ PCI_INPUT_SCANNER, ++ PCI_INPUT_GAMEPORT, ++ PCI_INPUT_OTHER = 0x80 ++} pci_input_subclasses; ++ ++typedef enum { ++ PCI_DOCK_GENERIC, ++ PCI_DOCK_OTHER = 0x80 ++} pci_dock_subclasses; ++ ++typedef enum { ++ PCI_CPU_386, ++ PCI_CPU_486, ++ PCI_CPU_PENTIUM, ++ PCI_CPU_ALPHA = 0x10, ++ PCI_CPU_POWERPC = 0x20, ++ PCI_CPU_MIPS = 0x30, ++ PCI_CPU_COPROC = 0x40, ++ PCI_CPU_OTHER = 0x80 ++} pci_cpu_subclasses; ++ ++typedef enum { ++ PCI_SERIAL_IEEE1394, ++ PCI_SERIAL_ACCESS, ++ PCI_SERIAL_SSA, ++ PCI_SERIAL_USB, ++ PCI_SERIAL_FIBER, ++ PCI_SERIAL_SMBUS, ++ PCI_SERIAL_OTHER = 0x80 ++} pci_serial_subclasses; ++ ++typedef enum { ++ PCI_INTELLIGENT_I2O ++} pci_intelligent_subclasses; ++ ++typedef enum { ++ PCI_SATELLITE_TV, ++ PCI_SATELLITE_AUDIO, ++ PCI_SATELLITE_VOICE, ++ PCI_SATELLITE_DATA, ++ PCI_SATELLITE_OTHER = 0x80 ++} pci_satellite_subclasses; ++ ++typedef enum { ++ PCI_CRYPT_NETWORK, ++ PCI_CRYPT_ENTERTAINMENT, ++ PCI_CRYPT_OTHER = 0x80 ++} pci_crypt_subclasses; ++ ++typedef enum { ++ PCI_DSP_DPIO, ++ PCI_DSP_OTHER = 0x80 ++} pci_dsp_subclasses; ++ ++typedef enum { ++ PCI_XOR_QDMA, ++ PCI_XOR_OTHER = 0x80 ++} pci_xor_subclasses; ++ ++/* Header types */ ++#define PCI_HEADER_MULTI 0x80 ++#define PCI_HEADER_MASK 0x7f ++typedef enum { ++ PCI_HEADER_NORMAL, ++ PCI_HEADER_BRIDGE, ++ PCI_HEADER_CARDBUS ++} pci_header_types; ++ ++ ++/* Overlay for a PCI-to-PCI bridge */ ++ ++#define PPB_RSVDA_MAX 2 ++#define PPB_RSVDD_MAX 8 ++ ++typedef struct _ppb_config_regs { ++ uint16 vendor; ++ uint16 device; ++ uint16 command; ++ uint16 status; ++ uint8 rev_id; ++ uint8 prog_if; ++ uint8 sub_class; ++ uint8 base_class; ++ uint8 cache_line_size; ++ uint8 latency_timer; ++ uint8 header_type; ++ uint8 bist; ++ uint32 rsvd_a[PPB_RSVDA_MAX]; ++ uint8 prim_bus; ++ uint8 sec_bus; ++ uint8 sub_bus; ++ uint8 sec_lat; ++ uint8 io_base; ++ uint8 io_lim; ++ uint16 sec_status; ++ uint16 mem_base; ++ uint16 mem_lim; ++ uint16 pf_mem_base; ++ uint16 pf_mem_lim; ++ uint32 pf_mem_base_hi; ++ uint32 pf_mem_lim_hi; ++ uint16 io_base_hi; ++ uint16 io_lim_hi; ++ uint16 subsys_vendor; ++ uint16 subsys_id; ++ uint32 rsvd_b; ++ uint8 rsvd_c; ++ uint8 int_pin; ++ uint16 bridge_ctrl; ++ uint8 chip_ctrl; ++ uint8 diag_ctrl; ++ uint16 arb_ctrl; ++ uint32 rsvd_d[PPB_RSVDD_MAX]; ++ uint8 dev_dep[192]; ++} ppb_config_regs; ++ ++ ++/* PCI CAPABILITY DEFINES */ ++#define PCI_CAP_POWERMGMTCAP_ID 0x01 ++#define PCI_CAP_MSICAP_ID 0x05 ++#define PCI_CAP_VENDSPEC_ID 0x09 ++#define PCI_CAP_PCIECAP_ID 0x10 ++ ++/* Data structure to define the Message Signalled Interrupt facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_msi { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 msgctrl; ++ uint32 msgaddr; ++} pciconfig_cap_msi; ++ ++/* Data structure to define the Power managment facility ++ * Valid for PCI and PCIE configurations ++ */ ++typedef struct _pciconfig_cap_pwrmgmt { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 pme_cap; ++ uint16 pme_sts_ctrl; ++ uint8 pme_bridge_ext; ++ uint8 data; ++} pciconfig_cap_pwrmgmt; ++ ++#define PME_CAP_PM_STATES (0x1f << 27) /* Bits 31:27 states that can generate PME */ ++#define PME_CSR_OFFSET 0x4 /* 4-bytes offset */ ++#define PME_CSR_PME_EN (1 << 8) /* Bit 8 Enable generating of PME */ ++#define PME_CSR_PME_STAT (1 << 15) /* Bit 15 PME got asserted */ ++ ++/* Data structure to define the PCIE capability */ ++typedef struct _pciconfig_cap_pcie { ++ uint8 capID; ++ uint8 nextptr; ++ uint16 pcie_cap; ++ uint32 dev_cap; ++ uint16 dev_ctrl; ++ uint16 dev_status; ++ uint32 link_cap; ++ uint16 link_ctrl; ++ uint16 link_status; ++ uint32 slot_cap; ++ uint16 slot_ctrl; ++ uint16 slot_status; ++ uint16 root_ctrl; ++ uint16 root_cap; ++ uint32 root_status; ++} pciconfig_cap_pcie; ++ ++/* PCIE Enhanced CAPABILITY DEFINES */ ++#define PCIE_EXTCFG_OFFSET 0x100 ++#define PCIE_ADVERRREP_CAPID 0x0001 ++#define PCIE_VC_CAPID 0x0002 ++#define PCIE_DEVSNUM_CAPID 0x0003 ++#define PCIE_PWRBUDGET_CAPID 0x0004 ++ ++/* PCIE Extended configuration */ ++#define PCIE_ADV_CORR_ERR_MASK 0x114 ++#define CORR_ERR_RE (1 << 0) /* Receiver */ ++#define CORR_ERR_BT (1 << 6) /* Bad TLP */ ++#define CORR_ERR_BD (1 << 7) /* Bad DLLP */ ++#define CORR_ERR_RR (1 << 8) /* REPLAY_NUM rollover */ ++#define CORR_ERR_RT (1 << 12) /* Reply timer timeout */ ++#define ALL_CORR_ERRORS (CORR_ERR_RE | CORR_ERR_BT | CORR_ERR_BD | \ ++ CORR_ERR_RR | CORR_ERR_RT) ++ ++/* PCIE Root Control Register bits (Host mode only) */ ++#define PCIE_RC_CORR_SERR_EN 0x0001 ++#define PCIE_RC_NONFATAL_SERR_EN 0x0002 ++#define PCIE_RC_FATAL_SERR_EN 0x0004 ++#define PCIE_RC_PME_INT_EN 0x0008 ++#define PCIE_RC_CRS_EN 0x0010 ++ ++/* PCIE Root Capability Register bits (Host mode only) */ ++#define PCIE_RC_CRS_VISIBILITY 0x0001 ++ ++/* Header to define the PCIE specific capabilities in the extended config space */ ++typedef struct _pcie_enhanced_caphdr { ++ uint16 capID; ++ uint16 cap_ver : 4; ++ uint16 next_ptr : 12; ++} pcie_enhanced_caphdr; ++ ++ ++/* Everything below is BRCM HND proprietary */ ++ ++ ++/* Brcm PCI configuration registers */ ++#define cap_list rsvd_a[0] ++#define bar0_window dev_dep[0x80 - 0x40] ++#define bar1_window dev_dep[0x84 - 0x40] ++#define sprom_control dev_dep[0x88 - 0x40] ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ ++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ ++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ ++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ ++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ ++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ ++#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */ ++#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */ ++#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */ ++#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ ++ ++#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++/* ++ * PCIE GEN2 changed some of the above locations for ++ * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase ++ * BAR0 maps 32K of register space ++*/ ++#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */ ++ ++#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */ ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* On AI chips we have a second window to map DMP regs are mapped: */ ++#define PCI_16KB0_WIN2_OFFSET (4 * 1024) /* bar0 + 4K is "Window 2" */ ++ ++/* PCI_INT_STATUS */ ++#define PCI_SBIM_STATUS_SERR 0x4 /* backplane SBErr interrupt status */ ++ ++/* PCI_INT_MASK */ ++#define PCI_SBIM_SHIFT 8 /* backplane core interrupt mask bits offset */ ++#define PCI_SBIM_MASK 0xff00 /* backplane core interrupt mask */ ++#define PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* PCI_SPROM_CONTROL */ ++#define SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ ++#define SPROM_LOCKED 0x08 /* SPROM Locked */ ++#define SPROM_BLANK 0x04 /* indicating a blank SPROM */ ++#define SPROM_WRITEEN 0x10 /* SPROM write enable */ ++#define SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ ++#define SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */ ++#define SPROM_OTPIN_USE 0x80 /* device OTP In use */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Bits in PCI command and status regs */ ++#define PCI_CMD_IO 0x00000001 /* I/O enable */ ++#define PCI_CMD_MEMORY 0x00000002 /* Memory enable */ ++#define PCI_CMD_MASTER 0x00000004 /* Master enable */ ++#define PCI_CMD_SPECIAL 0x00000008 /* Special cycles enable */ ++#define PCI_CMD_INVALIDATE 0x00000010 /* Invalidate? */ ++#define PCI_CMD_VGA_PAL 0x00000040 /* VGA Palate */ ++#define PCI_STAT_TA 0x08000000 /* target abort status */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define PCI_CONFIG_SPACE_SIZE 256 ++#endif /* _h_pcicfg_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/802.11.h b/drivers/bcmdrivers/gmac/src/include/proto/802.11.h +new file mode 100755 +index 0000000..db026bf +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/802.11.h +@@ -0,0 +1,2356 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to 802.11 ++ * ++ * $Id: 802.11.h 308961 2012-01-18 03:01:00Z $ ++ */ ++ ++#ifndef _802_11_H_ ++#define _802_11_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++#ifndef _NET_ETHERNET_H_ ++#include ++#endif ++ ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ ++ ++/* Generic 802.11 frame constants */ ++#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ ++#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ ++#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ ++#define DOT11_FCS_LEN 4 /* d11 FCS length */ ++#define DOT11_ICV_LEN 4 /* d11 ICV length */ ++#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ ++#define DOT11_QOS_LEN 2 /* d11 QoS length */ ++#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ ++ ++#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ ++#define DOT11_IV_LEN 4 /* d11 IV length */ ++#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ ++#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ ++#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ ++#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ ++ ++/* Includes MIC */ ++#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ ++/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ ++#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ ++ DOT11_QOS_LEN + \ ++ DOT11_IV_AES_CCM_LEN + \ ++ DOT11_MAX_MPDU_BODY_LEN + \ ++ DOT11_ICV_LEN + \ ++ DOT11_FCS_LEN) /* d11 max MPDU length */ ++ ++#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ ++ ++/* dot11RTSThreshold */ ++#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ ++#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ ++ ++/* dot11FragmentationThreshold */ ++#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ ++#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength ++ * of the attached PHY ++ */ ++#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ ++ ++/* dot11BeaconPeriod */ ++#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ ++ ++/* dot11DTIMPeriod */ ++#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ ++#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ ++ ++/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ ++#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ ++#define DOT11_OUI_LEN 3 /* d11 OUI length */ ++BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { ++ uint8 dsap; /* always 0xAA */ ++ uint8 ssap; /* always 0xAA */ ++ uint8 ctl; /* always 0x03 */ ++ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 ++ * Bridge-Tunnel: 0x00 0x00 0xF8 ++ */ ++ uint16 type; /* ethertype */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* RFC1042 header used by 802.11 per 802.1H */ ++#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ ++ ++/* Generic 802.11 MAC header */ ++/* ++ * N.B.: This struct reflects the full 4 address 802.11 MAC header. ++ * The fields are defined such that the shorter 1, 2, and 3 ++ * address headers just use the first k fields. ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr a1; /* address 1 */ ++ struct ether_addr a2; /* address 2 */ ++ struct ether_addr a3; /* address 3 */ ++ uint16 seq; /* sequence control */ ++ struct ether_addr a4; /* address 4 */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* Control frames */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* AID */ ++ struct ether_addr bssid; /* receiver address, STA in AP */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr bssid; /* transmitter address, STA in AP */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ ++ ++/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling ++* category+OUI+vendor specific content ( this can be variable) ++*/ ++BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1040]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; ++ ++/* generic vender specific action frame with variable length */ ++BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t; ++#define DOT11_ACTION_VS_HDR_LEN 6 ++ ++#define BCM_ACTION_OUI_BYTE0 0x00 ++#define BCM_ACTION_OUI_BYTE1 0x90 ++#define BCM_ACTION_OUI_BYTE2 0x4c ++ ++/* BA/BAR Control parameters */ ++#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ ++#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ ++#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ ++ ++#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ ++#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ ++ ++#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ ++#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ ++ ++#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ ++#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ ++ ++/* control frame header (BA/BAR) */ ++BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ ++ ++/* BAR frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_bar { ++ uint16 bar_control; /* BAR Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BAR_LEN 4 /* BAR frame payload length */ ++ ++#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ ++#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ ++/* BA frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_ba { ++ uint16 ba_control; /* BA Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */ ++ ++/* Management frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr da; /* receiver address */ ++ struct ether_addr sa; /* transmitter address */ ++ struct ether_addr bssid; /* BSS ID */ ++ uint16 seq; /* sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ ++ ++/* Management frame payloads */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { ++ uint32 timestamp[2]; ++ uint16 beacon_interval; ++ uint16 capability; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_auth { ++ uint16 alg; /* algorithm */ ++ uint16 seq; /* sequence control */ ++ uint16 status; /* status code */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++ struct ether_addr ap; /* Current AP address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { ++ uint16 capability; /* capability information */ ++ uint16 status; /* status code */ ++ uint16 aid; /* association ID */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_measure { ++ uint8 category; ++ uint8 action; ++ uint8 token; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { ++ uint8 category; ++ uint8 action; ++ uint8 ch_width; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { ++ uint8 category; ++ uint8 action; ++ uint8 control; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query { ++ uint8 category; ++ uint8 action; ++ uint16 id; ++} BWL_POST_PACKED_STRUCT; ++ ++#define SM_PWRSAVE_ENABLE 1 ++#define SM_PWRSAVE_MODE 2 ++ ++/* ************* 802.11h related definitions. ************* */ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { ++ uint8 id; ++ uint8 len; ++ uint8 power; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cnst dot11_power_cnst_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cap { ++ uint8 min; ++ uint8 max; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cap dot11_power_cap_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { ++ uint8 id; ++ uint8 len; ++ uint8 tx_pwr; ++ uint8 margin; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_tpc_rep dot11_tpc_rep_t; ++#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { ++ uint8 id; ++ uint8 len; ++ uint8 first_channel; ++ uint8 num_channels; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_supp_channels dot11_supp_channels_t; ++ ++/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband ++ * offset for 40MHz operation. The possible 3 values are: ++ * 1 = above control channel ++ * 3 = below control channel ++ * 0 = no extension channel ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_extch { ++ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ ++ uint8 len; /* IE length */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extch dot11_extch_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; ++ ++#define BRCM_EXTCH_IE_LEN 5 ++#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ ++#define DOT11_EXTCH_IE_LEN 1 ++#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ ++#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ ++#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ ++#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { ++ uint8 category; ++ uint8 action; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_FRMHDR_LEN 2 ++ ++/* CSA IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { ++ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_channel_switch dot11_chan_switch_ie_t; ++ ++#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ ++/* CSA mode - 802.11h-2003 $7.3.2.20 */ ++#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ ++#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { ++ uint8 category; ++ uint8 action; ++ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ ++ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_csa_body { ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 reg; /* regulatory class */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* 11n Extended Channel Switch IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { ++ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ext_csa dot11_ext_csa_ie_t; ++#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { ++ uint8 id; ++ uint8 len; ++ uint8 info; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_coex dot11_obss_coex_t; ++#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */ ++ ++#define DOT11_OBSS_COEX_INFO_REQ 0x01 ++#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 ++#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { ++ uint8 id; ++ uint8 len; ++ uint8 regclass; ++ uint8 chanlist[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; ++#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { ++ uint8 id; ++ uint8 len; ++ uint8 cap[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap_ie dot11_extcap_ie_t; ++ ++#define DOT11_EXTCAP_LEN_MAX 7 ++#define DOT11_EXTCAP_LEN_COEX 1 ++#define DOT11_EXTCAP_LEN_BT 3 ++#define DOT11_EXTCAP_LEN_IW 4 ++#define DOT11_EXTCAP_LEN_SI 6 ++ ++#define DOT11_EXTCAP_LEN_TDLS 5 ++BWL_PRE_PACKED_STRUCT struct dot11_extcap { ++ uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap dot11_extcap_t; ++ ++/* TDLS Capabilities */ ++#define TDLS_CAP_TDLS 37 /* TDLS support */ ++#define TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */ ++#define TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */ ++#define TDLS_CAP_CH_SW 30 /* TDLS Channel switch */ ++#define TDLS_CAP_PROH 38 /* TDLS prohibited */ ++#define TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */ ++ ++#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */ ++ ++/* 802.11h/802.11k Measurement Request/Report IEs */ ++/* Measurement Type field */ ++#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ ++#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ ++#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */ ++#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */ ++#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */ ++#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */ ++#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */ ++#define DOT11_MEASURE_TYPE_STATS 7 /* d11 measurement STA Statistics type */ ++#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ ++#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */ ++#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */ ++ ++/* Measurement Request Modes */ ++#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */ ++#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ ++#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ ++#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ ++#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */ ++/* Measurement Report Modes */ ++#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ ++#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ ++#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ ++/* Basic Measurement Map bits */ ++#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ ++#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ ++#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ ++#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ ++#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_req { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_req dot11_meas_req_t; ++#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ ++/* length of Measure Request IE data not including variable len */ ++#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ BWL_PRE_PACKED_STRUCT union ++ { ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++ } BWL_POST_PACKED_STRUCT basic; ++ uint8 data[1]; ++ } BWL_POST_PACKED_STRUCT rep; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep dot11_meas_rep_t; ++ ++/* length of Measure Report IE data not including variable len */ ++#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; ++#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_quiet { ++ uint8 id; ++ uint8 len; ++ uint8 count; /* TBTTs until beacon interval in quiet starts */ ++ uint8 period; /* Beacon intervals between periodic quiet periods ? */ ++ uint16 duration; /* Length of quiet period, in TU's */ ++ uint16 offset; /* TU's offset from TBTT in Count field */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_quiet dot11_quiet_t; ++ ++BWL_PRE_PACKED_STRUCT struct chan_map_tuple { ++ uint8 channel; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct chan_map_tuple chan_map_tuple_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { ++ uint8 id; ++ uint8 len; ++ uint8 eaddr[ETHER_ADDR_LEN]; ++ uint8 interval; ++ chan_map_tuple_t map[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; ++ ++/* WME Elements */ ++#define WME_OUI "\x00\x50\xf2" /* WME OUI */ ++#define WME_OUI_LEN 3 ++#define WME_OUI_TYPE 2 /* WME type */ ++#define WME_TYPE 2 /* WME type, deprecated */ ++#define WME_SUBTYPE_IE 0 /* Information Element */ ++#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ ++#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ ++#define WME_VER 1 /* WME version */ ++ ++/* WME Access Category Indices (ACIs) */ ++#define AC_BE 0 /* Best Effort */ ++#define AC_BK 1 /* Background */ ++#define AC_VI 2 /* Video */ ++#define AC_VO 3 /* Voice */ ++#define AC_COUNT 4 /* number of ACs */ ++ ++typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ ++ ++#define AC_BITMAP_NONE 0x0 /* No ACs */ ++#define AC_BITMAP_ALL 0xf /* All ACs */ ++#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) ++#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) ++#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) ++ ++/* WME Information Element (IE) */ ++BWL_PRE_PACKED_STRUCT struct wme_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_ie wme_ie_t; ++#define WME_IE_LEN 7 /* WME IE length */ ++ ++BWL_PRE_PACKED_STRUCT struct edcf_acparam { ++ uint8 ACI; ++ uint8 ECW; ++ uint16 TXOP; /* stored in network order (ls octet first) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct edcf_acparam edcf_acparam_t; ++ ++/* WME Parameter Element (PE) */ ++BWL_PRE_PACKED_STRUCT struct wme_param_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_param_ie wme_param_ie_t; ++#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ ++ ++/* QoS Info field for IE as sent from AP */ ++#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ ++#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ ++#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ ++#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ ++ ++/* QoS Info field for IE as sent from STA */ ++#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ ++#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ ++#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ ++#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ ++#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ ++#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ ++#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ ++#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ ++#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ ++#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ ++#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ ++#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ ++ ++/* ACI */ ++#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ ++#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ ++#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ ++#define EDCF_ACM_MASK 0x10 /* ACM mask */ ++#define EDCF_ACI_MASK 0x60 /* ACI mask */ ++#define EDCF_ACI_SHIFT 5 /* ACI shift */ ++#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ ++ ++/* ECW */ ++#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ ++#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ ++#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ ++#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ ++ ++/* TXOP */ ++#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ ++#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++ ++/* Default BE ACI value for non-WME connection STA */ ++#define NON_EDCF_AC_BE_ACI_STA 0x02 ++ ++/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ ++#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ ++#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ ++#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ ++ ++/* Default EDCF parameters that AP uses; WMM draft Table 14 */ ++#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ ++#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ ++#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ ++ ++/* EDCA Parameter IE */ ++BWL_PRE_PACKED_STRUCT struct edca_param_ie { ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct edca_param_ie edca_param_ie_t; ++#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */ ++ ++/* QoS Capability IE */ ++BWL_PRE_PACKED_STRUCT struct qos_cap_ie { ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct qos_cap_ie qos_cap_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { ++ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ ++ uint8 length; ++ uint16 station_count; /* total number of STAs associated */ ++ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ ++ uint16 aac; /* available admission capacity */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; ++#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ ++ ++/* nom_msdu_size */ ++#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ ++#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ ++ ++/* surplus_bandwidth */ ++/* Represented as 3 bits of integer, binary point, 13 bits fraction */ ++#define INTEGER_SHIFT 13 /* integer shift */ ++#define FRACTION_MASK 0x1FFF /* fraction mask */ ++ ++/* Management Notification Frame */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_notification { ++ uint8 category; /* DOT11_ACTION_NOTIFICATION */ ++ uint8 action; ++ uint8 token; ++ uint8 status; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ ++ ++/* Timeout Interval IE */ ++BWL_PRE_PACKED_STRUCT struct ti_ie { ++ uint8 ti_type; ++ uint32 ti_val; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ti_ie ti_ie_t; ++#define TI_TYPE_REASSOC_DEADLINE 1 ++#define TI_TYPE_KEY_LIFETIME 2 ++ ++/* WME Action Codes */ ++#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ ++#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ ++#define WME_DELTS_REQUEST 2 /* WME DELTS request */ ++ ++/* WME Setup Response Status Codes */ ++#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ ++#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ ++#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ ++ ++/* Macro to take a pointer to a beacon or probe response ++ * body and return the char* pointer to the SSID info element ++ */ ++#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) ++ ++/* Authentication frame payload constants */ ++#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ ++#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */ ++#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */ ++ ++/* Frame control macros */ ++#define FC_PVER_MASK 0x3 /* PVER mask */ ++#define FC_PVER_SHIFT 0 /* PVER shift */ ++#define FC_TYPE_MASK 0xC /* type mask */ ++#define FC_TYPE_SHIFT 2 /* type shift */ ++#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ ++#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ ++#define FC_TODS 0x100 /* to DS */ ++#define FC_TODS_SHIFT 8 /* to DS shift */ ++#define FC_FROMDS 0x200 /* from DS */ ++#define FC_FROMDS_SHIFT 9 /* from DS shift */ ++#define FC_MOREFRAG 0x400 /* more frag. */ ++#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ ++#define FC_RETRY 0x800 /* retry */ ++#define FC_RETRY_SHIFT 11 /* retry shift */ ++#define FC_PM 0x1000 /* PM */ ++#define FC_PM_SHIFT 12 /* PM shift */ ++#define FC_MOREDATA 0x2000 /* more data */ ++#define FC_MOREDATA_SHIFT 13 /* more data shift */ ++#define FC_WEP 0x4000 /* WEP */ ++#define FC_WEP_SHIFT 14 /* WEP shift */ ++#define FC_ORDER 0x8000 /* order */ ++#define FC_ORDER_SHIFT 15 /* order shift */ ++ ++/* sequence control macros */ ++#define SEQNUM_SHIFT 4 /* seq. number shift */ ++#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ ++#define FRAGNUM_MASK 0xF /* frag. number mask */ ++ ++/* Frame Control type/subtype defs */ ++ ++/* FC Types */ ++#define FC_TYPE_MNG 0 /* management type */ ++#define FC_TYPE_CTL 1 /* control type */ ++#define FC_TYPE_DATA 2 /* data type */ ++ ++/* Management Subtypes */ ++#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ ++#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ ++#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ ++#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ ++#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ ++#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ ++#define FC_SUBTYPE_BEACON 8 /* beacon */ ++#define FC_SUBTYPE_ATIM 9 /* ATIM */ ++#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ ++#define FC_SUBTYPE_AUTH 11 /* authentication */ ++#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ ++#define FC_SUBTYPE_ACTION 13 /* action */ ++#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ ++ ++/* Control Subtypes */ ++#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ ++#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ ++#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ ++#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ ++#define FC_SUBTYPE_RTS 11 /* RTS */ ++#define FC_SUBTYPE_CTS 12 /* CTS */ ++#define FC_SUBTYPE_ACK 13 /* ACK */ ++#define FC_SUBTYPE_CF_END 14 /* CF-END */ ++#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ ++ ++/* Data Subtypes */ ++#define FC_SUBTYPE_DATA 0 /* Data */ ++#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ ++#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ ++#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_NULL 4 /* Null */ ++#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ ++#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ ++#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ ++#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ ++#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ ++#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ ++ ++/* Data Subtype Groups */ ++#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) ++#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) ++#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) ++#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) ++ ++/* Type/Subtype Combos */ ++#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ ++ ++#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ ++ ++#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ ++#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ ++ ++#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ ++#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ ++#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ ++#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ ++#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ ++#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ ++#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ ++#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ ++#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ ++#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ ++#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ ++#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ ++ ++#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ ++#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ ++#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ ++#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ ++#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ ++#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ ++#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ ++#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ ++#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ ++ ++#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ ++#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ ++#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ ++#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ ++#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ ++ ++/* QoS Control Field */ ++ ++/* 802.1D Priority */ ++#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ ++#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ ++#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ ++ ++/* Traffic Identifier */ ++#define QOS_TID_SHIFT 0 /* QoS TID shift */ ++#define QOS_TID_MASK 0x000f /* QoS TID mask */ ++#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ ++ ++/* End of Service Period (U-APSD) */ ++#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ ++#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ ++#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ ++ ++/* Ack Policy */ ++#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ ++#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ ++#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ ++#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ ++#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ ++#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ ++#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ ++ ++/* A-MSDU flag */ ++#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ ++#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ ++ ++/* Management Frames */ ++ ++/* Management Frame Constants */ ++ ++/* Fixed fields */ ++#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ ++#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ ++#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ ++#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ ++#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ ++#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ ++#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ ++#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ ++#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ ++#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ ++ ++/* DUR/ID field in assoc resp is 0xc000 | AID */ ++#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ ++ ++/* Reason Codes */ ++#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ ++#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ ++#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */ ++#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station ++ * is leaving (or has left) IBSS or ESS ++ */ ++#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ ++#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle ++ * all currently associated stations ++ */ ++#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from ++ * nonauthenticated station ++ */ ++#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from ++ * nonassociated station ++ */ ++#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is ++ * leaving (or has left) BSS ++ */ ++#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not ++ * authenticated with responding station ++ */ ++#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ ++#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ ++/* 12 is unused */ ++ ++/* 32-39 are QSTA specific reasons added in 11e */ ++#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ ++#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ ++#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ ++#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ ++#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ ++#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ ++#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ ++#define DOT11_RC_TIMEOUT 39 /* timeout */ ++ ++#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ ++ ++#define DOT11_RC_TDLS_PEER_UNREACH 25 ++#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 ++ ++/* Status Codes */ ++#define DOT11_SC_SUCCESS 0 /* Successful */ ++#define DOT11_SC_FAILURE 1 /* Unspecified failure */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */ ++ /* schedule provided */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */ ++#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */ ++#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */ ++#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */ ++#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested ++ * capabilities in the Capability ++ * Information field ++ */ ++#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability ++ * to confirm that association exists ++ */ ++#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason ++ * outside the scope of this standard ++ */ ++#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support ++ * the specified authentication ++ * algorithm ++ */ ++#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame ++ * with authentication transaction ++ * sequence number out of expected ++ * sequence ++ */ ++#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of ++ * challenge failure ++ */ ++#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout ++ * waiting for next frame in sequence ++ */ ++#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is ++ * unable to handle additional ++ * associated stations ++ */ ++#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting ++ * station not supporting all of the ++ * data rates in the BSSBasicRateSet ++ * parameter ++ */ ++#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting ++ * station not supporting the Short ++ * Preamble option ++ */ ++#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting ++ * station not supporting the PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting ++ * station not supporting the Channel ++ * Agility option ++ */ ++#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum ++ * Management capability is required. ++ */ ++#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info ++ * in the Power Cap element is ++ * unacceptable. ++ */ ++#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info ++ * in the Supported Channel element is ++ * unacceptable ++ */ ++#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting ++ * station not supporting the Short Slot ++ * Time option ++ */ ++#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting ++ * station not supporting the ER-PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting ++ * station not supporting the DSS-OFDM ++ * option ++ */ ++#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP ++ * being unable to reach the R0 Key Holder ++ */ ++#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later ++ */ ++#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management ++ * frame policy violation ++ */ ++ ++#define DOT11_SC_DECLINED 37 /* request declined */ ++#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ ++#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */ ++#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */ ++#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */ ++#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */ ++#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */ ++#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */ ++#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */ ++ ++#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */ ++#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */ ++#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */ ++ ++/* Info Elts, length of INFORMATION portion of Info Elts */ ++#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ ++#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ ++ ++/* TIM Info element has 3 bytes fixed info in INFORMATION field, ++ * followed by 1 to 251 bytes of Partial Virtual Bitmap ++ */ ++#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ ++#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ ++#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ ++#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ ++#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ ++ ++/* TLV defines */ ++#define TLV_TAG_OFF 0 /* tag offset */ ++#define TLV_LEN_OFF 1 /* length offset */ ++#define TLV_HDR_LEN 2 /* header length */ ++#define TLV_BODY_OFF 2 /* body offset */ ++ ++/* Management Frame Information Element IDs */ ++#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ ++#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ ++#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ ++#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ ++#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ ++#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ ++#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ ++#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ ++#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ ++#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ ++#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ ++#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ ++#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */ ++#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ ++#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ ++#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ ++#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ ++#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ ++#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ ++#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ ++#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ ++#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ ++#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ ++#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ ++#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ ++#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ ++#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */ ++#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */ ++#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ ++#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ ++#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ ++#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */ ++#define DOT11_MNG_NBR_REP_ID 52 /* 11k Neighbor report id */ ++#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */ ++#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */ ++#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */ ++#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */ ++#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */ ++#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ ++#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */ ++#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */ ++#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */ ++#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */ ++#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */ ++#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */ ++#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */ ++#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */ ++#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */ ++#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */ ++#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */ ++#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */ ++#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */ ++#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */ ++#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */ ++#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */ ++#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */ ++#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */ ++#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */ ++#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */ ++#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */ ++ ++#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ ++#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ ++/* should start using this one instead of above two */ ++#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ ++ ++/* Rate element Basic flag and rate mask */ ++#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ ++#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ ++ ++/* ERP info element bit values */ ++#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ ++#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present ++ *in the BSS ++ */ ++#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ++ *ERP-OFDM frames ++ */ ++#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, ++ * 1 == not allowed ++ */ ++/* TS Delay element offset & size */ ++#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ ++#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ ++ ++/* Capability Information Field */ ++#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ ++#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ ++#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ ++#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ ++#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ ++#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ ++#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ ++#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ ++#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ ++#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ ++#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */ ++#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ ++ ++/* Extended capabilities IE bitfields */ ++/* 20/40 BSS Coexistence Management support bit position */ ++#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0 ++/* scheduled PSMP support bit position */ ++#define DOT11_EXT_CAP_SPSMP 6 ++/* BSS Transition Management support bit position */ ++#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 ++/* Interworking support bit position */ ++#define DOT11_EXT_CAP_IW 31 ++/* service Interval granularity bit position and mask */ ++#define DOT11_EXT_CAP_SI 41 ++#define DOT11_EXT_CAP_SI_MASK 0x0E ++ ++/* ++ * Action Frame Constants ++ */ ++#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */ ++#define DOT11_ACTION_CAT_OFF 0 /* category offset */ ++#define DOT11_ACTION_ACT_OFF 1 /* action offset */ ++ ++/* Action Category field (sec 7.3.1.11) */ ++#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */ ++#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */ ++#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */ ++#define DOT11_ACTION_CAT_QOS 1 /* category QoS */ ++#define DOT11_ACTION_CAT_DLS 2 /* category DLS */ ++#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */ ++#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */ ++#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */ ++#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */ ++#define DOT11_ACTION_CAT_HT 7 /* category for HT */ ++#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */ ++#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */ ++#define DOT11_ACTION_CAT_BSSMGMT 10 /* category for BSS transition management */ ++#define DOT11_ACTION_NOTIFICATION 17 ++#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */ ++#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */ ++ ++/* Spectrum Management Action IDs (sec 7.4.1) */ ++#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */ ++#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */ ++#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */ ++#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */ ++#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */ ++ ++/* HT action ids */ ++#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ ++#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ ++ ++/* Public action ids */ ++#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */ ++#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++ ++/* Block Ack action types */ ++#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ ++#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ ++#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ ++ ++/* ADDBA action parameters */ ++#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ ++#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ ++#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ ++#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ ++#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ ++#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ ++#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ ++ ++#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ ++#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ ++ ++/* Fast Transition action types */ ++#define DOT11_FT_ACTION_FT_RESERVED 0 ++#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */ ++#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */ ++ ++/* DLS action types */ ++#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */ ++#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */ ++#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */ ++ ++/* Wireless Network Management (WNM) action types */ ++#define DOT11_WNM_ACTION_EVENT_REQ 0 ++#define DOT11_WNM_ACTION_EVENT_REP 1 ++#define DOT11_WNM_ACTION_DIAG_REQ 2 ++#define DOT11_WNM_ACTION_DIAG_REP 3 ++#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 ++#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 ++#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 ++#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 ++#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 ++#define DOT11_WNM_ACTION_FMS_REQ 9 ++#define DOT11_WNM_ACTION_FMS_RESP 10 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 ++#define DOT11_WNM_ACTION_TFS_REQ 13 ++#define DOT11_WNM_ACTION_TFS_RESP 14 ++#define DOT11_WNM_ACTION_TFS_NOTIFY 15 ++#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 ++#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 ++#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 ++#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 ++#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 ++#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 ++#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 ++#define DOT11_WNM_ACTION_DMS_REQ 23 ++#define DOT11_WNM_ACTION_DMS_RESP 24 ++#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 ++#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 ++#define DOT11_WNM_ACTION_NOTFCTN_RES 27 ++ ++#define DOT11_MNG_COUNTRY_ID_LEN 3 ++ ++/* DLS Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_req { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint16 cap; /* capability */ ++ uint16 timeout; /* timeout value */ ++ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_req dot11_dls_req_t; ++#define DOT11_DLS_REQ_LEN 18 /* Fixed length */ ++ ++/* DLS response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ uint16 status; /* status code field */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint8 data[1]; /* optional: capability, rate ... */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_resp dot11_dls_resp_t; ++#define DOT11_DLS_RESP_LEN 16 /* Fixed length */ ++ ++ ++/* BSS Management Transition Query frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_query (6) */ ++ uint8 token; /* dialog token */ ++ uint8 reason; /* transition query reason */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; ++#define DOT11_BSS_TRANS_QUERY_LEN 4 /* Fixed length */ ++ ++/* BSS Management Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_req (7) */ ++ uint8 token; /* dialog token */ ++ uint8 reqmode; /* transition request mode */ ++ uint16 disassoc_tmr; /* disassociation timer */ ++ uint8 validity_intrvl; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; ++#define DOT11_BSS_TRANS_REQ_LEN 7 /* Fixed length */ ++ ++#define DOT11_BSS_TERM_DUR_LEN 12 /* Fixed length if present */ ++ ++ ++/* BSS Mgmt Transition Request Mode Field - 802.11v */ ++#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 ++#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 ++#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 ++#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 ++#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 ++ ++ ++/* BSS Management transition response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_res (8) */ ++ uint8 token; /* dialog token */ ++ uint8 status; /* transition status */ ++ uint8 term_delay; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; ++#define DOT11_BSS_TRANS_RES_LEN 5 /* Fixed length */ ++ ++/* BSS Mgmt Transition Response Status Field */ ++#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 ++#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 ++ ++ ++/* Neighbor Report BSSID Information Field */ ++#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 ++#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 ++#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 ++ ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 ++ ++/* Neighbor Report Subelements */ ++#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 ++ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_req { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint8 token; /* identifier */ ++ uint16 addba_param_set; /* parameter set */ ++ uint16 timeout; /* timeout in seconds */ ++ uint16 start_seqnum; /* starting sequence number */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_req dot11_addba_req_t; ++#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba resp */ ++ uint8 token; /* identifier */ ++ uint16 status; /* status of add request */ ++ uint16 addba_param_set; /* negotiated parameter set */ ++ uint16 timeout; /* negotiated timeout in seconds */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_resp dot11_addba_resp_t; ++#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ ++ ++/* DELBA action parameters */ ++#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ ++#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ ++#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ ++#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_delba { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint16 delba_param_set; /* paarmeter set */ ++ uint16 reason; /* reason for dellba */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_delba dot11_delba_t; ++#define DOT11_DELBA_LEN 6 /* length of delba frame */ ++ ++/* SA Query action field value */ ++#define SA_QUERY_REQUEST 0 ++#define SA_QUERY_RESPONSE 1 ++ ++/* ************* 802.11r related definitions. ************* */ ++ ++/* Over-the-DS Fast Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_req { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft req */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_req dot11_ft_req_t; ++#define DOT11_FT_REQ_FIXED_LEN 14 ++ ++/* Over-the-DS Fast Transition Response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_res { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft resp */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint16 status; /* status code */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_res dot11_ft_res_t; ++#define DOT11_FT_RES_FIXED_LEN 16 ++ ++ ++/* ************* 802.11k related definitions. ************* */ ++ ++/* Radio measurements enabled capability ie */ ++ ++#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */ ++BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { ++ uint8 cap[DOT11_RRM_CAP_LEN]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; ++ ++/* Bitmap definitions for cap ie */ ++#define DOT11_RRM_CAP_LINK 0 ++#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1 ++#define DOT11_RRM_CAP_PARALLEL 2 ++#define DOT11_RRM_CAP_REPEATED 3 ++#define DOT11_RRM_CAP_BCN_PASSIVE 4 ++#define DOT11_RRM_CAP_BCN_ACTIVE 5 ++#define DOT11_RRM_CAP_BCN_TABLE 6 ++#define DOT11_RRM_CAP_BCN_REP_COND 7 ++#define DOT11_RRM_CAP_AP_CHANREP 16 ++ ++ ++/* Operating Class (formerly "Regulatory Class") definitions */ ++#define DOT11_OP_CLASS_NONE 255 ++ ++ ++/* Radio Measurements action ids */ ++#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */ ++#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */ ++#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */ ++#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */ ++#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */ ++#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */ ++ ++/* Generic radio measurement action frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_action { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_action dot11_rm_action_t; ++#define DOT11_RM_ACTION_LEN 3 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint16 reps; /* no. of repetitions */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq dot11_rmreq_t; ++#define DOT11_RMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_ie { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_ie dot11_rm_ie_t; ++#define DOT11_RM_IE_LEN 5 ++ ++/* Definitions for "mode" bits in rm req */ ++#define DOT11_RMREQ_MODE_PARALLEL 1 ++#define DOT11_RMREQ_MODE_ENABLE 2 ++#define DOT11_RMREQ_MODE_REQUEST 4 ++#define DOT11_RMREQ_MODE_REPORT 8 ++#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */ ++ ++/* Definitions for "mode" bits in rm rep */ ++#define DOT11_RMREP_MODE_LATE 1 ++#define DOT11_RMREP_MODE_INCAPABLE 2 ++#define DOT11_RMREP_MODE_REFUSED 4 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 reg; ++ uint8 channel; ++ uint16 interval; ++ uint16 duration; ++ uint8 bcn_mode; ++ struct ether_addr bssid; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t; ++#define DOT11_RMREQ_BCN_LEN 18 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn { ++ uint8 reg; ++ uint8 channel; ++ uint32 starttime[2]; ++ uint16 duration; ++ uint8 frame_info; ++ uint8 rcpi; ++ uint8 rsni; ++ struct ether_addr bssid; ++ uint8 antenna_id; ++ uint32 parent_tsf; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; ++#define DOT11_RMREP_BCN_LEN 26 ++ ++/* Beacon request measurement mode */ ++#define DOT11_RMREQ_BCN_PASSIVE 0 ++#define DOT11_RMREQ_BCN_ACTIVE 1 ++#define DOT11_RMREQ_BCN_TABLE 2 ++ ++/* Sub-element IDs for Beacon Request */ ++#define DOT11_RMREQ_BCN_SSID_ID 0 ++#define DOT11_RMREQ_BCN_REPINFO_ID 1 ++#define DOT11_RMREQ_BCN_REPDET_ID 2 ++#define DOT11_RMREQ_BCN_REQUEST_ID 10 ++#define DOT11_RMREQ_BCN_APCHREP_ID 51 ++ ++/* Reporting Detail element definition */ ++#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ ++#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */ ++#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */ ++ ++/* Sub-element IDs for Beacon Report */ ++#define DOT11_RMREP_BCN_FRM_BODY 1 ++ ++/* Neighbor measurement report */ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { ++ struct ether_addr bssid; ++ uint32 bssid_info; ++ uint8 reg; ++ uint8 channel; ++ uint8 phytype; ++ uchar sub_elements[1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; ++#define DOT11_RMREP_NBR_LEN 13 ++ ++/* MLME Enumerations */ ++#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ ++#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ ++#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ ++#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ ++#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ ++ ++/* Link Measurement */ ++BWL_PRE_PACKED_STRUCT struct dot11_lmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 txpwr; /* Transmit Power Used */ ++ uint8 maxtxpwr; /* Max Transmit Power */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmreq dot11_lmreq_t; ++#define DOT11_LMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_lmrep { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ dot11_tpc_rep_t tpc; /* TPC element */ ++ uint8 rxant; /* Receive Antenna ID */ ++ uint8 txant; /* Transmit Antenna ID */ ++ uint8 rcpi; /* RCPI */ ++ uint8 rsni; /* RSNI */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmrep dot11_lmrep_t; ++#define DOT11_LMREP_LEN 11 ++ ++/* 802.11 BRCM "Compromise" Pre N constants */ ++#define PREN_PREAMBLE 24 /* green field preamble time */ ++#define PREN_MM_EXT 12 /* extra mixed mode preamble time */ ++#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ ++ ++/* 802.11N PHY constants */ ++#define RIFS_11N_TIME 2 /* NPHY RIFS time */ ++ ++/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3 ++ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2 ++ */ ++/* HT-SIG1 */ ++#define HT_SIG1_MCS_MASK 0x00007F ++#define HT_SIG1_CBW 0x000080 ++#define HT_SIG1_HT_LENGTH 0xFFFF00 ++ ++/* HT-SIG2 */ ++#define HT_SIG2_SMOOTHING 0x000001 ++#define HT_SIG2_NOT_SOUNDING 0x000002 ++#define HT_SIG2_RESERVED 0x000004 ++#define HT_SIG2_AGGREGATION 0x000008 ++#define HT_SIG2_STBC_MASK 0x000030 ++#define HT_SIG2_STBC_SHIFT 4 ++#define HT_SIG2_FEC_CODING 0x000040 ++#define HT_SIG2_SHORT_GI 0x000080 ++#define HT_SIG2_ESS_MASK 0x000300 ++#define HT_SIG2_ESS_SHIFT 8 ++#define HT_SIG2_CRC 0x03FC00 ++#define HT_SIG2_TAIL 0x1C0000 ++ ++/* 802.11 A PHY constants */ ++#define APHY_SLOT_TIME 9 /* APHY slot time */ ++#define APHY_SIFS_TIME 16 /* APHY SIFS time */ ++#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ ++#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ ++#define APHY_SIGNAL_TIME 4 /* APHY signal time */ ++#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ ++#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ ++#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ ++#define APHY_CWMIN 15 /* APHY cwmin */ ++ ++/* 802.11 B PHY constants */ ++#define BPHY_SLOT_TIME 20 /* BPHY slot time */ ++#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ ++#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ ++#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ ++#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ ++#define BPHY_CWMIN 31 /* BPHY cwmin */ ++ ++/* 802.11 G constants */ ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ ++ ++#define PHY_CWMAX 1023 /* PHY cwmax */ ++ ++#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ ++ ++/* 802.11 AC (VHT) constants */ ++ ++typedef int vht_group_id_t; ++ ++/* for VHT-A1 */ ++/* SIG-A1 reserved bits */ ++#define VHT_SIGA1_CONST_MASK 0x800004 ++ ++#define VHT_SIGA1_20MHZ_VAL 0x000000 ++#define VHT_SIGA1_40MHZ_VAL 0x000001 ++#define VHT_SIGA1_80MHZ_VAL 0x000002 ++#define VHT_SIGA1_160MHZ_VAL 0x000003 ++ ++#define VHT_SIGA1_STBC 0x000008 ++ ++#define VHT_SIGA1_GID_MAX_GID 0x3f ++#define VHT_SIGA1_GID_SHIFT 4 ++#define VHT_SIGA1_GID_TO_AP 0x00 ++#define VHT_SIGA1_GID_NOT_TO_AP 0x3f ++ ++#define VHT_SIGA1_NSTS_SHIFT 10 ++#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 ++ ++#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 ++ ++/* for VHT-A2 */ ++#define VHT_SIGA2_GI_NONE 0x000000 ++#define VHT_SIGA2_GI_SHORT 0x000001 ++#define VHT_SIGA2_GI_W_MOD10 0x000002 ++#define VHT_SIGA2_CODING_LDPC 0x000004 ++#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 ++#define VHT_SIGA2_MCS_SHIFT 4 ++ ++#define VHT_SIGA2_B9_RESERVED 0x000200 ++#define VHT_SIGA2_TAIL_MASK 0xfc0000 ++#define VHT_SIGA2_TAIL_VALUE 0x000000 ++ ++#define VHT_SIGA2_SVC_BITS 16 ++#define VHT_SIGA2_TAIL_BITS 6 ++ ++ ++/* dot11Counters Table - 802.11 spec., Annex D */ ++typedef struct d11cnt { ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++} d11cnt_t; ++ ++/* OUI for BRCM proprietary IE */ ++#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* The following BRCM_PROP_OUI types are currently in use (defined in ++ * relevant subsections). Each of them will be in a separate proprietary(221) IE ++ * #define SES_VNDR_IE_TYPE 1 (defined in src/ses/shared/ses.h) ++ * #define DPT_IE_TYPE 2 ++ * #define HT_CAP_IE_TYPE 51 ++ * #define HT_ADD_IE_TYPE 52 ++ * #define BRCM_EXTCH_IE_TYPE 53 ++ */ ++ ++/* Following is the generic structure for brcm_prop_ie (uses BRCM_PROP_OUI). ++ * DPT uses this format with type set to DPT_IE_TYPE ++ */ ++BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type of this IE */ ++ uint16 cap; /* DPT capabilities */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_prop_ie_s brcm_prop_ie_t; ++ ++#define BRCM_PROP_IE_LEN 6 /* len of fixed part of brcm_prop ie */ ++ ++#define DPT_IE_TYPE 2 ++#define WET_TUNNEL_IE_TYPE 3 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* BRCM OUI: Used in the proprietary(221) IE in all broadcom devices */ ++#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ ++ ++/* BRCM info element */ ++BWL_PRE_PACKED_STRUCT struct brcm_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ ++ uint8 ver; /* type/ver of this IE */ ++ uint8 assoc; /* # of assoc STAs */ ++ uint8 flags; /* misc flags */ ++ uint8 flags1; /* misc flags */ ++ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_ie brcm_ie_t; ++#define BRCM_IE_LEN 11 /* BRCM IE length */ ++#define BRCM_IE_VER 2 /* BRCM IE version */ ++#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ ++ ++/* brcm_ie flags */ ++#define BRF_LZWDS 0x4 /* lazy wds enabled */ ++#define BRF_BLOCKACK 0x8 /* BlockACK capable */ ++ ++/* brcm_ie flags1 */ ++#define BRF1_AMSDU 0x1 /* A-MSDU capable */ ++#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */ ++#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */ ++#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */ ++#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */ ++#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */ ++ ++/* Vendor IE structure */ ++BWL_PRE_PACKED_STRUCT struct vndr_ie { ++ uchar id; ++ uchar len; ++ uchar oui [3]; ++ uchar data [1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vndr_ie vndr_ie_t; ++ ++#define VNDR_IE_HDR_LEN 2 /* id + len field */ ++#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ ++#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ ++ ++/* ************* HT definitions. ************* */ ++#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ ++#define MAX_MCS_NUM (128) /* max mcs number = 128 */ ++ ++BWL_PRE_PACKED_STRUCT struct ht_cap_ie { ++ uint16 cap; ++ uint8 params; ++ uint8 supp_mcs[MCSSET_LEN]; ++ uint16 ext_htcap; ++ uint32 txbf_cap; ++ uint8 as_cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_cap_ie ht_cap_ie_t; ++ ++/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the capability IE is primarily used to convey this nodes abilities */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ ht_cap_ie_t cap_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; ++ ++#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ ++#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */ ++#define HT_CAP_IE_TYPE 51 ++ ++#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ ++#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */ ++#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ ++#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ ++#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ ++#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ ++#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ ++#define HT_CAP_GF 0x0010 /* Greenfield preamble support */ ++#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ ++#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ ++#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */ ++#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ ++#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ ++#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */ ++#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ ++ ++#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ ++#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ ++#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ ++#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ ++ ++#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ ++#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ ++#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ ++ ++#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */ ++#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */ ++/* Max AMSDU len - per spec */ ++#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA) ++ ++#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */ ++#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */ ++ ++#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ ++#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ ++#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ ++ ++/* HT/AMPDU specific define */ ++#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */ ++#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */ ++#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */ ++#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */ ++#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */ ++#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ ++ ++#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ ++#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ ++ ++#define HT_CAP_EXT_PCO 0x0001 ++#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 ++#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 ++#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 ++#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 ++#define HT_CAP_EXT_HTC 0x0400 ++#define HT_CAP_EXT_RD_RESP 0x0800 ++ ++BWL_PRE_PACKED_STRUCT struct ht_add_ie { ++ uint8 ctl_ch; /* control channel number */ ++ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ ++ uint16 opmode; /* operation mode */ ++ uint16 misc_bits; /* misc bits */ ++ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_add_ie ht_add_ie_t; ++ ++/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the additional IE is primarily used to convey the current BSS configuration */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* indicates what follows */ ++ ht_add_ie_t add_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_add_ie ht_prop_add_ie_t; ++ ++#define HT_ADD_IE_LEN 22 ++#define HT_ADD_IE_TYPE 52 ++ ++/* byte1 defn's */ ++#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ ++#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */ ++ ++/* opmode defn's */ ++#define HT_OPMODE_MASK 0x0003 /* protection mode mask */ ++#define HT_OPMODE_SHIFT 0 /* protection mode shift */ ++#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* misc_bites defn's */ ++#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ ++#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ ++#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */ ++#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ ++#define HT_PCO_ACTIVE 0x0400 /* PCO active */ ++#define HT_PCO_PHASE 0x0800 /* PCO phase */ ++#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */ ++ ++/* Tx Burst Limits */ ++#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++ ++/* Macros for opmode */ ++#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ >> HT_OPMODE_SHIFT) ++#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_MIXED) /* mixed mode present */ ++#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_HT20IN40) /* 20MHz HT present */ ++#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_OPTIONAL) /* Optional protection present */ ++#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ ++ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */ ++#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ ++ == HT_OPMODE_NONGF) /* non-GF present */ ++#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ ++ == DOT11N_TXBURST) /* Tx Burst present */ ++#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ ++ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ ++ ++BWL_PRE_PACKED_STRUCT struct obss_params { ++ uint16 passive_dwell; ++ uint16 active_dwell; ++ uint16 bss_widthscan_interval; ++ uint16 passive_total; ++ uint16 active_total; ++ uint16 chanwidth_transition_dly; ++ uint16 activity_threshold; ++} BWL_POST_PACKED_STRUCT; ++typedef struct obss_params obss_params_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { ++ uint8 id; ++ uint8 len; ++ obss_params_t obss_params; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_ie dot11_obss_ie_t; ++#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */ ++ ++/* HT control field */ ++#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */ ++#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */ ++#define HT_CTRL_LA_MAI_SHIFT 2 ++#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */ ++#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */ ++#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */ ++#define HT_CTRL_LA_MFSI_SHIFT 6 ++#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */ ++#define HT_CTRL_LA_MFB_ASELC_SH 9 ++#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */ ++#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */ ++#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */ ++#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */ ++#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */ ++#define HT_CTRL_CSI_STEER_SHIFT 22 ++#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */ ++#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */ ++#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */ ++#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */ ++#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */ ++#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */ ++#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */ ++ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* ************* VHT definitions. ************* */ ++ ++BWL_PRE_PACKED_STRUCT struct vht_cap_ie { ++ uint32 vht_cap_info; ++ /* supported MCS set - 64 bit field */ ++ uint16 rx_mcs_map; ++ uint16 rx_max_rate; ++ uint16 tx_mcs_map; ++ uint16 tx_max_rate; ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_cap_ie vht_cap_ie_t; ++/* 4B cap_info + 8B supp_mcs */ ++#define VHT_CAP_IE_LEN 12 ++/* 32bit - cap info */ ++#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 ++#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c ++#define VHT_CAP_INFO_LDPC 0x00000010 ++#define VHT_CAP_INFO_SGI_80MHZ 0x00000020 ++#define VHT_CAP_INFO_SGI_160MHZ 0x00000040 ++#define VHT_CAP_INFO_TX_STBC 0x00000080 ++#define VHT_CAP_INFO_RX_STBC 0x00000700 ++ ++#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 ++#define VHT_CAP_INFO_RX_STBC_SHIFT 8 ++#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 ++#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 ++ ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 ++#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 ++#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000 ++#define VHT_CAP_INFO_TXOPPS 0x00200000 ++#define VHT_CAP_INFO_HTCVHT 0x00400000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 ++ ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 ++ ++/* 64-bit Supp MCS. */ ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_MCS_MAP_0_7 0 ++#define VHT_CAP_MCS_MAP_0_8 1 ++#define VHT_CAP_MCS_MAP_0_9 2 ++#define VHT_CAP_MCS_MAP_NONE 3 ++ ++#define VHT_CAP_MCS_MAP_NSS_MAX 8 ++ ++/* VHT Capabilities Supported Channel Width */ ++typedef enum vht_cap_chan_width { ++ VHT_CAP_CHAN_WIDTH_20_40 = 0x00, ++ VHT_CAP_CHAN_WIDTH_80 = 0x04, ++ VHT_CAP_CHAN_WIDTH_160 = 0x08 ++} vht_cap_chan_width_t; ++ ++/* VHT Capabilities Supported max MPDU LEN */ ++typedef enum vht_cap_max_mpdu_len { ++ VHT_CAP_MPDU_MAX_4K = 0x00, ++ VHT_CAP_MPDU_MAX_8K = 0x01, ++ VHT_CAP_MPDU_MAX_11K = 0x02 ++} vht_cap_max_mpdu_len_t; ++ ++/* VHT Operation Element */ ++BWL_PRE_PACKED_STRUCT struct vht_op_ie { ++ uint8 chan_width; ++ uint8 chan1; ++ uint8 chan2; ++ uint16 supp_mcs; /* same def as above in vht cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_op_ie vht_op_ie_t; ++/* 3B VHT Op info + 2B Basic MCS */ ++#define VHT_OP_IE_LEN 5 ++ ++typedef enum vht_op_chan_width { ++ VHT_OP_CHAN_WIDTH_20_40 = 0, ++ VHT_OP_CHAN_WIDTH_80 = 1, ++ VHT_OP_CHAN_WIDTH_160 = 2, ++ VHT_OP_CHAN_WIDTH_80_80 = 3 ++} vht_op_chan_width_t; ++ ++/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */ ++#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) ++#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ ++ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) ++#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ ++ ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) ++ ++/* ************* WPA definitions. ************* */ ++#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ ++#define WPA_OUI_LEN 3 /* WPA OUI length */ ++#define WPA_OUI_TYPE 1 ++#define WPA_VERSION 1 /* WPA version */ ++#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ ++#define WPA2_OUI_LEN 3 /* WPA2 OUI length */ ++#define WPA2_VERSION 1 /* WPA2 version */ ++#define WPA2_VERSION_LEN 2 /* WAP2 version length */ ++ ++/* ************* WPS definitions. ************* */ ++#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */ ++#define WPS_OUI_LEN 3 /* WPS OUI length */ ++#define WPS_OUI_TYPE 4 ++ ++/* ************* WFA definitions. ************* */ ++#if defined(MACOSX) ++#define MAC_OUI "\x00\x17\xF2" /* MACOSX OUI */ ++#define MAC_OUI_TYPE_P2P 5 ++#endif /* MACOSX */ ++ ++#if defined(MACOSX) && !defined(WLP2P_NEW_WFA_OUI) ++#define WFA_OUI WPS_OUI /* WFA OUI */ ++#else ++#ifdef P2P_IE_OVRD ++#define WFA_OUI MAC_OUI ++#else ++#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */ ++#endif /* P2P_IE_OVRD */ ++#endif /* MACOSX && !WLP2P_NEW_WFA_OUI */ ++#define WFA_OUI_LEN 3 /* WFA OUI length */ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P ++#else ++#define WFA_OUI_TYPE_P2P 9 ++#endif ++ ++#define WFA_OUI_TYPE_TPC 8 ++ ++/* RSN authenticated key managment suite */ ++#define RSN_AKM_NONE 0 /* None (IBSS) */ ++#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ ++#define RSN_AKM_PSK 2 /* Pre-shared Key */ ++#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */ ++#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */ ++#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */ ++#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ ++#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ ++ ++/* Key related defines */ ++#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ ++#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ ++#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ ++#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ ++#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */ ++ ++#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ ++#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ ++#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ ++#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ ++#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ ++#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ ++#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ ++#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ ++#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ ++#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ ++#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ ++#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ ++#define AES_KEY_SIZE 16 /* size of AES key */ ++#define AES_MIC_SIZE 8 /* size of AES MIC */ ++#define BIP_KEY_SIZE 16 /* size of BIP key */ ++ ++/* WCN */ ++#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ ++#define WCN_TYPE 4 /* WCN type */ ++ ++ ++/* 802.11r protocol definitions */ ++ ++/* Mobility Domain IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mdid; /* Mobility Domain Id */ ++ uint8 cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_mdid_ie dot11_mdid_ie_t; ++ ++#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ ++#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ ++ ++/* Fast Bss Transition IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mic_control; /* Mic Control */ ++ uint8 mic[16]; ++ uint8 anonce[32]; ++ uint8 snonce[32]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_ie dot11_ft_ie_t; ++ ++#define TIE_TYPE_RESERVED 0 ++#define TIE_TYPE_REASSOC_DEADLINE 1 ++#define TIE_TYPE_KEY_LIEFTIME 2 ++#define TIE_TYPE_ASSOC_COMEBACK 3 ++BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { ++ uint8 id; ++ uint8 len; ++ uint8 type; /* timeout interval type */ ++ uint32 value; /* timeout interval value */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_timeout_ie dot11_timeout_ie_t; ++ ++/* GTK ie */ ++BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { ++ uint8 id; ++ uint8 len; ++ uint16 key_info; ++ uint8 key_len; ++ uint8 rsc[8]; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_gtk_ie dot11_gtk_ie_t; ++ ++#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" ++#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" ++ ++ ++/* ************* WMM Parameter definitions. ************* */ ++#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ ++#define WMM_OUI_LEN 3 /* WMM OUI length */ ++#define WMM_OUI_TYPE 2 /* WMM OUT type */ ++#define WMM_VERSION 1 ++#define WMM_VERSION_LEN 1 ++ ++/* WMM OUI subtype */ ++#define WMM_OUI_SUBTYPE_PARAMETER 1 ++#define WMM_PARAMETER_IE_LEN 24 ++ ++/* Link Identifier Element */ ++BWL_PRE_PACKED_STRUCT struct link_id_ie { ++ uint8 id; ++ uint8 len; ++ struct ether_addr bssid; ++ struct ether_addr tdls_init_mac; ++ struct ether_addr tdls_resp_mac; ++} BWL_POST_PACKED_STRUCT; ++typedef struct link_id_ie link_id_ie_t; ++#define TDLS_LINK_ID_IE_LEN 18 ++ ++/* Link Wakeup Schedule Element */ ++BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { ++ uint8 id; ++ uint8 len; ++ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */ ++ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */ ++ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */ ++ uint32 max_wake_win; /* in ms, max duration of Awake Window */ ++ uint16 idle_cnt; /* number of consecutive Awake Windows */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wakeup_sch_ie wakeup_sch_ie_t; ++#define TDLS_WAKEUP_SCH_IE_LEN 18 ++ ++/* Channel Switch Timing Element */ ++BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { ++ uint8 id; ++ uint8 len; ++ uint16 switch_time; /* in ms, time to switch channels */ ++ uint16 switch_timeout; /* in ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; ++#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 ++ ++/* PTI Control Element */ ++BWL_PRE_PACKED_STRUCT struct pti_control_ie { ++ uint8 id; ++ uint8 len; ++ uint8 tid; ++ uint16 seq_control; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pti_control_ie pti_control_ie_t; ++#define TDLS_PTI_CONTROL_IE_LEN 3 ++ ++/* PU Buffer Status Element */ ++BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { ++ uint8 id; ++ uint8 len; ++ uint8 status; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; ++#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BK 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BE 2 ++#define TDLS_PU_BUFFER_STATUS_AC_VI 4 ++#define TDLS_PU_BUFFER_STATUS_AC_VO 8 ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h b/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h +new file mode 100755 +index 0000000..3749214 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/802.1d.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to 802.1D ++ * ++ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_1_D_ ++#define _802_1_D_ ++ ++/* 802.1D priority defines */ ++#define PRIO_8021D_NONE 2 /* None = - */ ++#define PRIO_8021D_BK 1 /* BK - Background */ ++#define PRIO_8021D_BE 0 /* BE - Best-effort */ ++#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ ++#define PRIO_8021D_CL 4 /* CL - Controlled Load */ ++#define PRIO_8021D_VI 5 /* Vi - Video */ ++#define PRIO_8021D_VO 6 /* Vo - Voice */ ++#define PRIO_8021D_NC 7 /* NC - Network Control */ ++#define MAXPRIO 7 /* 0-7 */ ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define ALLPRIO -1 /* All prioirty */ ++ ++/* Converts prio to precedence since the numerical value of ++ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. ++ */ ++#define PRIO2PREC(prio) \ ++ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) ++ ++#endif /* _802_1_D__ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/BOM b/drivers/bcmdrivers/gmac/src/include/proto/BOM +new file mode 100755 +index 0000000..98c6e5d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/BOM +@@ -0,0 +1,4 @@ ++# Created by mkbom ++# $Id: BOM,v 9.0 1998-07-30 23:19:02 $ ++ ++File 1.46 vip.h +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/Makefile b/drivers/bcmdrivers/gmac/src/include/proto/Makefile +new file mode 100755 +index 0000000..533b7c4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/Makefile +@@ -0,0 +1,9 @@ ++# ++# include/proto/Makefile ++# ++# Copyright 2006, Broadcom, Inc. ++# ++# $Id: Makefile 241182 2011-02-17 21:50:03Z $ ++# ++ ++# build etags +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h +new file mode 100755 +index 0000000..f3aede9 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmeth.h +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Ethernettype protocol definitions ++ * ++ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $ ++ */ ++ ++/* ++ * Broadcom Ethernet protocol defines ++ */ ++ ++#ifndef _BCMETH_H_ ++#define _BCMETH_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* ETHER_TYPE_BRCM is defined in ethernet.h */ ++ ++/* ++ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field ++ * in one of two formats: (only subtypes 32768-65535 are in use now) ++ * ++ * subtypes 0-32767: ++ * 8 bit subtype (0-127) ++ * 8 bit length in bytes (0-255) ++ * ++ * subtypes 32768-65535: ++ * 16 bit big-endian subtype ++ * 16 bit big-endian length in bytes (0-65535) ++ * ++ * length is the number of additional bytes beyond the 4 or 6 byte header ++ * ++ * Reserved values: ++ * 0 reserved ++ * 5-15 reserved for iLine protocol assignments ++ * 17-126 reserved, assignable ++ * 127 reserved ++ * 32768 reserved ++ * 32769-65534 reserved, assignable ++ * 65535 reserved ++ */ ++ ++/* ++ * While adding the subtypes and their specific processing code make sure ++ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition ++ */ ++ ++#define BCMILCP_SUBTYPE_RATE 1 ++#define BCMILCP_SUBTYPE_LINK 2 ++#define BCMILCP_SUBTYPE_CSA 3 ++#define BCMILCP_SUBTYPE_LARQ 4 ++#define BCMILCP_SUBTYPE_VENDOR 5 ++#define BCMILCP_SUBTYPE_FLH 17 ++ ++#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 ++#define BCMILCP_SUBTYPE_CERT 32770 ++#define BCMILCP_SUBTYPE_SES 32771 ++ ++ ++#define BCMILCP_BCM_SUBTYPE_RESERVED 0 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define BCMILCP_BCM_SUBTYPE_SES 2 ++/* ++ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded ++ * within BCMILCP_BCM_SUBTYPE_EVENT type messages ++ */ ++/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ ++#define BCMILCP_BCM_SUBTYPE_DPT 4 ++ ++#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 ++#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 ++ ++/* These fields are stored in network order */ ++typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr ++{ ++ uint16 subtype; /* Vendor specific..32769 */ ++ uint16 length; ++ uint8 version; /* Version is 0 */ ++ uint8 oui[3]; /* Broadcom OUI */ ++ /* user specific Data */ ++ uint16 usr_subtype; ++} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMETH_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h +new file mode 100755 +index 0000000..57776ae +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmevent.h +@@ -0,0 +1,313 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Event protocol definitions ++ * ++ * Dependencies: proto/bcmeth.h ++ * ++ * $Id: bcmevent.h 315348 2012-02-16 07:32:51Z $ ++ * ++ */ ++ ++/* ++ * Broadcom Ethernet Events protocol defines ++ * ++ */ ++ ++#ifndef _BCMEVENT_H_ ++#define _BCMEVENT_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */ ++#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ ++ ++/* flags */ ++#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ ++#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ ++#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ ++#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */ ++#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */ ++ ++/* these fields are stored in network order */ ++ ++/* version 1 */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t; ++ ++/* the current version */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++ uint8 ifidx; /* destination OS i/f index */ ++ uint8 bsscfgidx; /* source bsscfg index */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_t; ++ ++/* used by driver msgs */ ++typedef BWL_PRE_PACKED_STRUCT struct bcm_event { ++ struct ether_header eth; ++ bcmeth_hdr_t bcm_hdr; ++ wl_event_msg_t event; ++ /* data portion follows */ ++} BWL_POST_PACKED_STRUCT bcm_event_t; ++ ++#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) ++ ++/* Event messages */ ++#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ ++#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ ++#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ ++#define WLC_E_AUTH 3 /* 802.11 AUTH request */ ++#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ ++#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ ++#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ ++#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ ++#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ ++#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ ++#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ ++#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ ++#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ ++#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ ++#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ ++#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ ++#define WLC_E_LINK 16 /* generic link indication */ ++#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ ++#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ ++#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ ++#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ ++#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ ++#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ ++#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ ++#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ ++#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ ++#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ ++#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ ++#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ ++#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ ++#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ ++#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */ ++#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ ++#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ ++#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ ++#define WLC_E_RESET_COMPLETE 35 ++#define WLC_E_JOIN_START 36 ++#define WLC_E_ROAM_START 37 ++#define WLC_E_ASSOC_START 38 ++#define WLC_E_IBSS_ASSOC 39 ++#define WLC_E_RADIO 40 ++#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */ ++#define WLC_E_PROBREQ_MSG 44 /* probe request received */ ++#define WLC_E_SCAN_CONFIRM_IND 45 ++#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */ ++#define WLC_E_COUNTRY_CODE_CHANGED 47 ++#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */ ++#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */ ++#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */ ++#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */ ++#define WLC_E_TRACE 52 ++#define WLC_E_IF 54 /* I/F change (for dongle host notification) */ ++#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */ ++#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */ ++#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */ ++#define WLC_E_EXTLOG_MSG 58 ++#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */ ++#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ ++#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ ++#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ ++#define WLC_E_CHANNEL_ADOPTED 63 ++#define WLC_E_AP_STARTED 64 /* AP started */ ++#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ ++#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ ++#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */ ++#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */ ++#define WLC_E_ESCAN_RESULT 69 /* escan result event */ ++#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */ ++#define WLC_E_PROBRESP_MSG 71 /* probe response received */ ++#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */ ++#define WLC_E_DCS_REQUEST 73 ++ ++#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ ++ ++#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH ++ * wl_event_rx_frame_data_t header ++ */ ++#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */ ++#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */ ++#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */ ++#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */ ++#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */ ++#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */ ++#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */ ++#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */ ++#define WLC_E_GTK_PLUMBED 84 ++#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */ ++#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */ ++#define WLC_E_ASSOC_REQ_IE 87 ++#define WLC_E_ASSOC_RESP_IE 88 ++ ++#define WLC_E_LAST 89 /* highest val + 1 for range checking */ ++ ++/* Table of event name strings for UIs and debugging dumps */ ++typedef struct { ++ uint event; ++ const char *name; ++} bcmevent_name_t; ++ ++extern const bcmevent_name_t bcmevent_names[]; ++extern const int bcmevent_names_size; ++ ++/* Event status codes */ ++#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ ++#define WLC_E_STATUS_FAIL 1 /* operation failed */ ++#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ ++#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ ++#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ ++#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ ++#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ ++#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ ++#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ ++#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ ++#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ ++#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ ++#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ ++#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ ++#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */ ++#define WLC_E_STATUS_ERROR 16 /* request failed due to error */ ++ ++/* roam reason codes */ ++#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ ++#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ ++#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ ++#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ ++#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ ++#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */ ++#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */ ++ ++/* Roam codes used primarily by CCX */ ++#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ ++#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ ++#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ ++#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ ++ ++#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition request by AP */ ++ ++/* prune reason codes */ ++#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */ ++#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ ++#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ ++#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ ++#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ ++#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ ++#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ ++#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ ++#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ ++#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ ++#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ ++#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ ++#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ ++#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ ++#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ ++ ++/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ ++#define WLC_E_SUP_OTHER 0 /* Other reason */ ++#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */ ++#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */ ++#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */ ++#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */ ++#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */ ++#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */ ++#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */ ++#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */ ++#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */ ++#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */ ++#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */ ++#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */ ++#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */ ++#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */ ++#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */ ++ ++/* Event data for events that include frames received over the air */ ++/* WLC_E_PROBRESP_MSG ++ * WLC_E_P2P_PROBREQ_MSG ++ * WLC_E_ACTION_FRAME_RX ++ */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { ++ uint16 version; ++ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ ++ int32 rssi; ++ uint32 mactime; ++ uint32 rate; ++} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; ++ ++#define BCM_RX_FRAME_DATA_VERSION 1 ++ ++/* WLC_E_IF event data */ ++typedef struct wl_event_data_if { ++ uint8 ifidx; /* RTE virtual device index (for dongle) */ ++ uint8 opcode; /* see I/F opcode */ ++ uint8 reserved; ++ uint8 bssidx; /* bsscfg index */ ++ uint8 role; /* see I/F role */ ++} wl_event_data_if_t; ++ ++/* opcode in WLC_E_IF event */ ++#define WLC_E_IF_ADD 1 /* bsscfg add */ ++#define WLC_E_IF_DEL 2 /* bsscfg delete */ ++#define WLC_E_IF_CHANGE 3 /* bsscfg role change */ ++ ++/* I/F role code in WLC_E_IF event */ ++#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ ++#define WLC_E_IF_ROLE_AP 1 /* Access Point */ ++#define WLC_E_IF_ROLE_WDS 2 /* WDS link */ ++#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ ++#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ ++ ++/* Reason codes for LINK */ ++#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */ ++#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */ ++#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ ++#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ ++ ++/* reason codes for WLC_E_OVERLAY_REQ event */ ++#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */ ++#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMEVENT_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h +new file mode 100755 +index 0000000..4f01aee +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmip.h +@@ -0,0 +1,205 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental constants relating to IP Protocol ++ * ++ * $Id: bcmip.h 324300 2012-03-28 20:29:37Z $ ++ */ ++ ++#ifndef _bcmip_h_ ++#define _bcmip_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* IPV4 and IPV6 common */ ++#define IP_VER_OFFSET 0x0 /* offset to version field */ ++#define IP_VER_MASK 0xf0 /* version mask */ ++#define IP_VER_SHIFT 4 /* version shift */ ++#define IP_VER_4 4 /* version number for IPV4 */ ++#define IP_VER_6 6 /* version number for IPV6 */ ++ ++#define IP_VER(ip_body) \ ++ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) ++ ++#define IP_PROT_ICMP 0x1 /* ICMP protocol */ ++#define IP_PROT_IGMP 0x2 /* IGMP protocol */ ++#define IP_PROT_TCP 0x6 /* TCP protocol */ ++#define IP_PROT_UDP 0x11 /* UDP protocol type */ ++#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */ ++ ++/* IPV4 field offsets */ ++#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ ++#define IPV4_TOS_OFFSET 1 /* type of service offset */ ++#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ ++#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ ++#define IPV4_PROT_OFFSET 9 /* protocol type offset */ ++#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ ++#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ ++#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ ++#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ ++#define IPV4_MIN_HEADER_LEN 20 /* Minimum size for an IP header (no options) */ ++ ++/* IPV4 field decodes */ ++#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ ++#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ ++ ++#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ ++#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) ++ ++#define IPV4_ADDR_LEN 4 /* IPV4 address length */ ++ ++#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ ++ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) ++ ++#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ ++ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) ++ ++#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ ++#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ ++ ++#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) ++ ++#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ ++#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ ++ ++#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ ++#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ ++#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ ++ ++#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) ++ ++#define IPV4_FRAG_RESV 0x8000 /* Reserved */ ++#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ ++#define IPV4_FRAG_MORE 0x2000 /* More fragments */ ++#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ ++ ++#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ ++ ++/* IPV4 packet formats */ ++BWL_PRE_PACKED_STRUCT struct ipv4_addr { ++ uint8 addr[IPV4_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv4_hdr { ++ uint8 version_ihl; /* Version and Internet Header Length */ ++ uint8 tos; /* Type Of Service */ ++ uint16 tot_len; /* Number of bytes in packet (max 65535) */ ++ uint16 id; ++ uint16 frag; /* 3 flag bits and fragment offset */ ++ uint8 ttl; /* Time To Live */ ++ uint8 prot; /* Protocol */ ++ uint16 hdr_chksum; /* IP header checksum */ ++ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ ++ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* IPV6 field offsets */ ++#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ ++#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ ++#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ ++#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ ++#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ ++ ++/* IPV6 field decodes */ ++#define IPV6_TRAFFIC_CLASS(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ ++ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) ++ ++#define IPV6_FLOW_LABEL(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ ++ (((uint8 *)(ipv6_body))[2] << 8) | \ ++ (((uint8 *)(ipv6_body))[3])) ++ ++#define IPV6_PAYLOAD_LEN(ipv6_body) \ ++ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ ++ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) ++ ++#define IPV6_NEXT_HDR(ipv6_body) \ ++ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) ++ ++#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) ++ ++#define IPV6_ADDR_LEN 16 /* IPV6 address length */ ++ ++/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ ++#define IP_TOS46(ip_body) \ ++ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ ++ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) ++ ++/* IPV6 extension headers (options) */ ++#define IPV6_EXTHDR_HOP 0 ++#define IPV6_EXTHDR_ROUTING 43 ++#define IPV6_EXTHDR_FRAGMENT 44 ++#define IPV6_EXTHDR_AUTH 51 ++#define IPV6_EXTHDR_NONE 59 ++#define IPV6_EXTHDR_DEST 60 ++ ++#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \ ++ ((prot) == IPV6_EXTHDR_ROUTING) || \ ++ ((prot) == IPV6_EXTHDR_FRAGMENT) || \ ++ ((prot) == IPV6_EXTHDR_AUTH) || \ ++ ((prot) == IPV6_EXTHDR_NONE) || \ ++ ((prot) == IPV6_EXTHDR_DEST)) ++ ++#define IPV6_MIN_HLEN 40 ++ ++#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3) ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr { ++ uint8 nexthdr; ++ uint8 hdrlen; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag { ++ uint8 nexthdr; ++ uint8 rsvd; ++ uint16 frag_off; ++ uint32 ident; ++} BWL_POST_PACKED_STRUCT; ++ ++static INLINE int32 ++ipv6_exthdr_len(uint8 *h, uint8 *proto) ++{ ++ uint16 len = 0, hlen; ++ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h; ++ ++ while (IPV6_EXTHDR(eh->nexthdr)) { ++ if (eh->nexthdr == IPV6_EXTHDR_NONE) ++ return -1; ++ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT) ++ hlen = 8; ++ else if (eh->nexthdr == IPV6_EXTHDR_AUTH) ++ hlen = (eh->hdrlen + 2) << 2; ++ else ++ hlen = IPV6_EXTHDR_LEN(eh); ++ ++ len += hlen; ++ eh = (struct ipv6_exthdr *)(h + len); ++ } ++ ++ *proto = eh->nexthdr; ++ return len; ++} ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bcmip_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h b/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h +new file mode 100755 +index 0000000..c72eb31 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/bcmipv6.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental constants relating to Neighbor Discovery Protocol ++ * ++ * $Id: bcmipv6.h 305568 2011-12-29 20:21:17Z $ ++ */ ++ ++#ifndef _bcmipv6_h_ ++#define _bcmipv6_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define ICMPV6_HEADER_TYPE 0x3A ++#define ICMPV6_PKT_TYPE_NS 135 ++#define ICMPV6_PKT_TYPE_NA 136 ++ ++#define ICMPV6_ND_OPT_TYPE_TARGET_MAC 2 ++#define ICMPV6_ND_OPT_TYPE_SRC_MAC 1 ++ ++#define IPV6_VERSION 6 ++#define IPV6_HOP_LIMIT 255 ++ ++#define IPV6_ADDR_NULL(a) ((a[0] | a[1] | a[2] | a[3] | a[4] | \ ++ a[5] | a[6] | a[7] | a[8] | a[9] | \ ++ a[10] | a[11] | a[12] | a[13] | \ ++ a[14] | a[15]) == 0) ++ ++/* IPV6 address */ ++BWL_PRE_PACKED_STRUCT struct ipv6_addr { ++ uint8 addr[16]; ++} BWL_POST_PACKED_STRUCT; ++ ++#ifndef IL_BIGENDIAN ++ ++/* ICMPV6 Header */ ++BWL_PRE_PACKED_STRUCT struct icmp6_hdr { ++ uint8 icmp6_type; ++ uint8 icmp6_code; ++ uint16 icmp6_cksum; ++ BWL_PRE_PACKED_STRUCT union { ++ uint32 reserved; ++ BWL_PRE_PACKED_STRUCT struct nd_advt { ++ uint32 reserved1:5, ++ override:1, ++ solicited:1, ++ router:1, ++ reserved2:24; ++ } BWL_POST_PACKED_STRUCT nd_advt; ++ } BWL_POST_PACKED_STRUCT opt; ++} BWL_POST_PACKED_STRUCT; ++ ++/* Ipv6 Header Format */ ++BWL_PRE_PACKED_STRUCT struct ipv6_hdr { ++ uint8 priority:4, ++ version:4; ++ uint8 flow_lbl[3]; ++ uint16 payload_len; ++ uint8 nexthdr; ++ uint8 hop_limit; ++ struct ipv6_addr saddr; ++ struct ipv6_addr daddr; ++} BWL_POST_PACKED_STRUCT; ++ ++/* Neighbor Advertisement/Solicitation Packet Structure */ ++BWL_PRE_PACKED_STRUCT struct nd_msg { ++ struct icmp6_hdr icmph; ++ struct ipv6_addr target; ++} BWL_POST_PACKED_STRUCT; ++ ++ ++/* Neighibor Solicitation/Advertisement Optional Structure */ ++BWL_PRE_PACKED_STRUCT struct nd_msg_opt { ++ uint8 type; ++ uint8 len; ++ uint8 mac_addr[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++#endif /* IL_BIGENDIAN */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* !defined(_bcmipv6_h_) */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h b/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h +new file mode 100755 +index 0000000..85d664c +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/ethernet.h +@@ -0,0 +1,202 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. ++ * ++ * $Id: ethernet.h 316696 2012-02-23 03:29:35Z $ ++ */ ++ ++#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ ++#define _NET_ETHERNET_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include "typedefs.h" ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* ++ * The number of bytes in an ethernet (MAC) address. ++ */ ++#define ETHER_ADDR_LEN 6 ++ ++/* ++ * The number of bytes in the type field. ++ */ ++#define ETHER_TYPE_LEN 2 ++ ++/* ++ * The number of bytes in the trailing CRC field. ++ */ ++#define ETHER_CRC_LEN 4 ++ ++/* ++ * The length of the combined header. ++ */ ++#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) ++ ++/* ++ * The minimum packet length. ++ */ ++#define ETHER_MIN_LEN 64 ++ ++/* ++ * The minimum packet user data length. ++ */ ++#define ETHER_MIN_DATA 46 ++ ++/* ++ * The maximum packet length. ++ */ ++#define ETHER_MAX_LEN 1518 ++ ++/* ++ * The maximum packet user data length. ++ */ ++#define ETHER_MAX_DATA 1500 ++ ++/* ether types */ ++#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ ++#define ETHER_TYPE_IP 0x0800 /* IP */ ++#define ETHER_TYPE_ARP 0x0806 /* ARP */ ++#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ ++#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ ++#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ ++#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ ++#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ ++#define ETHER_TYPE_WAI 0x88b4 /* WAI */ ++#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ ++ ++#define ETHER_TYPE_PPP_SES 0x8864 /* PPPoE Session */ ++ ++/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ ++#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ ++ ++/* ether header */ ++#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ ++#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ ++#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ ++ ++/* ++ * A macro to validate a length with ++ */ ++#define ETHER_IS_VALID_LEN(foo) \ ++ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) ++ ++#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ ++ ((uint8 *)ea)[0] = 0x01; \ ++ ((uint8 *)ea)[1] = 0x00; \ ++ ((uint8 *)ea)[2] = 0x5e; \ ++ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ ++ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ ++ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ ++} ++ ++#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ ++/* ++ * Structure of a 10Mb/s Ethernet header. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 ether_type; ++} BWL_POST_PACKED_STRUCT; ++ ++/* ++ * Structure of a 48-bit Ethernet address. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_addr { ++ uint8 octet[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ ++ ++/* ++ * Takes a pointer, set, test, clear, toggle locally admininistered ++ * address bit in the 48-bit Ethernet address. ++ */ ++#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) ++#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) ++#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) ++#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) ++ ++/* Takes a pointer, marks unicast address bit in the MAC address */ ++#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) ++ ++/* ++ * Takes a pointer, returns true if a 48-bit multicast address ++ * (including broadcast, since it is all ones) ++ */ ++#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) ++ ++/* Copy an ethernet address in reverse order */ ++#define ether_rcopy(s, d) \ ++do { \ ++ ((uint16 *)(d))[2] = ((uint16 *)(s))[2]; \ ++ ((uint16 *)(d))[1] = ((uint16 *)(s))[1]; \ ++ ((uint16 *)(d))[0] = ((uint16 *)(s))[0]; \ ++} while (0) ++ ++/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ ++#define eacmp(a, b) ((((uint16 *)(a))[0] ^ ((uint16 *)(b))[0]) | \ ++ (((uint16 *)(a))[1] ^ ((uint16 *)(b))[1]) | \ ++ (((uint16 *)(a))[2] ^ ((uint16 *)(b))[2])) ++ ++#define ether_cmp(a, b) eacmp(a, b) ++ ++/* copy an ethernet address - assumes the pointers can be referenced as shorts */ ++#define eacopy(s, d) \ ++do { \ ++ ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \ ++ ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \ ++ ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \ ++} while (0) ++ ++#define ether_copy(s, d) eacopy(s, d) ++ ++ ++static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; ++static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; ++ ++#define ETHER_ISBCAST(ea) ((((const uint8 *)(ea))[0] & \ ++ ((const uint8 *)(ea))[1] & \ ++ ((const uint8 *)(ea))[2] & \ ++ ((const uint8 *)(ea))[3] & \ ++ ((const uint8 *)(ea))[4] & \ ++ ((const uint8 *)(ea))[5]) == 0xff) ++#define ETHER_ISNULLADDR(ea) ((((const uint8 *)(ea))[0] | \ ++ ((const uint8 *)(ea))[1] | \ ++ ((const uint8 *)(ea))[2] | \ ++ ((const uint8 *)(ea))[3] | \ ++ ((const uint8 *)(ea))[4] | \ ++ ((const uint8 *)(ea))[5]) == 0) ++ ++#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \ ++ ((const uint16 *)(da))[1] | \ ++ ((const uint16 *)(da))[2]) == 0) ++ ++ ++#define ETHER_MOVE_HDR(d, s) \ ++do { \ ++ struct ether_header t; \ ++ t = *(struct ether_header *)(s); \ ++ *(struct ether_header *)(d) = t; \ ++} while (0) ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _NET_ETHERNET_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/vlan.h b/drivers/bcmdrivers/gmac/src/include/proto/vlan.h +new file mode 100755 +index 0000000..5393070 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/vlan.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * 802.1Q VLAN protocol definitions ++ * ++ * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _vlan_h_ ++#define _vlan_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#ifndef VLAN_VID_MASK ++#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ ++#endif ++#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ ++#define VLAN_PRI_SHIFT 13 /* user priority */ ++ ++#define VLAN_PRI_MASK 7 /* 3 bits of priority */ ++ ++#define VLAN_TCI_OFFSET 14 /* offset of tag ctrl info field */ ++ ++#define VLAN_TAG_LEN 4 ++#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ ++ ++#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ ++ ++struct ethervlan_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 vlan_type; /* 0x8100 */ ++ uint16 vlan_tag; /* priority, cfi and vid */ ++ uint16 ether_type; ++}; ++ ++#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#define ETHERVLAN_MOVE_HDR(d, s) \ ++do { \ ++ struct ethervlan_header t; \ ++ t = *(struct ethervlan_header *)(s); \ ++ *(struct ethervlan_header *)(d) = t; \ ++} while (0) ++ ++#endif /* _vlan_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/proto/wpa.h b/drivers/bcmdrivers/gmac/src/include/proto/wpa.h +new file mode 100755 +index 0000000..98b09a2 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/proto/wpa.h +@@ -0,0 +1,169 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Fundamental types and constants relating to WPA ++ * ++ * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ ++ */ ++ ++#ifndef _proto_wpa_h_ ++#define _proto_wpa_h_ ++ ++#include ++#include ++ ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* Reason Codes */ ++ ++/* 13 through 23 taken from IEEE Std 802.11i-2004 */ ++#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ ++#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ ++#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ ++#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ ++#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from ++ * (re-)assoc. request/probe response ++ */ ++#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ ++#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ ++#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ ++#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ ++#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ ++#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ ++ ++#define WPA2_PMKID_LEN 16 ++ ++/* WPA IE fixed portion */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ uint8 oui[3]; /* IE OUI */ ++ uint8 oui_type; /* OUI type */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; ++#define WPA_IE_OUITYPE_LEN 4 ++#define WPA_IE_FIXED_LEN 8 ++#define WPA_IE_TAG_FIXED_LEN 6 ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; ++#define WPA_RSN_IE_FIXED_LEN 4 ++#define WPA_RSN_IE_TAG_FIXED_LEN 2 ++typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; ++ ++/* WPA suite/multicast suite */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 oui[3]; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; ++#define WPA_SUITE_LEN 4 ++ ++/* WPA unicast suite list/key management suite list */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_suite_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; ++#define WPA_IE_SUITE_COUNT_LEN 2 ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_pmkid_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; ++ ++/* WPA cipher suites */ ++#define WPA_CIPHER_NONE 0 /* None */ ++#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ ++#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ ++#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ ++#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ ++#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ ++#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */ ++#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */ ++ ++ ++#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ ++ (cipher) == WPA_CIPHER_WEP_40 || \ ++ (cipher) == WPA_CIPHER_WEP_104 || \ ++ (cipher) == WPA_CIPHER_TKIP || \ ++ (cipher) == WPA_CIPHER_AES_OCB || \ ++ (cipher) == WPA_CIPHER_AES_CCM || \ ++ (cipher) == WPA_CIPHER_TPK) ++ ++ ++/* WPA TKIP countermeasures parameters */ ++#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ ++#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ ++ ++/* RSN IE defines */ ++#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ ++ ++/* RSN Capabilities defined in 802.11i */ ++#define RSN_CAP_PREAUTH 0x0001 ++#define RSN_CAP_NOPAIRWISE 0x0002 ++#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C ++#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 ++#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 ++#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 ++#define RSN_CAP_1_REPLAY_CNTR 0 ++#define RSN_CAP_2_REPLAY_CNTRS 1 ++#define RSN_CAP_4_REPLAY_CNTRS 2 ++#define RSN_CAP_16_REPLAY_CNTRS 3 ++#ifdef MFP ++#define RSN_CAP_MFPR 0x0040 ++#define RSN_CAP_MFPC 0x0080 ++#endif ++ ++/* WPA capabilities defined in 802.11i */ ++#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS ++#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS ++#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT ++#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK ++ ++/* WPA capabilities defined in 802.11zD9.0 */ ++#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */ ++ ++/* WPA Specific defines */ ++#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ ++#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */ ++ ++#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH ++ ++#define WPA2_PMKID_COUNT_LEN 2 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _proto_wpa_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbchipc.h b/drivers/bcmdrivers/gmac/src/include/sbchipc.h +new file mode 100755 +index 0000000..a03df39 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbchipc.h +@@ -0,0 +1,2517 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * SiliconBackplane Chipcommon core hardware definitions. ++ * ++ * The chipcommon core provides chip identification, SB control, ++ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, ++ * GPIO interface, extbus, and support for serial and parallel flashes. ++ * ++ * $Id: sbchipc.h 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++typedef struct eci_prerev35 { ++ uint32 eci_output; ++ uint32 eci_control; ++ uint32 eci_inputlo; ++ uint32 eci_inputmi; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolaritymi; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskmi; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventmi; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskmi; ++ uint32 eci_eventmaskhi; ++ uint32 PAD[3]; ++} eci_prerev35_t; ++ ++typedef struct eci_rev35 { ++ uint32 eci_outputlo; ++ uint32 eci_outputhi; ++ uint32 eci_controllo; ++ uint32 eci_controlhi; ++ uint32 eci_inputlo; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskhi; ++ uint32 eci_auxtx; ++ uint32 eci_auxrx; ++ uint32 eci_datatag; ++ uint32 eci_uartescvalue; ++ uint32 eci_autobaudctr; ++ uint32 eci_uartfifolevel; ++} eci_rev35_t; ++ ++typedef struct flash_config { ++ uint32 PAD[19]; ++ /* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */ ++ uint32 flashstrconfig; ++} flash_config_t; ++ ++typedef volatile struct { ++ uint32 chipid; /* 0x0 */ ++ uint32 capabilities; ++ uint32 corecontrol; /* corerev >= 1 */ ++ uint32 bist; ++ ++ /* OTP */ ++ uint32 otpstatus; /* 0x10, corerev >= 10 */ ++ uint32 otpcontrol; ++ uint32 otpprog; ++ uint32 otplayout; /* corerev >= 23 */ ++ ++ /* Interrupt control */ ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; ++ ++ /* Chip specific regs */ ++ uint32 chipcontrol; /* 0x28, rev >= 11 */ ++ uint32 chipstatus; /* 0x2c, rev >= 11 */ ++ ++ /* Jtag Master */ ++ uint32 jtagcmd; /* 0x30, rev >= 10 */ ++ uint32 jtagir; ++ uint32 jtagdr; ++ uint32 jtagctrl; ++ ++ /* serial flash interface registers */ ++ uint32 flashcontrol; /* 0x40 */ ++ uint32 flashaddress; ++ uint32 flashdata; ++ uint32 otplayoutextension; /* rev >= 35 */ ++ ++ /* Silicon backplane configuration broadcast control */ ++ uint32 broadcastaddress; /* 0x50 */ ++ uint32 broadcastdata; ++ ++ /* gpio - cleared only by power-on-reset */ ++ uint32 gpiopullup; /* 0x58, corerev >= 20 */ ++ uint32 gpiopulldown; /* 0x5c, corerev >= 20 */ ++ uint32 gpioin; /* 0x60 */ ++ uint32 gpioout; /* 0x64 */ ++ uint32 gpioouten; /* 0x68 */ ++ uint32 gpiocontrol; /* 0x6C */ ++ uint32 gpiointpolarity; /* 0x70 */ ++ uint32 gpiointmask; /* 0x74 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioevent; ++ uint32 gpioeventintmask; ++ ++ /* Watchdog timer */ ++ uint32 watchdog; /* 0x80 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioeventintpolarity; ++ ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ uint32 gpiotimerval; /* 0x88 */ ++ uint32 gpiotimeroutmask; ++ ++ /* clock control */ ++ uint32 clockcontrol_n; /* 0x90 */ ++ uint32 clockcontrol_sb; /* aka m0 */ ++ uint32 clockcontrol_pci; /* aka m1 */ ++ uint32 clockcontrol_m2; /* mii/uart/mipsref */ ++ uint32 clockcontrol_m3; /* cpu */ ++ uint32 clkdiv; /* corerev >= 3 */ ++ uint32 gpiodebugsel; /* corerev >= 28 */ ++ uint32 capabilities_ext; /* 0xac */ ++ ++ /* pll delay registers (corerev >= 4) */ ++ uint32 pll_on_delay; /* 0xb0 */ ++ uint32 fref_sel_delay; ++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ uint32 PAD; ++ ++ /* Instaclock registers (corerev >= 10) */ ++ uint32 system_clk_ctl; /* 0xc0 */ ++ uint32 clkstatestretch; ++ uint32 PAD[2]; ++ ++ /* Indirect backplane access (corerev >= 22) */ ++ uint32 bp_addrlow; /* 0xd0 */ ++ uint32 bp_addrhigh; ++ uint32 bp_data; ++ uint32 PAD; ++ uint32 bp_indaccess; ++ /* SPI registers, corerev >= 37 */ ++ uint32 gsioctrl; ++ uint32 gsioaddress; ++ uint32 gsiodata; ++ ++ /* More clock dividers (corerev >= 32) */ ++ uint32 clkdiv2; ++ /* FAB ID (corerev >= 40) */ ++ uint32 otpcontrol1; ++ uint32 fabid; /* 0xf8 */ ++ ++ /* In AI chips, pointer to erom */ ++ uint32 eromptr; /* 0xfc */ ++ ++ /* ExtBus control registers (corerev >= 3) */ ++ uint32 pcmcia_config; /* 0x100 */ ++ uint32 pcmcia_memwait; ++ uint32 pcmcia_attrwait; ++ uint32 pcmcia_iowait; ++ uint32 ide_config; ++ uint32 ide_memwait; ++ uint32 ide_attrwait; ++ uint32 ide_iowait; ++ uint32 prog_config; ++ uint32 prog_waitcount; ++ uint32 flash_config; ++ uint32 flash_waitcount; ++ uint32 SECI_config; /* 0x130 SECI configuration */ ++ uint32 SECI_status; ++ uint32 SECI_statusmask; ++ uint32 SECI_rxnibchanged; ++ ++ union { /* 0x140 */ ++ /* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */ ++ struct eci_prerev35 lt35; ++ struct eci_rev35 ge35; ++ /* Other interfaces */ ++ struct flash_config flashconf; ++ uint32 PAD[20]; ++ } eci; ++ ++ /* SROM interface (corerev >= 32) */ ++ uint32 sromcontrol; /* 0x190 */ ++ uint32 sromaddress; ++ uint32 sromdata; ++ uint32 PAD[1]; /* 0x19C */ ++ /* NAND flash registers for BCM4706 (corerev = 31) */ ++ uint32 nflashctrl; /* 0x1a0 */ ++ uint32 nflashconf; ++ uint32 nflashcoladdr; ++ uint32 nflashrowaddr; ++ uint32 nflashdata; ++ uint32 nflashwaitcnt0; /* 0x1b4 */ ++ uint32 PAD[2]; ++ ++ uint32 seci_uart_data; /* 0x1C0 */ ++ uint32 seci_uart_bauddiv; ++ uint32 seci_uart_fcr; ++ uint32 seci_uart_lcr; ++ uint32 seci_uart_mcr; ++ uint32 seci_uart_lsr; ++ uint32 seci_uart_msr; ++ uint32 seci_uart_baudadj; ++ /* Clock control and hardware workarounds (corerev >= 20) */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; ++ uint32 PAD[70]; ++ ++ /* UARTs */ ++ uint8 uart0data; /* 0x300 */ ++ uint8 uart0imr; ++ uint8 uart0fcr; ++ uint8 uart0lcr; ++ uint8 uart0mcr; ++ uint8 uart0lsr; ++ uint8 uart0msr; ++ uint8 uart0scratch; ++ uint8 PAD[248]; /* corerev >= 1 */ ++ ++ uint8 uart1data; /* 0x400 */ ++ uint8 uart1imr; ++ uint8 uart1fcr; ++ uint8 uart1lcr; ++ uint8 uart1mcr; ++ uint8 uart1lsr; ++ uint8 uart1msr; ++ uint8 uart1scratch; ++ uint32 PAD[126]; ++ ++ /* PMU registers (corerev >= 20) */ ++ /* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP. ++ * The CPU must read them twice, compare, and retry if different. ++ */ ++ uint32 pmucontrol; /* 0x600 */ ++ uint32 pmucapabilities; ++ uint32 pmustatus; ++ uint32 res_state; ++ uint32 res_pending; ++ uint32 pmutimer; ++ uint32 min_res_mask; ++ uint32 max_res_mask; ++ uint32 res_table_sel; ++ uint32 res_dep_mask; ++ uint32 res_updn_timer; ++ uint32 res_timer; ++ uint32 clkstretch; ++ uint32 pmuwatchdog; ++ uint32 gpiosel; /* 0x638, rev >= 1 */ ++ uint32 gpioenable; /* 0x63c, rev >= 1 */ ++ uint32 res_req_timer_sel; ++ uint32 res_req_timer; ++ uint32 res_req_mask; ++ uint32 PAD; ++ uint32 chipcontrol_addr; /* 0x650 */ ++ uint32 chipcontrol_data; /* 0x654 */ ++ uint32 regcontrol_addr; ++ uint32 regcontrol_data; ++ uint32 pllcontrol_addr; ++ uint32 pllcontrol_data; ++ uint32 pmustrapopt; /* 0x668, corerev >= 28 */ ++ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ ++ uint32 PAD[100]; ++ uint16 sromotp[512]; /* 0x800 */ ++#ifdef NFLASH_SUPPORT ++ /* Nand flash MLC controller registers (corerev >= 38) */ ++ uint32 nand_revision; /* 0xC00 */ ++ uint32 nand_cmd_start; ++ uint32 nand_cmd_addr_x; ++ uint32 nand_cmd_addr; ++ uint32 nand_cmd_end_addr; ++ uint32 nand_cs_nand_select; ++ uint32 nand_cs_nand_xor; ++ uint32 PAD; ++ uint32 nand_spare_rd0; ++ uint32 nand_spare_rd4; ++ uint32 nand_spare_rd8; ++ uint32 nand_spare_rd12; ++ uint32 nand_spare_wr0; ++ uint32 nand_spare_wr4; ++ uint32 nand_spare_wr8; ++ uint32 nand_spare_wr12; ++ uint32 nand_acc_control; ++ uint32 PAD; ++ uint32 nand_config; ++ uint32 PAD; ++ uint32 nand_timing_1; ++ uint32 nand_timing_2; ++ uint32 nand_semaphore; ++ uint32 PAD; ++ uint32 nand_devid; ++ uint32 nand_devid_x; ++ uint32 nand_block_lock_status; ++ uint32 nand_intfc_status; ++ uint32 nand_ecc_corr_addr_x; ++ uint32 nand_ecc_corr_addr; ++ uint32 nand_ecc_unc_addr_x; ++ uint32 nand_ecc_unc_addr; ++ uint32 nand_read_error_count; ++ uint32 nand_corr_stat_threshold; ++ uint32 PAD[2]; ++ uint32 nand_read_addr_x; ++ uint32 nand_read_addr; ++ uint32 nand_page_program_addr_x; ++ uint32 nand_page_program_addr; ++ uint32 nand_copy_back_addr_x; ++ uint32 nand_copy_back_addr; ++ uint32 nand_block_erase_addr_x; ++ uint32 nand_block_erase_addr; ++ uint32 nand_inv_read_addr_x; ++ uint32 nand_inv_read_addr; ++ uint32 PAD[2]; ++ uint32 nand_blk_wr_protect; ++ uint32 PAD[3]; ++ uint32 nand_acc_control_cs1; ++ uint32 nand_config_cs1; ++ uint32 nand_timing_1_cs1; ++ uint32 nand_timing_2_cs1; ++ uint32 PAD[20]; ++ uint32 nand_spare_rd16; ++ uint32 nand_spare_rd20; ++ uint32 nand_spare_rd24; ++ uint32 nand_spare_rd28; ++ uint32 nand_cache_addr; ++ uint32 nand_cache_data; ++ uint32 nand_ctrl_config; ++ uint32 nand_ctrl_status; ++#endif /* NFLASH_SUPPORT */ ++ uint32 gci_corecaps0; /* GCI starting at 0xC00 */ ++ uint32 gci_corecaps1; ++ uint32 gci_corecaps2; ++ uint32 gci_corectrl; ++ uint32 gci_corestat; /* 0xC10 */ ++ uint32 PAD[11]; ++ uint32 gci_indirect_addr; /* 0xC40 */ ++ uint32 PAD[111]; ++ uint32 gci_chipctrl; /* 0xE00 */ ++} chipcregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#if defined(IL_BIGENDIAN) && defined(BCMHND74K) ++/* Selective swapped defines for those registers we need in ++ * big-endian code. ++ */ ++#define CC_CHIPID 4 ++#define CC_CAPABILITIES 0 ++#define CC_CHIPST 0x28 ++#define CC_EROMPTR 0xf8 ++ ++#else /* !IL_BIGENDIAN || !BCMHND74K */ ++ ++#define CC_CHIPID 0 ++#define CC_CAPABILITIES 4 ++#define CC_CHIPST 0x2c ++#define CC_EROMPTR 0xfc ++ ++#endif /* IL_BIGENDIAN && BCMHND74K */ ++ ++#define CC_OTPST 0x10 ++#define CC_JTAGCMD 0x30 ++#define CC_JTAGIR 0x34 ++#define CC_JTAGDR 0x38 ++#define CC_JTAGCTRL 0x3c ++#define CC_GPIOPU 0x58 ++#define CC_GPIOPD 0x5c ++#define CC_GPIOIN 0x60 ++#define CC_GPIOOUT 0x64 ++#define CC_GPIOOUTEN 0x68 ++#define CC_GPIOCTRL 0x6c ++#define CC_GPIOPOL 0x70 ++#define CC_GPIOINTM 0x74 ++#define CC_WATCHDOG 0x80 ++#define CC_CLKC_N 0x90 ++#define CC_CLKC_M0 0x94 ++#define CC_CLKC_M1 0x98 ++#define CC_CLKC_M2 0x9c ++#define CC_CLKC_M3 0xa0 ++#define CC_CLKDIV 0xa4 ++#define CC_SYS_CLK_CTL 0xc0 ++#define CC_CLK_CTL_ST SI_CLK_CTL_ST ++#define PMU_CTL 0x600 ++#define PMU_CAP 0x604 ++#define PMU_ST 0x608 ++#define PMU_RES_STATE 0x60c ++#define PMU_TIMER 0x614 ++#define PMU_MIN_RES_MASK 0x618 ++#define PMU_MAX_RES_MASK 0x61c ++#define CC_CHIPCTL_ADDR 0x650 ++#define CC_CHIPCTL_DATA 0x654 ++#define PMU_REG_CONTROL_ADDR 0x658 ++#define PMU_REG_CONTROL_DATA 0x65C ++#define PMU_PLL_CONTROL_ADDR 0x660 ++#define PMU_PLL_CONTROL_DATA 0x664 ++#define CC_SROM_CTRL 0x190 ++#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ ++#define CC_GCI_INDIRECT_ADDR_REG 0xC40 ++#define CC_GCI_CHIP_CTRL_REG 0xE00 ++#define CC_GCI_CC_OFFSET_2 2 ++#define CC_GCI_CC_OFFSET_5 5 ++ ++#ifdef NFLASH_SUPPORT ++/* NAND flash support */ ++#define CC_NAND_REVISION 0xC00 ++#define CC_NAND_CMD_START 0xC04 ++#define CC_NAND_CMD_ADDR 0xC0C ++#define CC_NAND_SPARE_RD_0 0xC20 ++#define CC_NAND_SPARE_RD_4 0xC24 ++#define CC_NAND_SPARE_RD_8 0xC28 ++#define CC_NAND_SPARE_RD_C 0xC2C ++#define CC_NAND_CONFIG 0xC48 ++#define CC_NAND_DEVID 0xC60 ++#define CC_NAND_DEVID_EXT 0xC64 ++#define CC_NAND_INTFC_STATUS 0xC6C ++#endif /* NFLASH_SUPPORT */ ++ ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 ++#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ ++#define CID_TYPE_SHIFT 28 ++ ++/* capabilities */ ++#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ ++#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ ++#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ ++#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ ++#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ ++#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */ ++#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ ++#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ ++ ++#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ ++#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ ++ ++/* capabilities extension */ ++#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ ++ ++/* PLL type */ ++#define PLL_NONE 0x00000000 ++#define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */ ++#define PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */ ++#define PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */ ++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ ++#define PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */ ++ ++/* ILP clock */ ++#define ILP_CLOCK 32000 ++ ++/* ALP clock on pre-PMU chips */ ++#define ALP_CLOCK 20000000 ++ ++#define NS_ALP_CLOCK 125000000 ++#define NS_SLOW_ALP_CLOCK 100000000 ++#define NS_CPU_CLOCK 1000000000 ++#define NS_SLOW_CPU_CLOCK 800000000 ++#define NS_SI_CLOCK 250000000 ++#define NS_SLOW_SI_CLOCK 200000000 ++#define NS_FAST_MEM_CLOCK 800000000 ++#define NS_MEM_CLOCK 533000000 ++#define NS_SLOW_MEM_CLOCK 400000000 ++ ++/* HT clock */ ++#define HT_CLOCK 80000000 ++ ++/* corecontrol */ ++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ ++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ ++#define CC_ASYNCGPIO 0x00000004 /* 1=generate GPIO interrupt without backplane clock */ ++#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */ ++ ++/* 4321 chipcontrol */ ++#define CHIPCTRL_4321A0_DEFAULT 0x3a4 ++#define CHIPCTRL_4321A1_DEFAULT 0x0a4 ++#define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */ ++ ++/* Fields in the otpstatus register in rev >= 21 */ ++#define OTPS_OL_MASK 0x000000ff ++#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */ ++#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */ ++#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */ ++#define OTPS_OL_GU 0x00000008 /* general use region is locked */ ++#define OTPS_GUP_MASK 0x00000f00 ++#define OTPS_GUP_SHIFT 8 ++#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ ++#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ ++#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ ++#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ ++#define OTPS_READY 0x00001000 ++#define OTPS_RV(x) (1 << (16 + (x))) /* redundancy entry valid */ ++#define OTPS_RV_MASK 0x0fff0000 ++#define OTPS_PROGOK 0x40000000 ++ ++/* Fields in the otpcontrol register in rev >= 21 */ ++#define OTPC_PROGSEL 0x00000001 ++#define OTPC_PCOUNT_MASK 0x0000000e ++#define OTPC_PCOUNT_SHIFT 1 ++#define OTPC_VSEL_MASK 0x000000f0 ++#define OTPC_VSEL_SHIFT 4 ++#define OTPC_TMM_MASK 0x00000700 ++#define OTPC_TMM_SHIFT 8 ++#define OTPC_ODM 0x00000800 ++#define OTPC_PROGEN 0x80000000 ++ ++/* Fields in the 40nm otpcontrol register in rev >= 40 */ ++#define OTPC_40NM_PROGSEL_SHIFT 0 ++#define OTPC_40NM_PCOUNT_SHIFT 1 ++#define OTPC_40NM_PCOUNT_WR 0xA ++#define OTPC_40NM_PCOUNT_V1X 0xB ++#define OTPC_40NM_REGCSEL_SHIFT 5 ++#define OTPC_40NM_REGCSEL_DEF 0x4 ++#define OTPC_40NM_PROGIN_SHIFT 8 ++#define OTPC_40NM_R2X_SHIFT 10 ++#define OTPC_40NM_ODM_SHIFT 11 ++#define OTPC_40NM_DF_SHIFT 15 ++#define OTPC_40NM_VSEL_SHIFT 16 ++#define OTPC_40NM_VSEL_WR 0xA ++#define OTPC_40NM_VSEL_V1X 0xA ++#define OTPC_40NM_VSEL_R1X 0x5 ++#define OTPC_40NM_COFAIL_SHIFT 30 ++ ++#define OTPC1_CPCSEL_SHIFT 0 ++#define OTPC1_CPCSEL_DEF 6 ++#define OTPC1_TM_SHIFT 8 ++#define OTPC1_TM_WR 0x84 ++#define OTPC1_TM_V1X 0x84 ++#define OTPC1_TM_R1X 0x4 ++ ++/* Fields in otpprog in rev >= 21 and HND OTP */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_COL_SHIFT 0 ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_OC_MASK 0x0f000000 ++#define OTPP_OC_SHIFT 24 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE_MASK 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_START_BUSY 0x80000000 ++#define OTPP_READ 0x40000000 /* HND OTP */ ++ ++/* Fields in otplayout register */ ++#define OTPL_HWRGN_OFF_MASK 0x00000FFF ++#define OTPL_HWRGN_OFF_SHIFT 0 ++#define OTPL_WRAP_REVID_MASK 0x00F80000 ++#define OTPL_WRAP_REVID_SHIFT 19 ++#define OTPL_WRAP_TYPE_MASK 0x00070000 ++#define OTPL_WRAP_TYPE_SHIFT 16 ++#define OTPL_WRAP_TYPE_65NM 0 ++#define OTPL_WRAP_TYPE_40NM 1 ++ ++/* otplayout reg corerev >= 36 */ ++#define OTP_CISFORMAT_NEW 0x80000000 ++ ++/* Opcodes for OTPP_OC field */ ++#define OTPPOC_READ 0 ++#define OTPPOC_BIT_PROG 1 ++#define OTPPOC_VERIFY 3 ++#define OTPPOC_INIT 4 ++#define OTPPOC_SET 5 ++#define OTPPOC_RESET 6 ++#define OTPPOC_OCST 7 ++#define OTPPOC_ROW_LOCK 8 ++#define OTPPOC_PRESCN_TEST 9 ++ ++/* Opcodes for OTPP_OC field (40NM) */ ++#define OTPPOC_READ_40NM 0 ++#define OTPPOC_PROG_ENABLE_40NM 1 ++#define OTPPOC_PROG_DISABLE_40NM 2 ++#define OTPPOC_VERIFY_40NM 3 ++#define OTPPOC_WORD_VERIFY_1_40NM 4 ++#define OTPPOC_ROW_LOCK_40NM 5 ++#define OTPPOC_STBY_40NM 6 ++#define OTPPOC_WAKEUP_40NM 7 ++#define OTPPOC_WORD_VERIFY_0_40NM 8 ++#define OTPPOC_PRESCN_TEST_40NM 9 ++#define OTPPOC_BIT_PROG_40NM 10 ++#define OTPPOC_WORDPROG_40NM 11 ++#define OTPPOC_BURNIN_40NM 12 ++#define OTPPOC_AUTORELOAD_40NM 13 ++#define OTPPOC_OVST_READ_40NM 14 ++#define OTPPOC_OVST_PROG_40NM 15 ++ ++/* Fields in otplayoutextension */ ++#define OTPLAYOUTEXT_FUSE_MASK 0x3FF ++ ++ ++/* Jtagm characteristics that appeared at a given corerev */ ++#define JTAGM_CREV_OLD 10 /* Old command set, 16bit max IR */ ++#define JTAGM_CREV_IRP 22 /* Able to do pause-ir */ ++#define JTAGM_CREV_RTI 28 /* Able to do return-to-idle */ ++ ++/* jtagcmd */ ++#define JCMD_START 0x80000000 ++#define JCMD_BUSY 0x80000000 ++#define JCMD_STATE_MASK 0x60000000 ++#define JCMD_STATE_TLR 0x00000000 /* Test-logic-reset */ ++#define JCMD_STATE_PIR 0x20000000 /* Pause IR */ ++#define JCMD_STATE_PDR 0x40000000 /* Pause DR */ ++#define JCMD_STATE_RTI 0x60000000 /* Run-test-idle */ ++#define JCMD0_ACC_MASK 0x0000f000 ++#define JCMD0_ACC_IRDR 0x00000000 ++#define JCMD0_ACC_DR 0x00001000 ++#define JCMD0_ACC_IR 0x00002000 ++#define JCMD0_ACC_RESET 0x00003000 ++#define JCMD0_ACC_IRPDR 0x00004000 ++#define JCMD0_ACC_PDR 0x00005000 ++#define JCMD0_IRW_MASK 0x00000f00 ++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ ++#define JCMD_ACC_IRDR 0x00000000 ++#define JCMD_ACC_DR 0x00010000 ++#define JCMD_ACC_IR 0x00020000 ++#define JCMD_ACC_RESET 0x00030000 ++#define JCMD_ACC_IRPDR 0x00040000 ++#define JCMD_ACC_PDR 0x00050000 ++#define JCMD_ACC_PIR 0x00060000 ++#define JCMD_ACC_IRDR_I 0x00070000 /* rev 28: return to run-test-idle */ ++#define JCMD_ACC_DR_I 0x00080000 /* rev 28: return to run-test-idle */ ++#define JCMD_IRW_MASK 0x00001f00 ++#define JCMD_IRW_SHIFT 8 ++#define JCMD_DRW_MASK 0x0000003f ++ ++/* jtagctrl */ ++#define JCTRL_FORCE_CLK 4 /* Force clock */ ++#define JCTRL_EXT_EN 2 /* Enable external targets */ ++#define JCTRL_EN 1 /* Enable Jtag master */ ++ ++/* Fields in clkdiv */ ++#define CLKD_SFLASH 0x0f000000 ++#define CLKD_SFLASH_SHIFT 24 ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++#define CLKD_JTAG 0x00000f00 ++#define CLKD_JTAG_SHIFT 8 ++#define CLKD_UART 0x000000ff ++ ++#define CLKD2_SROM 0x00000003 ++ ++/* intstatus/intmask */ ++#define CI_GPIO 0x00000001 /* gpio intr */ ++#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */ ++#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */ ++#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */ ++#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */ ++#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */ ++#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */ ++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ ++ ++/* slow_clk_ctl */ ++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ ++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ ++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ ++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ ++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, ++ * 0: LPO is enabled ++ */ ++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, ++ * 0: power logic control ++ */ ++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors ++ * PLL clock disable requests from core ++ */ ++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't ++ * disable crystal when appropriate ++ */ ++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_SHIFT 16 ++ ++/* system_clk_ctl */ ++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ ++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ ++#define SYCC_FP 0x00000004 /* ForcePLLOn */ ++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_HR 0x00000010 /* Force HT */ ++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_SHIFT 16 ++ ++/* Indirect backplane access */ ++#define BPIA_BYTEEN 0x0000000f ++#define BPIA_SZ1 0x00000001 ++#define BPIA_SZ2 0x00000003 ++#define BPIA_SZ4 0x00000007 ++#define BPIA_SZ8 0x0000000f ++#define BPIA_WRITE 0x00000100 ++#define BPIA_START 0x00000200 ++#define BPIA_BUSY 0x00000200 ++#define BPIA_ERROR 0x00000400 ++ ++/* pcmcia/prog/flash_config */ ++#define CF_EN 0x00000001 /* enable */ ++#define CF_EM_MASK 0x0000000e /* mode */ ++#define CF_EM_SHIFT 1 ++#define CF_EM_FLASH 0 /* flash/asynchronous mode */ ++#define CF_EM_SYNC 2 /* synchronous mode */ ++#define CF_EM_PCMCIA 4 /* pcmcia mode */ ++#define CF_DS 0x00000010 /* destsize: 0=8bit, 1=16bit */ ++#define CF_BS 0x00000020 /* byteswap */ ++#define CF_CD_MASK 0x000000c0 /* clock divider */ ++#define CF_CD_SHIFT 6 ++#define CF_CD_DIV2 0x00000000 /* backplane/2 */ ++#define CF_CD_DIV3 0x00000040 /* backplane/3 */ ++#define CF_CD_DIV4 0x00000080 /* backplane/4 */ ++#define CF_CE 0x00000100 /* clock enable */ ++#define CF_SB 0x00000200 /* size/bytestrobe (synch only) */ ++ ++/* pcmcia_memwait */ ++#define PM_W0_MASK 0x0000003f /* waitcount0 */ ++#define PM_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PM_W1_SHIFT 8 ++#define PM_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PM_W2_SHIFT 16 ++#define PM_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PM_W3_SHIFT 24 ++ ++/* pcmcia_attrwait */ ++#define PA_W0_MASK 0x0000003f /* waitcount0 */ ++#define PA_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PA_W1_SHIFT 8 ++#define PA_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PA_W2_SHIFT 16 ++#define PA_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PA_W3_SHIFT 24 ++ ++/* pcmcia_iowait */ ++#define PI_W0_MASK 0x0000003f /* waitcount0 */ ++#define PI_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PI_W1_SHIFT 8 ++#define PI_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PI_W2_SHIFT 16 ++#define PI_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PI_W3_SHIFT 24 ++ ++/* prog_waitcount */ ++#define PW_W0_MASK 0x0000001f /* waitcount0 */ ++#define PW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PW_W1_SHIFT 8 ++#define PW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PW_W2_SHIFT 16 ++#define PW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PW_W3_SHIFT 24 ++ ++#define PW_W0 0x0000000c ++#define PW_W1 0x00000a00 ++#define PW_W2 0x00020000 ++#define PW_W3 0x01000000 ++ ++/* flash_waitcount */ ++#define FW_W0_MASK 0x0000003f /* waitcount0 */ ++#define FW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define FW_W1_SHIFT 8 ++#define FW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define FW_W2_SHIFT 16 ++#define FW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define FW_W3_SHIFT 24 ++ ++/* When Srom support present, fields in sromcontrol */ ++#define SRC_START 0x80000000 ++#define SRC_BUSY 0x80000000 ++#define SRC_OPCODE 0x60000000 ++#define SRC_OP_READ 0x00000000 ++#define SRC_OP_WRITE 0x20000000 ++#define SRC_OP_WRDIS 0x40000000 ++#define SRC_OP_WREN 0x60000000 ++#define SRC_OTPSEL 0x00000010 ++#define SRC_LOCK 0x00000008 ++#define SRC_SIZE_MASK 0x00000006 ++#define SRC_SIZE_1K 0x00000000 ++#define SRC_SIZE_4K 0x00000002 ++#define SRC_SIZE_16K 0x00000004 ++#define SRC_SIZE_SHIFT 1 ++#define SRC_PRESENT 0x00000001 ++ ++/* Fields in pmucontrol */ ++#define PCTL_ILP_DIV_MASK 0xffff0000 ++#define PCTL_ILP_DIV_SHIFT 16 ++#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ ++#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ ++#define PCTL_HT_REQ_EN 0x00000100 ++#define PCTL_ALP_REQ_EN 0x00000080 ++#define PCTL_XTALFREQ_MASK 0x0000007c ++#define PCTL_XTALFREQ_SHIFT 2 ++#define PCTL_ILP_DIV_EN 0x00000002 ++#define PCTL_LPO_SEL 0x00000001 ++ ++/* Fields in clkstretch */ ++#define CSTRETCH_HT 0xffff0000 ++#define CSTRETCH_ALP 0x0000ffff ++ ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 ++ ++/* clockcontrol_n */ ++#define CN_N1_MASK 0x3f /* n1 control */ ++#define CN_N2_MASK 0x3f00 /* n2 control */ ++#define CN_N2_SHIFT 8 ++#define CN_PLLC_MASK 0xf0000 /* pll control */ ++#define CN_PLLC_SHIFT 16 ++ ++/* clockcontrol_sb/pci/uart */ ++#define CC_M1_MASK 0x3f /* m1 control */ ++#define CC_M2_MASK 0x3f00 /* m2 control */ ++#define CC_M2_SHIFT 8 ++#define CC_M3_MASK 0x3f0000 /* m3 control */ ++#define CC_M3_SHIFT 16 ++#define CC_MC_MASK 0x1f000000 /* mux control */ ++#define CC_MC_SHIFT 24 ++ ++/* N3M Clock control magic field values */ ++#define CC_F6_2 0x02 /* A factor of 2 in */ ++#define CC_F6_3 0x03 /* 6-bit fields like */ ++#define CC_F6_4 0x05 /* N1, M1 or M3 */ ++#define CC_F6_5 0x09 ++#define CC_F6_6 0x11 ++#define CC_F6_7 0x21 ++ ++#define CC_F5_BIAS 5 /* 5-bit fields get this added */ ++ ++#define CC_MC_BYPASS 0x08 ++#define CC_MC_M1 0x04 ++#define CC_MC_M1M2 0x02 ++#define CC_MC_M1M2M3 0x01 ++#define CC_MC_M1M3 0x11 ++ ++/* Type 2 Clock control magic field values */ ++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ ++#define CC_T2M2_BIAS 3 /* m2 bias */ ++ ++#define CC_T2MC_M1BYP 1 ++#define CC_T2MC_M2BYP 2 ++#define CC_T2MC_M3BYP 4 ++ ++/* Type 6 Clock control magic field values */ ++#define CC_T6_MMASK 1 /* bits of interest in m */ ++#define CC_T6_M0 120000000 /* sb clock for m = 0 */ ++#define CC_T6_M1 100000000 /* sb clock for m = 1 */ ++#define SB2MIPS_T6(sb) (2 * (sb)) ++ ++/* Common clock base */ ++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ ++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLLs */ ++ ++/* Clock control values for 200MHz in 5350 */ ++#define CLKC_5350_N 0x0311 ++#define CLKC_5350_M 0x04020009 ++ ++/* Flash types in the chipcommon capabilities register */ ++#define FLASH_NONE 0x000 /* No flash */ ++#define SFLASH_ST 0x100 /* ST serial flash */ ++#define SFLASH_AT 0x200 /* Atmel serial flash */ ++#define NFLASH 0x300 ++#define PFLASH 0x700 /* Parallel flash */ ++#define QSPIFLASH_ST 0x800 ++#define QSPIFLASH_AT 0x900 ++ ++/* Bits in the ExtBus config registers */ ++#define CC_CFG_EN 0x0001 /* Enable */ ++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ ++#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */ ++#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */ ++#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ ++#define CC_CFG_EM_IDE 0x0006 /* IDE */ ++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ ++#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */ ++#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */ ++#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */ ++#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */ ++ ++/* ExtBus address space */ ++#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ ++#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */ ++#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */ ++#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */ ++#define CC_EB_IDE 0x1a800000 /* IDE memory base */ ++#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */ ++#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */ ++#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */ ++#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */ ++ ++ ++/* Start/busy bit in flashcontrol */ ++#define SFLASH_OPCODE 0x000000ff ++#define SFLASH_ACTION 0x00000700 ++#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ ++#define SFLASH_START 0x80000000 ++#define SFLASH_BUSY SFLASH_START ++ ++/* flashcontrol action codes */ ++#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */ ++#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */ ++#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 addr bytes */ ++#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addr & 1 data bytes */ ++#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addr & 4 data bytes */ ++#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addr, 4 don't care & 4 data bytes */ ++#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addr, 1 don't care & 4 data bytes */ ++ ++/* flashcontrol action+opcodes for ST flashes */ ++#define SFLASH_ST_WREN 0x0006 /* Write Enable */ ++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ ++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ ++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ ++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ ++#define SFLASH_ST_PP 0x0302 /* Page Program */ ++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ ++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ ++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ ++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ ++#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */ ++#define SFLASH_ST_SSE 0x0220 /* Sub-sector Erase */ ++ ++#define SFLASH_MXIC_RDID 0x0390 /* Read Manufacture ID */ ++#define SFLASH_MXIC_MFID 0xc2 /* MXIC Manufacture ID */ ++ ++/* Status register bits for ST flashes */ ++#define SFLASH_ST_WIP 0x01 /* Write In Progress */ ++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ ++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ ++#define SFLASH_ST_BP_SHIFT 2 ++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ ++ ++/* flashcontrol action+opcodes for Atmel flashes */ ++#define SFLASH_AT_READ 0x07e8 ++#define SFLASH_AT_PAGE_READ 0x07d2 ++#define SFLASH_AT_BUF1_READ ++#define SFLASH_AT_BUF2_READ ++#define SFLASH_AT_STATUS 0x01d7 ++#define SFLASH_AT_BUF1_WRITE 0x0384 ++#define SFLASH_AT_BUF2_WRITE 0x0387 ++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 ++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 ++#define SFLASH_AT_BUF1_PROGRAM 0x0288 ++#define SFLASH_AT_BUF2_PROGRAM 0x0289 ++#define SFLASH_AT_PAGE_ERASE 0x0281 ++#define SFLASH_AT_BLOCK_ERASE 0x0250 ++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 ++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 ++#define SFLASH_AT_BUF1_LOAD 0x0253 ++#define SFLASH_AT_BUF2_LOAD 0x0255 ++#define SFLASH_AT_BUF1_COMPARE 0x0260 ++#define SFLASH_AT_BUF2_COMPARE 0x0261 ++#define SFLASH_AT_BUF1_REPROGRAM 0x0258 ++#define SFLASH_AT_BUF2_REPROGRAM 0x0259 ++ ++/* Status register bits for Atmel flashes */ ++#define SFLASH_AT_READY 0x80 ++#define SFLASH_AT_MISMATCH 0x40 ++#define SFLASH_AT_ID_MASK 0x38 ++#define SFLASH_AT_ID_SHIFT 3 ++ ++/* SPI register bits, corerev >= 37 */ ++#define GSIO_START 0x80000000 ++#define GSIO_BUSY GSIO_START ++ ++/* ++ * These are the UART port assignments, expressed as offsets from the base ++ * register. These assignments should hold for any serial port based on ++ * a 8250, 16450, or 16550(A). ++ */ ++ ++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ ++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ ++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ ++#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */ ++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ ++#define UART_IIR 2 /* In: Interrupt Identity Register */ ++#define UART_FCR 2 /* Out: FIFO Control Register */ ++#define UART_LCR 3 /* Out: Line Control Register */ ++#define UART_MCR 4 /* Out: Modem Control Register */ ++#define UART_LSR 5 /* In: Line Status Register */ ++#define UART_MSR 6 /* In: Modem Status Register */ ++#define UART_SCR 7 /* I/O: Scratch Register */ ++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ ++#define UART_LCR_WLEN8 0x03 /* Word length: 8 bits */ ++#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */ ++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ ++#define UART_LSR_RX_FIFO 0x80 /* Receive FIFO error */ ++#define UART_LSR_TDHR 0x40 /* Data-hold-register empty */ ++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ ++#define UART_LSR_BREAK 0x10 /* Break interrupt */ ++#define UART_LSR_FRAMING 0x08 /* Framing error */ ++#define UART_LSR_PARITY 0x04 /* Parity error */ ++#define UART_LSR_OVERRUN 0x02 /* Overrun error */ ++#define UART_LSR_RXRDY 0x01 /* Receiver ready */ ++#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ ++ ++/* Interrupt Identity Register (IIR) bits */ ++#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */ ++#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */ ++#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */ ++#define UART_IIR_NOINT 0x1 /* No interrupt pending */ ++#define UART_IIR_THRE 0x2 /* THR empty */ ++#define UART_IIR_RCVD_DATA 0x4 /* Received data available */ ++#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */ ++#define UART_IIR_CHAR_TIME 0xc /* Character time */ ++ ++/* Interrupt Enable Register (IER) bits */ ++#define UART_IER_EDSSI 8 /* enable modem status interrupt */ ++#define UART_IER_ELSI 4 /* enable receiver line status interrupt */ ++#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ ++#define UART_IER_ERBFI 1 /* enable data available interrupt */ ++ ++/* pmustatus */ ++#define PST_EXTLPOAVAIL 0x0100 ++#define PST_WDRESET 0x0080 ++#define PST_INTPEND 0x0040 ++#define PST_SBCLKST 0x0030 ++#define PST_SBCLKST_ILP 0x0010 ++#define PST_SBCLKST_ALP 0x0020 ++#define PST_SBCLKST_HT 0x0030 ++#define PST_ALPAVAIL 0x0008 ++#define PST_HTAVAIL 0x0004 ++#define PST_RESINIT 0x0003 ++ ++/* pmucapabilities */ ++#define PCAP_REV_MASK 0x000000ff ++#define PCAP_RC_MASK 0x00001f00 ++#define PCAP_RC_SHIFT 8 ++#define PCAP_TC_MASK 0x0001e000 ++#define PCAP_TC_SHIFT 13 ++#define PCAP_PC_MASK 0x001e0000 ++#define PCAP_PC_SHIFT 17 ++#define PCAP_VC_MASK 0x01e00000 ++#define PCAP_VC_SHIFT 21 ++#define PCAP_CC_MASK 0x1e000000 ++#define PCAP_CC_SHIFT 25 ++#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ ++#define PCAP5_PC_SHIFT 17 ++#define PCAP5_VC_MASK 0x07c00000 ++#define PCAP5_VC_SHIFT 22 ++#define PCAP5_CC_MASK 0xf8000000 ++#define PCAP5_CC_SHIFT 27 ++ ++/* PMU Resource Request Timer registers */ ++/* This is based on PmuRev0 */ ++#define PRRT_TIME_MASK 0x03ff ++#define PRRT_INTEN 0x0400 ++#define PRRT_REQ_ACTIVE 0x0800 ++#define PRRT_ALP_REQ 0x1000 ++#define PRRT_HT_REQ 0x2000 ++#define PRRT_HQ_REQ 0x4000 ++ ++/* PMU resource bit position */ ++#define PMURES_BIT(bit) (1 << (bit)) ++ ++/* PMU resource number limit */ ++#define PMURES_MAX_RESNUM 30 ++ ++/* PMU chip control0 register */ ++#define PMU_CHIPCTL0 0 ++ ++/* clock req types */ ++#define PMU_CC1_CLKREQ_TYPE_SHIFT 19 ++#define PMU_CC1_CLKREQ_TYPE_MASK (1 << PMU_CC1_CLKREQ_TYPE_SHIFT) ++ ++#define CLKREQ_TYPE_CONFIG_OPENDRAIN 0 ++#define CLKREQ_TYPE_CONFIG_PUSHPULL 1 ++ ++/* PMU chip control1 register */ ++#define PMU_CHIPCTL1 1 ++#define PMU_CC1_RXC_DLL_BYPASS 0x00010000 ++ ++#define PMU_CC1_IF_TYPE_MASK 0x00000030 ++#define PMU_CC1_IF_TYPE_RMII 0x00000000 ++#define PMU_CC1_IF_TYPE_MII 0x00000010 ++#define PMU_CC1_IF_TYPE_RGMII 0x00000020 ++ ++#define PMU_CC1_SW_TYPE_MASK 0x000000c0 ++#define PMU_CC1_SW_TYPE_EPHY 0x00000000 ++#define PMU_CC1_SW_TYPE_EPHYMII 0x00000040 ++#define PMU_CC1_SW_TYPE_EPHYRMII 0x00000080 ++#define PMU_CC1_SW_TYPE_RGMII 0x000000c0 ++ ++/* PMU chip control2 register */ ++#define PMU_CHIPCTL2 2 ++ ++/* PMU chip control3 register */ ++#define PMU_CHIPCTL3 3 ++ ++#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19 ++#define PMU_CC3_ENABLE_RF_SHIFT 22 ++#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 ++ ++ ++/* PMU corerev and chip specific PLL controls. ++ * PMU_PLL_XX where is PMU corerev and is an arbitrary number ++ * to differentiate different PLLs controlled by the same PMU rev. ++ */ ++/* pllcontrol registers */ ++/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */ ++#define PMU0_PLL0_PLLCTL0 0 ++#define PMU0_PLL0_PC0_PDIV_MASK 1 ++#define PMU0_PLL0_PC0_PDIV_FREQ 25000 ++#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 ++#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 ++#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 ++ ++/* PC0_DIV_ARM for PLLOUT_ARM */ ++#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 ++#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 ++#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 ++#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */ ++#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 ++#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 ++#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 ++#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 ++ ++/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */ ++#define PMU0_PLL0_PLLCTL1 1 ++#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 ++#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 ++#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 ++#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 ++#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 ++ ++/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */ ++#define PMU0_PLL0_PLLCTL2 2 ++#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf ++#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 ++ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU1_PLL0_PLLCTL0 0 ++#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 ++#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 ++#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 ++#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU1_PLL0_PLLCTL1 1 ++#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 ++#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 ++#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 ++#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 ++#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 ++#define PMU1_PLL0_PC1_M4DIV_BY_9 9 ++#define PMU1_PLL0_PC1_M4DIV_BY_18 0x12 ++#define PMU1_PLL0_PC1_M4DIV_BY_36 0x24 ++ ++#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 ++#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU1_PLL0_PLLCTL2 2 ++#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 ++#define PMU1_PLL0_PC2_M5DIV_BY_12 0xc ++#define PMU1_PLL0_PC2_M5DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M5DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 ++#define PMU1_PLL0_PC2_M6DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M6DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1 ++#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */ ++#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU1_PLL0_PLLCTL3 3 ++#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU1_PLL0_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU1_PLL0_PLLCTL5 5 ++#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 ++#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 ++ ++/* PMU rev 2 control words */ ++#define PMU2_PHY_PLL_PLLCTL 4 ++#define PMU2_SI_PLL_PLLCTL 10 ++ ++/* PMU rev 2 */ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU2_PLL_PLLCTL0 0 ++#define PMU2_PLL_PC0_P1DIV_MASK 0x00f00000 ++#define PMU2_PLL_PC0_P1DIV_SHIFT 20 ++#define PMU2_PLL_PC0_P2DIV_MASK 0x0f000000 ++#define PMU2_PLL_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU2_PLL_PLLCTL1 1 ++#define PMU2_PLL_PC1_M1DIV_MASK 0x000000ff ++#define PMU2_PLL_PC1_M1DIV_SHIFT 0 ++#define PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC1_M2DIV_SHIFT 8 ++#define PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU2_PLL_PC1_M3DIV_SHIFT 16 ++#define PMU2_PLL_PC1_M4DIV_MASK 0xff000000 ++#define PMU2_PLL_PC1_M4DIV_SHIFT 24 ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU2_PLL_PLLCTL2 2 ++#define PMU2_PLL_PC2_M5DIV_MASK 0x000000ff ++#define PMU2_PLL_PC2_M5DIV_SHIFT 0 ++#define PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC2_M6DIV_SHIFT 8 ++#define PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU2_PLL_PC2_NDIV_MODE_SHIFT 17 ++#define PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU2_PLL_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU2_PLL_PLLCTL3 3 ++#define PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU2_PLL_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU2_PLL_PLLCTL5 5 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28 ++ ++/* PMU rev 5 (& 6) */ ++#define PMU5_PLL_P1P2_OFF 0 ++#define PMU5_PLL_P1_MASK 0x0f000000 ++#define PMU5_PLL_P1_SHIFT 24 ++#define PMU5_PLL_P2_MASK 0x00f00000 ++#define PMU5_PLL_P2_SHIFT 20 ++#define PMU5_PLL_M14_OFF 1 ++#define PMU5_PLL_MDIV_MASK 0x000000ff ++#define PMU5_PLL_MDIV_WIDTH 8 ++#define PMU5_PLL_NM5_OFF 2 ++#define PMU5_PLL_NDIV_MASK 0xfff00000 ++#define PMU5_PLL_NDIV_SHIFT 20 ++#define PMU5_PLL_NDIV_MODE_MASK 0x000e0000 ++#define PMU5_PLL_NDIV_MODE_SHIFT 17 ++#define PMU5_PLL_FMAB_OFF 3 ++#define PMU5_PLL_MRAT_MASK 0xf0000000 ++#define PMU5_PLL_MRAT_SHIFT 28 ++#define PMU5_PLL_ABRAT_MASK 0x08000000 ++#define PMU5_PLL_ABRAT_SHIFT 27 ++#define PMU5_PLL_FDIV_MASK 0x07ffffff ++#define PMU5_PLL_PLLCTL_OFF 4 ++#define PMU5_PLL_PCHI_OFF 5 ++#define PMU5_PLL_PCHI_MASK 0x0000003f ++ ++/* pmu XtalFreqRatio */ ++#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF ++#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 ++#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 ++ ++/* Divider allocation in 4716/47162/5356/5357 */ ++#define PMU5_MAINPLL_CPU 1 ++#define PMU5_MAINPLL_MEM 2 ++#define PMU5_MAINPLL_SI 3 ++ ++/* 4706 PMU */ ++#define PMU4706_MAINPLL_PLL0 0 ++#define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ ++#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 ++#define PMU6_4706_PROC_P2DIV_SHIFT 16 ++#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 ++#define PMU6_4706_PROC_P1DIV_SHIFT 12 ++#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 ++#define PMU6_4706_PROC_NDIV_INT_SHIFT 3 ++#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 ++#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0 ++ ++#define PMU7_PLL_PLLCTL7 7 ++#define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000 ++#define PMU7_PLL_CTL7_M4DIV_SHIFT 24 ++#define PMU7_PLL_CTL7_M4DIV_BY_6 6 ++#define PMU7_PLL_CTL7_M4DIV_BY_12 0xc ++#define PMU7_PLL_CTL7_M4DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL8 8 ++#define PMU7_PLL_CTL8_M5DIV_MASK 0x000000ff ++#define PMU7_PLL_CTL8_M5DIV_SHIFT 0 ++#define PMU7_PLL_CTL8_M5DIV_BY_8 8 ++#define PMU7_PLL_CTL8_M5DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M5DIV_BY_24 0x18 ++#define PMU7_PLL_CTL8_M6DIV_MASK 0x0000ff00 ++#define PMU7_PLL_CTL8_M6DIV_SHIFT 8 ++#define PMU7_PLL_CTL8_M6DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M6DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL11 11 ++#define PMU7_PLL_PLLCTL11_MASK 0xffffff00 ++#define PMU7_PLL_PLLCTL11_VAL 0x22222200 ++ ++/* PMU rev 15 */ ++#define PMU15_PLL_PLLCTL0 0 ++#define PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 ++#define PMU15_PLL_PC0_CLKSEL_SHIFT 0 ++#define PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC ++#define PMU15_PLL_PC0_FREQTGT_SHIFT 2 ++#define PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 ++#define PMU15_PLL_PC0_PRESCALE_SHIFT 22 ++#define PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 ++#define PMU15_PLL_PC0_KPCTRL_SHIFT 24 ++#define PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 ++#define PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 ++#define PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 ++#define PMU15_PLL_PC0_FDCMODE_SHIFT 30 ++#define PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 ++#define PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 ++ ++#define PMU15_PLL_PLLCTL1 1 ++#define PMU15_PLL_PC1_BIAS_CTLM_MASK 0x00000060 ++#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT 5 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK 0x00000040 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT 6 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK 0x0001FF80 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT 7 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK 0x03FE0000 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT 17 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK 0x0C000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT 26 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK 0x10000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT 28 ++#define PMU15_PLL_PC1_OPENLP_EN_MASK 0x40000000 ++#define PMU15_PLL_PC1_OPENLP_EN_SHIFT 30 ++ ++#define PMU15_PLL_PLLCTL2 2 ++#define PMU15_PLL_PC2_CTEN_MASK 0x00000001 ++#define PMU15_PLL_PC2_CTEN_SHIFT 0 ++ ++#define PMU15_PLL_PLLCTL3 3 ++#define PMU15_PLL_PC3_DITHER_EN_MASK 0x00000001 ++#define PMU15_PLL_PC3_DITHER_EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_MASK 0xFE000000 ++#define PMU15_PLL_PC3_DCOCTLSP_SHIFT 25 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK 0x01 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK 0x02 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK 0x04 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK 0x18 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT 3 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK 0x60 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT 5 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5 3 ++ ++#define PMU15_PLL_PLLCTL4 4 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK 0x00000007 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT 0 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK 0x00000038 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT 3 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK 0x000001C0 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT 6 ++#define PMU15_PLL_PC4_DBGMODE_MASK 0x00000E00 ++#define PMU15_PLL_PC4_DBGMODE_SHIFT 9 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK 0x00001000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT 12 ++#define PMU15_PLL_PC4_FLL480_CTLSP_MASK 0x000FE000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT 13 ++#define PMU15_PLL_PC4_DINPOL_MASK 0x00100000 ++#define PMU15_PLL_PC4_DINPOL_SHIFT 20 ++#define PMU15_PLL_PC4_CLKOUT_PD_MASK 0x00200000 ++#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT 21 ++#define PMU15_PLL_PC4_CLKDIV2_PD_MASK 0x00400000 ++#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT 22 ++#define PMU15_PLL_PC4_CLKDIV4_PD_MASK 0x00800000 ++#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT 23 ++#define PMU15_PLL_PC4_CLKDIV8_PD_MASK 0x01000000 ++#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT 24 ++#define PMU15_PLL_PC4_CLKDIV16_PD_MASK 0x02000000 ++#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT 25 ++#define PMU15_PLL_PC4_TEST_EN_MASK 0x04000000 ++#define PMU15_PLL_PC4_TEST_EN_SHIFT 26 ++ ++#define PMU15_PLL_PLLCTL5 5 ++#define PMU15_PLL_PC5_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC5_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC5_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC5_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC5_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC5_PRESCALE_SHIFT 27 ++ ++#define PMU15_PLL_PLLCTL6 6 ++#define PMU15_PLL_PC6_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC6_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC6_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC6_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC6_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC6_PRESCALE_SHIFT 27 ++ ++#define PMU15_FREQTGT_480_DEFAULT 0x19AB1 ++#define PMU15_FREQTGT_492_DEFAULT 0x1A4F5 ++#define PMU15_ARM_96MHZ 96000000 /* 96 Mhz */ ++#define PMU15_ARM_98MHZ 98400000 /* 98.4 Mhz */ ++#define PMU15_ARM_97MHZ 97000000 /* 97 Mhz */ ++ ++ ++#define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070 ++#define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4 ++ ++#define PMU17_PLLCTL2_NDIV_MODE_INT 0 ++#define PMU17_PLLCTL2_NDIV_MODE_INT1B8 1 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111 2 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8 3 ++ ++#define PMU17_PLLCTL0_BBPLL_PWRDWN 0 ++#define PMU17_PLLCTL0_BBPLL_DRST 3 ++#define PMU17_PLLCTL0_BBPLL_DISBL_CLK 8 ++ ++/* PLL usage in 4716/47162 */ ++#define PMU4716_MAINPLL_PLL0 12 ++ ++/* PLL usage in 5356/5357 */ ++#define PMU5356_MAINPLL_PLL0 0 ++#define PMU5357_MAINPLL_PLL0 0 ++ ++/* 4716/47162 resources */ ++#define RES4716_PROC_PLL_ON 0x00000040 ++#define RES4716_PROC_HT_AVAIL 0x00000080 ++ ++/* 4716/4717/4718 Chip specific ChipControl register bits */ ++#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++/* 2nd - 32-bit reg */ ++#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */ ++#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */ ++ ++/* 5354 resources */ ++#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES5354_ILP_REQUEST 4 /* 0x00010 */ ++#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES5354_ROM_SWITCH 7 /* 0x00080 */ ++#define RES5354_PA_REF_LDO 8 /* 0x00100 */ ++#define RES5354_RADIO_LDO 9 /* 0x00200 */ ++#define RES5354_AFE_LDO 10 /* 0x00400 */ ++#define RES5354_PLL_LDO 11 /* 0x00800 */ ++#define RES5354_BG_FILTBYP 12 /* 0x01000 */ ++#define RES5354_TX_FILTBYP 13 /* 0x02000 */ ++#define RES5354_RX_FILTBYP 14 /* 0x04000 */ ++#define RES5354_XTAL_PU 15 /* 0x08000 */ ++#define RES5354_XTAL_EN 16 /* 0x10000 */ ++#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES5354_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ ++#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ ++#define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */ ++ ++/* 4328 resources */ ++#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES4328_ILP_REQUEST 4 /* 0x00010 */ ++#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES4328_ROM_SWITCH 7 /* 0x00080 */ ++#define RES4328_PA_REF_LDO 8 /* 0x00100 */ ++#define RES4328_RADIO_LDO 9 /* 0x00200 */ ++#define RES4328_AFE_LDO 10 /* 0x00400 */ ++#define RES4328_PLL_LDO 11 /* 0x00800 */ ++#define RES4328_BG_FILTBYP 12 /* 0x01000 */ ++#define RES4328_TX_FILTBYP 13 /* 0x02000 */ ++#define RES4328_RX_FILTBYP 14 /* 0x04000 */ ++#define RES4328_XTAL_PU 15 /* 0x08000 */ ++#define RES4328_XTAL_EN 16 /* 0x10000 */ ++#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES4328_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 4325 A0/A1 resources */ ++#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */ ++#define RES4325_CBUCK_BURST 1 /* 0x00000002 */ ++#define RES4325_CBUCK_PWM 2 /* 0x00000004 */ ++#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */ ++#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */ ++#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */ ++#define RES4325_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4325_ABUCK_BURST 7 /* 0x00000080 */ ++#define RES4325_ABUCK_PWM 8 /* 0x00000100 */ ++#define RES4325_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4325_OTP_PU 10 /* 0x00000400 */ ++#define RES4325_LNLDO3_PU 11 /* 0x00000800 */ ++#define RES4325_LNLDO4_PU 12 /* 0x00001000 */ ++#define RES4325_XTAL_PU 13 /* 0x00002000 */ ++#define RES4325_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4325_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4325 B0/C0 resources */ ++#define RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4325B0_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4325B0_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4325B0_CLDO_PU 4 /* 0x00000010 */ ++ ++/* 4325 C1 resources */ ++#define RES4325C1_LNLDO2_PU 12 /* 0x00001000 */ ++ ++/* 4325 chip-specific ChipStatus register bits */ ++#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4325_SDIO_USB_MODE_MASK 0x00000004 ++#define CST4325_SDIO_USB_MODE_SHIFT 2 ++#define CST4325_RCAL_VALID_MASK 0x00000008 ++#define CST4325_RCAL_VALID_SHIFT 3 ++#define CST4325_RCAL_VALUE_MASK 0x000001f0 ++#define CST4325_RCAL_VALUE_SHIFT 4 ++#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */ ++#define CST4325_PMUTOP_2B_SHIFT 9 ++ ++#define RES4329_RESERVED0 0 /* 0x00000001 */ ++#define RES4329_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4329_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4329_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4329_CLDO_PU 4 /* 0x00000010 */ ++#define RES4329_PALDO_PU 5 /* 0x00000020 */ ++#define RES4329_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4329_RESERVED7 7 /* 0x00000080 */ ++#define RES4329_RESERVED8 8 /* 0x00000100 */ ++#define RES4329_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4329_OTP_PU 10 /* 0x00000400 */ ++#define RES4329_RESERVED11 11 /* 0x00000800 */ ++#define RES4329_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4329_XTAL_PU 13 /* 0x00002000 */ ++#define RES4329_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4329_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4329_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4329_HT_AVAIL 21 /* 0x00200000 */ ++ ++#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 ++#define CST4329_SPI_SDIO_MODE_SHIFT 2 ++ ++/* 4312 chip-specific ChipStatus register bits */ ++#define CST4312_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4312_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4312_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4312_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4312_OTP_BAD 3 /* OTP is broken, SPROM is present */ ++ ++/* 4312 resources (all PMU chips with little memory constraint) */ ++#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */ ++#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */ ++#define RES4312_PA_REF_LDO 2 /* 0x00000004 */ ++#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */ ++#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */ ++#define RES4312_RADIO_LDO 5 /* 0x00000020 */ ++#define RES4312_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4312_BG_FILTBYP 7 /* 0x00000080 */ ++#define RES4312_TX_FILTBYP 8 /* 0x00000100 */ ++#define RES4312_RX_FILTBYP 9 /* 0x00000200 */ ++#define RES4312_XTAL_PU 10 /* 0x00000400 */ ++#define RES4312_ALP_AVAIL 11 /* 0x00000800 */ ++#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */ ++#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */ ++#define RES4312_HT_AVAIL 14 /* 0x00004000 */ ++ ++/* 4322 resources */ ++#define RES4322_RF_LDO 0 ++#define RES4322_ILP_REQUEST 1 ++#define RES4322_XTAL_PU 2 ++#define RES4322_ALP_AVAIL 3 ++#define RES4322_SI_PLL_ON 4 ++#define RES4322_HT_SI_AVAIL 5 ++#define RES4322_PHY_PLL_ON 6 ++#define RES4322_HT_PHY_AVAIL 7 ++#define RES4322_OTP_PU 8 ++ ++/* 4322 chip-specific ChipStatus register bits */ ++#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 ++#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 ++#define CST4322_SPROM_OTP_SEL_SHIFT 6 ++#define CST4322_NO_SPROM_OTP 0 /* no OTP, no SPROM */ ++#define CST4322_SPROM_PRESENT 1 /* SPROM is present */ ++#define CST4322_OTP_PRESENT 2 /* OTP is present */ ++#define CST4322_PCI_OR_USB 0x00000100 ++#define CST4322_BOOT_MASK 0x00000600 ++#define CST4322_BOOT_SHIFT 9 ++#define CST4322_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST4322_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST4322_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST4322_BOOT_FROM_INVALID 3 ++#define CST4322_ILP_DIV_EN 0x00000800 ++#define CST4322_FLASH_TYPE_MASK 0x00001000 ++#define CST4322_FLASH_TYPE_SHIFT 12 ++#define CST4322_FLASH_TYPE_SHIFT_ST 0 /* ST serial FLASH */ ++#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /* ATMEL flash */ ++#define CST4322_ARM_TAP_SEL 0x00002000 ++#define CST4322_RES_INIT_MODE_MASK 0x0000c000 ++#define CST4322_RES_INIT_MODE_SHIFT 14 ++#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /* resinitmode: ILP available */ ++#define CST4322_RES_INIT_MODE_ILPREQ 1 /* resinitmode: ILP request */ ++#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /* resinitmode: ALP available */ ++#define CST4322_RES_INIT_MODE_HTAVAIL 3 /* resinitmode: HT available */ ++#define CST4322_PCIPLLCLK_GATING 0x00010000 ++#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 ++#define CST4322_PCI_CARDBUS_MODE 0x00040000 ++ ++/* 43224 chip-specific ChipControl register bits */ ++#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ ++#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ ++#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ ++ ++/* 43236 resources */ ++#define RES43236_REGULATOR 0 ++#define RES43236_ILP_REQUEST 1 ++#define RES43236_XTAL_PU 2 ++#define RES43236_ALP_AVAIL 3 ++#define RES43236_SI_PLL_ON 4 ++#define RES43236_HT_SI_AVAIL 5 ++ ++/* 43236 chip-specific ChipControl register bits */ ++#define CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43236_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43236_GSIO (1<<4) /* 0 disable */ ++ ++/* 43236 Chip specific ChipStatus register bits */ ++#define CST43236_SFLASH_MASK 0x00000040 ++#define CST43236_OTP_SEL_MASK 0x00000080 ++#define CST43236_OTP_SEL_SHIFT 7 ++#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43236_BOOT_MASK 0x00001800 ++#define CST43236_BOOT_SHIFT 11 ++#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43236_BOOT_FROM_INVALID 3 ++ ++/* 43237 resources */ ++#define RES43237_REGULATOR 0 ++#define RES43237_ILP_REQUEST 1 ++#define RES43237_XTAL_PU 2 ++#define RES43237_ALP_AVAIL 3 ++#define RES43237_SI_PLL_ON 4 ++#define RES43237_HT_SI_AVAIL 5 ++ ++/* 43237 chip-specific ChipControl register bits */ ++#define CCTRL43237_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43237_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43237_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43237_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43237_GSIO (1<<4) /* 0 disable */ ++ ++/* 43237 Chip specific ChipStatus register bits */ ++#define CST43237_SFLASH_MASK 0x00000040 ++#define CST43237_OTP_SEL_MASK 0x00000080 ++#define CST43237_OTP_SEL_SHIFT 7 ++#define CST43237_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43237_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43237_BOOT_MASK 0x00001800 ++#define CST43237_BOOT_SHIFT 11 ++#define CST43237_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43237_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43237_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43237_BOOT_FROM_INVALID 3 ++ ++/* 43239 resources */ ++#define RES43239_OTP_PU 9 ++#define RES43239_MACPHY_CLKAVAIL 23 ++#define RES43239_HT_AVAIL 24 ++ ++/* 43239 Chip specific ChipStatus register bits */ ++#define CST43239_SPROM_MASK 0x00000002 ++#define CST43239_SFLASH_MASK 0x00000004 ++#define CST43239_RES_INIT_MODE_SHIFT 7 ++#define CST43239_RES_INIT_MODE_MASK 0x000001f0 ++#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /* SDIO || gSPI */ ++#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /* USB || USBDA */ ++#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /* SDIO */ ++#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */ ++ ++/* 4324 resources */ ++#define RES4324_OTP_PU 10 ++#define RES4324_HT_AVAIL 29 ++#define RES4324_MACPHY_CLKAVAIL 30 ++ ++/* 4324 Chip specific ChipStatus register bits */ ++#define CST4324_SPROM_MASK 0x00000080 ++#define CST4324_SFLASH_MASK 0x00400000 ++#define CST4324_RES_INIT_MODE_SHIFT 10 ++#define CST4324_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4324_CHIPMODE_MASK 0x7 ++#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */ ++#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */ ++ ++/* 4331 resources */ ++#define RES4331_REGULATOR 0 ++#define RES4331_ILP_REQUEST 1 ++#define RES4331_XTAL_PU 2 ++#define RES4331_ALP_AVAIL 3 ++#define RES4331_SI_PLL_ON 4 ++#define RES4331_HT_SI_AVAIL 5 ++ ++/* 4331 chip-specific ChipControl register bits */ ++#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL4331_EXT_LNA_G (1<<2) /* 0 disable */ ++#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */ ++#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */ ++#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */ ++#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ ++#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */ ++#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ ++#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ ++#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ ++#define CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_EXT_LNA_A (1<<13) /* 0 disable */ ++#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ ++#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ ++#define CCTRL4331_EXTPA_ANA_EN (1<<24) /* 0 ext pa disable, 1 ext pa enabled */ ++ ++/* 4331 Chip specific ChipStatus register bits */ ++#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */ ++#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 ++#define CST4331_SPROM_OTP_SEL_SHIFT 1 ++#define CST4331_SPROM_PRESENT 0x00000002 ++#define CST4331_OTP_PRESENT 0x00000004 ++#define CST4331_LDO_RF 0x00000008 ++#define CST4331_LDO_PAR 0x00000010 ++ ++/* 4315 resource */ ++#define RES4315_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4315_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4315_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4315_CLDO_PU 4 /* 0x00000010 */ ++#define RES4315_PALDO_PU 5 /* 0x00000020 */ ++#define RES4315_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4315_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4315_OTP_PU 10 /* 0x00000400 */ ++#define RES4315_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4315_XTAL_PU 13 /* 0x00002000 */ ++#define RES4315_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4315_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4315_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4315_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4315 chip-specific ChipStatus register bits */ ++#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /* gpio [7:6], SDIO CIS selection */ ++#define CST4315_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4315_SPROM_SEL 0x00000001 /* use SPROM, OTP is powered up */ ++#define CST4315_OTP_SEL 0x00000002 /* use OTP, OTP is powered up */ ++#define CST4315_OTP_PWRDN 0x00000003 /* use SPROM, OTP is powered down */ ++#define CST4315_SDIO_MODE 0x00000004 /* gpio [8], sdio/usb mode */ ++#define CST4315_RCAL_VALID 0x00000008 ++#define CST4315_RCAL_VALUE_MASK 0x000001f0 ++#define CST4315_RCAL_VALUE_SHIFT 4 ++#define CST4315_PALDO_EXTPNP 0x00000200 /* PALDO is configured with external PNP */ ++#define CST4315_CBUCK_MODE_MASK 0x00000c00 ++#define CST4315_CBUCK_MODE_BURST 0x00000400 ++#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 ++ ++/* 4319 resources */ ++#define RES4319_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4319_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4319_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4319_CLDO_PU 4 /* 0x00000010 */ ++#define RES4319_PALDO_PU 5 /* 0x00000020 */ ++#define RES4319_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4319_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4319_OTP_PU 10 /* 0x00000400 */ ++#define RES4319_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4319_XTAL_PU 13 /* 0x00002000 */ ++#define RES4319_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4319_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4319_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4319_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4319 chip-specific ChipStatus register bits */ ++#define CST4319_SPI_CPULESSUSB 0x00000001 ++#define CST4319_SPI_CLK_POL 0x00000002 ++#define CST4319_SPI_CLK_PH 0x00000008 ++#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */ ++#define CST4319_SPROM_OTP_SEL_SHIFT 6 ++#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */ ++#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ ++#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ ++#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */ ++#define CST4319_REMAP_SEL_MASK 0x00000600 ++#define CST4319_ILPDIV_EN 0x00000800 ++#define CST4319_XTAL_PD_POL 0x00001000 ++#define CST4319_LPO_SEL 0x00002000 ++#define CST4319_RES_INIT_MODE 0x0000c000 ++#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */ ++#define CST4319_CBUCK_MODE_MASK 0x00060000 ++#define CST4319_CBUCK_MODE_BURST 0x00020000 ++#define CST4319_CBUCK_MODE_LPBURST 0x00060000 ++#define CST4319_RCAL_VALID 0x01000000 ++#define CST4319_RCAL_VALUE_MASK 0x3e000000 ++#define CST4319_RCAL_VALUE_SHIFT 25 ++ ++#define PMU1_PLL0_CHIPCTL0 0 ++#define PMU1_PLL0_CHIPCTL1 1 ++#define PMU1_PLL0_CHIPCTL2 2 ++#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 ++#define CCTL_4319USB_XTAL_SEL_SHIFT 19 ++#define CCTL_4319USB_48MHZ_PLL_SEL 1 ++#define CCTL_4319USB_24MHZ_PLL_SEL 2 ++ ++/* PMU resources for 4336 */ ++#define RES4336_CBUCK_LPOM 0 ++#define RES4336_CBUCK_BURST 1 ++#define RES4336_CBUCK_LP_PWM 2 ++#define RES4336_CBUCK_PWM 3 ++#define RES4336_CLDO_PU 4 ++#define RES4336_DIS_INT_RESET_PD 5 ++#define RES4336_ILP_REQUEST 6 ++#define RES4336_LNLDO_PU 7 ++#define RES4336_LDO3P3_PU 8 ++#define RES4336_OTP_PU 9 ++#define RES4336_XTAL_PU 10 ++#define RES4336_ALP_AVAIL 11 ++#define RES4336_RADIO_PU 12 ++#define RES4336_BG_PU 13 ++#define RES4336_VREG1p4_PU_PU 14 ++#define RES4336_AFE_PWRSW_PU 15 ++#define RES4336_RX_PWRSW_PU 16 ++#define RES4336_TX_PWRSW_PU 17 ++#define RES4336_BB_PWRSW_PU 18 ++#define RES4336_SYNTH_PWRSW_PU 19 ++#define RES4336_MISC_PWRSW_PU 20 ++#define RES4336_LOGEN_PWRSW_PU 21 ++#define RES4336_BBPLL_PWRSW_PU 22 ++#define RES4336_MACPHY_CLKAVAIL 23 ++#define RES4336_HT_AVAIL 24 ++#define RES4336_RSVD 25 ++ ++/* 4336 chip-specific ChipStatus register bits */ ++#define CST4336_SPI_MODE_MASK 0x00000001 ++#define CST4336_SPROM_PRESENT 0x00000002 ++#define CST4336_OTP_PRESENT 0x00000004 ++#define CST4336_ARMREMAP_0 0x00000008 ++#define CST4336_ILPDIV_EN_MASK 0x00000010 ++#define CST4336_ILPDIV_EN_SHIFT 4 ++#define CST4336_XTAL_PD_POL_MASK 0x00000020 ++#define CST4336_XTAL_PD_POL_SHIFT 5 ++#define CST4336_LPO_SEL_MASK 0x00000040 ++#define CST4336_LPO_SEL_SHIFT 6 ++#define CST4336_RES_INIT_MODE_MASK 0x00000180 ++#define CST4336_RES_INIT_MODE_SHIFT 7 ++#define CST4336_CBUCK_MODE_MASK 0x00000600 ++#define CST4336_CBUCK_MODE_SHIFT 9 ++ ++/* 4336 Chip specific PMU ChipControl register bits */ ++#define PCTL_4336_SERIAL_ENAB (1 << 24) ++ ++/* 4330 resources */ ++#define RES4330_CBUCK_LPOM 0 ++#define RES4330_CBUCK_BURST 1 ++#define RES4330_CBUCK_LP_PWM 2 ++#define RES4330_CBUCK_PWM 3 ++#define RES4330_CLDO_PU 4 ++#define RES4330_DIS_INT_RESET_PD 5 ++#define RES4330_ILP_REQUEST 6 ++#define RES4330_LNLDO_PU 7 ++#define RES4330_LDO3P3_PU 8 ++#define RES4330_OTP_PU 9 ++#define RES4330_XTAL_PU 10 ++#define RES4330_ALP_AVAIL 11 ++#define RES4330_RADIO_PU 12 ++#define RES4330_BG_PU 13 ++#define RES4330_VREG1p4_PU_PU 14 ++#define RES4330_AFE_PWRSW_PU 15 ++#define RES4330_RX_PWRSW_PU 16 ++#define RES4330_TX_PWRSW_PU 17 ++#define RES4330_BB_PWRSW_PU 18 ++#define RES4330_SYNTH_PWRSW_PU 19 ++#define RES4330_MISC_PWRSW_PU 20 ++#define RES4330_LOGEN_PWRSW_PU 21 ++#define RES4330_BBPLL_PWRSW_PU 22 ++#define RES4330_MACPHY_CLKAVAIL 23 ++#define RES4330_HT_AVAIL 24 ++#define RES4330_5gRX_PWRSW_PU 25 ++#define RES4330_5gTX_PWRSW_PU 26 ++#define RES4330_5g_LOGEN_PWRSW_PU 27 ++ ++/* 4330 chip-specific ChipStatus register bits */ ++#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */ ++#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */ ++#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */ ++#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */ ++#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */ ++#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */ ++#define CST4330_OTP_PRESENT 0x00000010 ++#define CST4330_LPO_AUTODET_EN 0x00000020 ++#define CST4330_ARMREMAP_0 0x00000040 ++#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */ ++#define CST4330_ILPDIV_EN 0x00000100 ++#define CST4330_LPO_SEL 0x00000200 ++#define CST4330_RES_INIT_MODE_SHIFT 10 ++#define CST4330_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4330_CBUCK_MODE_SHIFT 12 ++#define CST4330_CBUCK_MODE_MASK 0x00003000 ++#define CST4330_CBUCK_POWER_OK 0x00004000 ++#define CST4330_BB_PLL_LOCKED 0x00008000 ++#define SOCDEVRAM_BP_ADDR 0x1E000000 ++#define SOCDEVRAM_ARM_ADDR 0x00800000 ++ ++/* 4330 Chip specific PMU ChipControl register bits */ ++#define PCTL_4330_SERIAL_ENAB (1 << 24) ++ ++/* 4330 Chip specific ChipControl register bits */ ++#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */ ++#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */ ++#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */ ++#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */ ++ ++/* 4334 resources */ ++#define RES4334_LPLDO_PU 0 ++#define RES4334_RESET_PULLDN_DIS 1 ++#define RES4334_PMU_BG_PU 2 ++#define RES4334_HSIC_LDO_PU 3 ++#define RES4334_CBUCK_LPOM_PU 4 ++#define RES4334_CBUCK_PFM_PU 5 ++#define RES4334_CLDO_PU 6 ++#define RES4334_LPLDO2_LVM 7 ++#define RES4334_LNLDO_PU 8 ++#define RES4334_LDO3P3_PU 9 ++#define RES4334_OTP_PU 10 ++#define RES4334_XTAL_PU 11 ++#define RES4334_WL_PWRSW_PU 12 ++#define RES4334_LQ_AVAIL 13 ++#define RES4334_LOGIC_RET 14 ++#define RES4334_MEM_SLEEP 15 ++#define RES4334_MACPHY_RET 16 ++#define RES4334_WL_CORE_READY 17 ++#define RES4334_ILP_REQ 18 ++#define RES4334_ALP_AVAIL 19 ++#define RES4334_MISC_PWRSW_PU 20 ++#define RES4334_SYNTH_PWRSW_PU 21 ++#define RES4334_RX_PWRSW_PU 22 ++#define RES4334_RADIO_PU 23 ++#define RES4334_WL_PMU_PU 24 ++#define RES4334_VCO_LDO_PU 25 ++#define RES4334_AFE_LDO_PU 26 ++#define RES4334_RX_LDO_PU 27 ++#define RES4334_TX_LDO_PU 28 ++#define RES4334_HT_AVAIL 29 ++#define RES4334_MACPHY_CLK_AVAIL 30 ++ ++/* 4334 chip-specific ChipStatus register bits */ ++#define CST4334_CHIPMODE_MASK 7 ++#define CST4334_SDIO_MODE 0x00000000 ++#define CST4334_SPI_MODE 0x00000004 ++#define CST4334_HSIC_MODE 0x00000006 ++#define CST4334_BLUSB_MODE 0x00000007 ++#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE) ++#define CST4334_OTP_PRESENT 0x00000010 ++#define CST4334_LPO_AUTODET_EN 0x00000020 ++#define CST4334_ARMREMAP_0 0x00000040 ++#define CST4334_SPROM_PRESENT 0x00000080 ++#define CST4334_ILPDIV_EN_MASK 0x00000100 ++#define CST4334_ILPDIV_EN_SHIFT 8 ++#define CST4334_LPO_SEL_MASK 0x00000200 ++#define CST4334_LPO_SEL_SHIFT 9 ++#define CST4334_RES_INIT_MODE_MASK 0x00000C00 ++#define CST4334_RES_INIT_MODE_SHIFT 10 ++ ++/* 4334 Chip specific PMU ChipControl register bits */ ++#define PCTL_4334_GPIO3_ENAB (1 << 3) ++ ++/* 4334 Chip control */ ++#define CCTRL4334_HSIC_LDO_PU (1 << 23) ++ ++/* 4324 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++/* 4313 resources */ ++#define RES4313_BB_PU_RSRC 0 ++#define RES4313_ILP_REQ_RSRC 1 ++#define RES4313_XTAL_PU_RSRC 2 ++#define RES4313_ALP_AVAIL_RSRC 3 ++#define RES4313_RADIO_PU_RSRC 4 ++#define RES4313_BG_PU_RSRC 5 ++#define RES4313_VREG1P4_PU_RSRC 6 ++#define RES4313_AFE_PWRSW_RSRC 7 ++#define RES4313_RX_PWRSW_RSRC 8 ++#define RES4313_TX_PWRSW_RSRC 9 ++#define RES4313_BB_PWRSW_RSRC 10 ++#define RES4313_SYNTH_PWRSW_RSRC 11 ++#define RES4313_MISC_PWRSW_RSRC 12 ++#define RES4313_BB_PLL_PWRSW_RSRC 13 ++#define RES4313_HT_AVAIL_RSRC 14 ++#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 ++ ++/* 4313 chip-specific ChipStatus register bits */ ++#define CST4313_SPROM_PRESENT 1 ++#define CST4313_OTP_PRESENT 2 ++#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 ++#define CST4313_SPROM_OTP_SEL_SHIFT 0 ++ ++/* 4313 Chip specific ChipControl register bits */ ++#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ ++ ++/* PMU respources for 4314 */ ++#define RES4314_LPLDO_PU 0 ++#define RES4314_PMU_SLEEP_DIS 1 ++#define RES4314_PMU_BG_PU 2 ++#define RES4314_CBUCK_LPOM_PU 3 ++#define RES4314_CBUCK_PFM_PU 4 ++#define RES4314_CLDO_PU 5 ++#define RES4314_LPLDO2_LVM 6 ++#define RES4314_WL_PMU_PU 7 ++#define RES4314_LNLDO_PU 8 ++#define RES4314_LDO3P3_PU 9 ++#define RES4314_OTP_PU 10 ++#define RES4314_XTAL_PU 11 ++#define RES4314_WL_PWRSW_PU 12 ++#define RES4314_LQ_AVAIL 13 ++#define RES4314_LOGIC_RET 14 ++#define RES4314_MEM_SLEEP 15 ++#define RES4314_MACPHY_RET 16 ++#define RES4314_WL_CORE_READY 17 ++#define RES4314_ILP_REQ 18 ++#define RES4314_ALP_AVAIL 19 ++#define RES4314_MISC_PWRSW_PU 20 ++#define RES4314_SYNTH_PWRSW_PU 21 ++#define RES4314_RX_PWRSW_PU 22 ++#define RES4314_RADIO_PU 23 ++#define RES4314_VCO_LDO_PU 24 ++#define RES4314_AFE_LDO_PU 25 ++#define RES4314_RX_LDO_PU 26 ++#define RES4314_TX_LDO_PU 27 ++#define RES4314_HT_AVAIL 28 ++#define RES4314_MACPHY_CLK_AVAIL 29 ++ ++/* 4314 chip-specific ChipStatus register bits */ ++#define CST4314_OTP_ENABLED 0x00200000 ++ ++/* 43228 resources */ ++#define RES43228_NOT_USED 0 ++#define RES43228_ILP_REQUEST 1 ++#define RES43228_XTAL_PU 2 ++#define RES43228_ALP_AVAIL 3 ++#define RES43228_PLL_EN 4 ++#define RES43228_HT_PHY_AVAIL 5 ++ ++/* 43228 chipstatus reg bits */ ++#define CST43228_ILP_DIV_EN 0x1 ++#define CST43228_OTP_PRESENT 0x2 ++#define CST43228_SERDES_REFCLK_PADSEL 0x4 ++#define CST43228_SDIO_MODE 0x8 ++#define CST43228_SDIO_OTP_PRESENT 0x10 ++#define CST43228_SDIO_RESET 0x20 ++ ++/* 4706 chipstatus reg bits */ ++#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */ ++#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */ ++#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ ++#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */ ++#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */ ++ ++/* 4706 flashstrconfig reg bits */ ++#define FLSTRCF4706_MASK 0x000000ff ++#define FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */ ++#define FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */ ++#define FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ ++#define FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */ ++#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */ ++#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ ++ ++/* 4360 Chip specific ChipControl register bits */ ++#define CCTRL4360_SECI_MODE (1 << 2) ++#define CCTRL4360_BTSWCTRL_MODE (1 << 3) ++#define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) ++#define CCTRL4360_BT_LGCY_MODE (1 << 9) ++#define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) ++ ++/* 4360 PMU resources and chip status bits */ ++#define RES4360_REGULATOR 0 ++#define RES4360_ILP_AVAIL 1 ++#define RES4360_ILP_REQ 2 ++#define RES4360_XTAL_PU 3 ++#define RES4360_ALP_AVAIL 4 ++#define RES4360_BBPLLPWRSW_PU 5 ++#define RES4360_HT_AVAIL 6 ++#define RES4360_OTP_PU 7 ++#define RES4360_USBLDO_PU 8 ++#define RES4360_USBPLL_PWRSW_PU 9 ++#define RES4360_LQ_AVAIL 10 ++ ++#define CST4360_XTAL_40MZ 0x00000001 ++#define CST4360_SFLASH 0x00000002 ++#define CST4360_SPROM_PRESENT 0x00000004 ++#define CST4360_SFLASH_TYPE 0x00000004 ++#define CST4360_OTP_ENABLED 0x00000008 ++#define CST4360_REMAP_ROM 0x00000010 ++#define CST4360_RSRC_INIT_MODE_MASK 0x00000060 ++#define CST4360_RSRC_INIT_MODE_SHIFT 5 ++#define CST4360_ILP_DIVEN 0x00000080 ++#define CST4360_MODE_USB 0x00000100 ++#define CST4360_SPROM_SIZE_MASK 0x00000600 ++#define CST4360_SPROM_SIZE_SHIFT 9 ++#define CST4360_BBPLL_LOCK 0x00000800 ++#define CST4360_AVBBPLL_LOCK 0x00001000 ++#define CST4360_USBBBPLL_LOCK 0x00002000 ++ ++#define CCTL_4360_UART_SEL 2 ++ ++/* 4335 resources */ ++#define RES4335_LPLDO_PO 0 ++#define RES4335_PMU_BG_PU 1 ++#define RES4335_PMU_SLEEP 2 ++#define RES4335_RSVD_3 3 ++#define RES4335_CBUCK_LPOM_PU 4 ++#define RES4335_CBUCK_PFM_PU 5 ++#define RES4335_RSVD_6 6 ++#define RES4335_RSVD_7 7 ++#define RES4335_LNLDO_PU 8 ++#define RES4335_XTALLDO_PU 9 ++#define RES4335_LDO3P3_PU 10 ++#define RES4335_OTP_PU 11 ++#define RES4335_XTAL_PU 12 ++#define RES4335_SR_CLK_START 13 ++#define RES4335_LQ_AVAIL 14 ++#define RES4335_LQ_START 15 ++#define RES4335_RSVD_16 16 ++#define RES4335_WL_CORE_RDY 17 ++#define RES4335_ILP_REQ 18 ++#define RES4335_ALP_AVAIL 19 ++#define RES4335_MINI_PMU 20 ++#define RES4335_RADIO_PU 21 ++#define RES4335_SR_CLK_STABLE 22 ++#define RES4335_SR_SAVE_RESTORE 23 ++#define RES4335_SR_PHY_PWRSW 24 ++#define RES4335_SR_VDDM_PWRSW 25 ++#define RES4335_SR_SUBCORE_PWRSW 26 ++#define RES4335_SR_SLEEP 27 ++#define RES4335_HT_START 28 ++#define RES4335_HT_AVAIL 29 ++#define RES4335_MACPHY_CLKAVAIL 30 ++ ++/* 4335 Chip specific ChipStatus register bits */ ++#define CST4335_SPROM_MASK 0x00000020 ++#define CST4335_SFLASH_MASK 0x00000040 ++#define CST4335_RES_INIT_MODE_SHIFT 7 ++#define CST4335_RES_INIT_MODE_MASK 0x00000180 ++#define CST4335_CHIPMODE_MASK 0xF ++#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */ ++#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */ ++#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) /* USB || USBDA */ ++#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */ ++ ++/* 4335 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++#define CR4_RAM_BASE (0x180000) ++#define PATCHTBL_SIZE (0x800) ++ ++ ++/* 4335 resources--END */ ++ ++/* GCI chipcontrol register indices */ ++#define CC_GCI_CHIPCTRL_00 (0) ++#define CC_GCI_CHIPCTRL_01 (1) ++#define CC_GCI_CHIPCTRL_02 (2) ++#define CC_GCI_CHIPCTRL_03 (3) ++#define CC_GCI_CHIPCTRL_04 (4) ++#define CC_GCI_CHIPCTRL_05 (5) ++#define CC_GCI_CHIPCTRL_06 (6) ++#define CC_GCI_CHIPCTRL_07 (7) ++#define CC_GCI_CHIPCTRL_08 (8) ++ ++#define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) ++ ++/* 4335 pins ++* note: only the values set as default/used are added here. ++*/ ++#define CC4335_PIN_GPIO_00 (0) ++#define CC4335_PIN_GPIO_01 (1) ++#define CC4335_PIN_GPIO_02 (2) ++#define CC4335_PIN_GPIO_03 (3) ++#define CC4335_PIN_GPIO_04 (4) ++#define CC4335_PIN_GPIO_05 (5) ++#define CC4335_PIN_GPIO_06 (6) ++#define CC4335_PIN_GPIO_07 (7) ++#define CC4335_PIN_GPIO_08 (8) ++#define CC4335_PIN_GPIO_09 (9) ++#define CC4335_PIN_GPIO_10 (10) ++#define CC4335_PIN_GPIO_11 (11) ++#define CC4335_PIN_GPIO_12 (12) ++#define CC4335_PIN_GPIO_13 (13) ++#define CC4335_PIN_GPIO_14 (14) ++#define CC4335_PIN_GPIO_15 (15) ++#define CC4335_PIN_SDIO_CLK (16) ++#define CC4335_PIN_SDIO_CMD (17) ++#define CC4335_PIN_SDIO_DATA0 (18) ++#define CC4335_PIN_SDIO_DATA1 (19) ++#define CC4335_PIN_SDIO_DATA2 (20) ++#define CC4335_PIN_SDIO_DATA3 (21) ++#define CC4335_PIN_RF_SW_CTRL_0 (22) ++#define CC4335_PIN_RF_SW_CTRL_1 (23) ++#define CC4335_PIN_RF_SW_CTRL_2 (24) ++#define CC4335_PIN_RF_SW_CTRL_3 (25) ++#define CC4335_PIN_RF_SW_CTRL_4 (26) ++#define CC4335_PIN_RF_SW_CTRL_5 (27) ++#define CC4335_PIN_RF_SW_CTRL_6 (28) ++#define CC4335_PIN_RF_SW_CTRL_7 (29) ++#define CC4335_PIN_RF_SW_CTRL_8 (30) ++#define CC4335_PIN_RF_SW_CTRL_9 (31) ++ ++/* 4335 GCI function sel values ++*/ ++#define CC4335_FNSEL_HWDEF (0) ++#define CC4335_FNSEL_SAMEASPIN (1) ++#define CC4335_FNSEL_GPIO0 (2) ++#define CC4335_FNSEL_GPIO1 (3) ++#define CC4335_FNSEL_GCI0 (4) ++#define CC4335_FNSEL_GCI1 (5) ++#define CC4335_FNSEL_UART (6) ++#define CC4335_FNSEL_SFLASH (7) ++#define CC4335_FNSEL_SPROM (8) ++#define CC4335_FNSEL_MISC0 (9) ++#define CC4335_FNSEL_MISC1 (10) ++#define CC4335_FNSEL_MISC2 (11) ++#define CC4335_FNSEL_IND (12) ++#define CC4335_FNSEL_PDN (13) ++#define CC4335_FNSEL_PUP (14) ++#define CC4335_FNSEL_TRI (15) ++ ++/* find the 4 bit mask given the bit position */ ++#define GCIMASK(pos) (((uint32)0xF) << pos) ++ ++/* get the value which can be used to directly OR with chipcontrol reg */ ++#define GCIPOSVAL(val, pos) ((((uint32)val) << pos) & GCIMASK(pos)) ++ ++/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic ++* for now only UART for bootloader. ++*/ ++#define MUXENAB4335_UART_MASK (0x0000000f) ++ ++ ++/* defines to detect active host interface in use */ ++#define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) & CST4360_MODE_USB) ++ ++/* ++* Maximum delay for the PMU state transition in us. ++* This is an upper bound intended for spinwaits etc. ++*/ ++#define PMU_MAX_TRANSITION_DLY 20000 ++ ++/* PMU resource up transition time in ILP cycles */ ++#define PMURES_UP_TRANSITION 2 ++ ++/* ++* Information from BT to WLAN over eci_inputlo, eci_inputmi & ++* eci_inputhi register. Rev >=21 ++*/ ++/* Fields in eci_inputlo register - [0:31] */ ++#define ECI_INLO_TASKTYPE_MASK 0x0000000f /* [3:0] - 4 bits */ ++#define ECI_INLO_TASKTYPE_SHIFT 0 ++#define ECI_INLO_PKTDUR_MASK 0x000000f0 /* [7:4] - 4 bits */ ++#define ECI_INLO_PKTDUR_SHIFT 4 ++#define ECI_INLO_ROLE_MASK 0x00000100 /* [8] - 1 bits */ ++#define ECI_INLO_ROLE_SHIFT 8 ++#define ECI_INLO_MLP_MASK 0x00000e00 /* [11:9] - 3 bits */ ++#define ECI_INLO_MLP_SHIFT 9 ++#define ECI_INLO_TXPWR_MASK 0x000ff000 /* [19:12] - 8 bits */ ++#define ECI_INLO_TXPWR_SHIFT 12 ++#define ECI_INLO_RSSI_MASK 0x0ff00000 /* [27:20] - 8 bits */ ++#define ECI_INLO_RSSI_SHIFT 20 ++#define ECI_INLO_VAD_MASK 0x10000000 /* [28] - 1 bits */ ++#define ECI_INLO_VAD_SHIFT 28 ++ ++/* ++* Register eci_inputlo bitfield values. ++* - BT packet type information bits [7:0] ++*/ ++/* [3:0] - Task (link) type */ ++#define BT_ACL 0x00 ++#define BT_SCO 0x01 ++#define BT_eSCO 0x02 ++#define BT_A2DP 0x03 ++#define BT_SNIFF 0x04 ++#define BT_PAGE_SCAN 0x05 ++#define BT_INQUIRY_SCAN 0x06 ++#define BT_PAGE 0x07 ++#define BT_INQUIRY 0x08 ++#define BT_MSS 0x09 ++#define BT_PARK 0x0a ++#define BT_RSSISCAN 0x0b ++#define BT_MD_ACL 0x0c ++#define BT_MD_eSCO 0x0d ++#define BT_SCAN_WITH_SCO_LINK 0x0e ++#define BT_SCAN_WITHOUT_SCO_LINK 0x0f ++/* [7:4] = packet duration code */ ++/* [8] - Master / Slave */ ++#define BT_MASTER 0 ++#define BT_SLAVE 1 ++/* [11:9] - multi-level priority */ ++#define BT_LOWEST_PRIO 0x0 ++#define BT_HIGHEST_PRIO 0x3 ++/* [19:12] - BT transmit power */ ++/* [27:20] - BT RSSI */ ++/* [28] - VAD silence */ ++/* [31:29] - Undefined */ ++/* Register eci_inputmi values - [32:63] - none defined */ ++/* [63:32] - Undefined */ ++ ++/* Information from WLAN to BT over eci_output register. */ ++/* Fields in eci_output register - [0:31] */ ++#define ECI48_OUT_MASKMAGIC_HIWORD 0x55550000 ++#define ECI_OUT_CHANNEL_MASK(ccrev) ((ccrev) < 35 ? 0xf : (ECI48_OUT_MASKMAGIC_HIWORD | 0xf000)) ++#define ECI_OUT_CHANNEL_SHIFT(ccrev) ((ccrev) < 35 ? 0 : 12) ++#define ECI_OUT_BW_MASK(ccrev) ((ccrev) < 35 ? 0x70 : (ECI48_OUT_MASKMAGIC_HIWORD | 0xe00)) ++#define ECI_OUT_BW_SHIFT(ccrev) ((ccrev) < 35 ? 4 : 9) ++#define ECI_OUT_ANTENNA_MASK(ccrev) ((ccrev) < 35 ? 0x80 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x100)) ++#define ECI_OUT_ANTENNA_SHIFT(ccrev) ((ccrev) < 35 ? 7 : 8) ++#define ECI_OUT_SIMUL_TXRX_MASK(ccrev) \ ++ ((ccrev) < 35 ? 0x10000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x80)) ++#define ECI_OUT_SIMUL_TXRX_SHIFT(ccrev) ((ccrev) < 35 ? 16 : 7) ++#define ECI_OUT_FM_DISABLE_MASK(ccrev) \ ++ ((ccrev) < 35 ? 0x40000 : (ECI48_OUT_MASKMAGIC_HIWORD | 0x40)) ++#define ECI_OUT_FM_DISABLE_SHIFT(ccrev) ((ccrev) < 35 ? 18 : 6) ++ ++/* Indicate control of ECI bits between s/w and dot11mac. ++ * 0 => FW control, 1=> MAC/ucode control ++ ++ * Current assignment (ccrev >= 35): ++ * 0 - TxConf (ucode) ++ * 38 - FM disable (wl) ++ * 39 - Allow sim rx (ucode) ++ * 40 - Num antennas (wl) ++ * 43:41 - WLAN channel exclusion BW (wl) ++ * 47:44 - WLAN channel (wl) ++ * ++ * (ccrev < 35) ++ * 15:0 - wl ++ * 16 - ++ * 18 - FM disable ++ * 30 - wl interrupt ++ * 31 - ucode interrupt ++ * others - unassigned (presumed to be with dot11mac/ucode) ++ */ ++#define ECI_MACCTRL_BITS 0xbffb0000 ++#define ECI_MACCTRLLO_BITS 0x1 ++#define ECI_MACCTRLHI_BITS 0xFF ++ ++ ++/* SECI configuration */ ++#define SECI_MODE_UART 0x0 ++#define SECI_MODE_SECI 0x1 ++#define SECI_MODE_LEGACY_3WIRE_BT 0x2 ++#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3 ++#define SECI_MODE_HALF_SECI 0x4 ++ ++#define SECI_RESET (1 << 0) ++#define SECI_RESET_BAR_UART (1 << 1) ++#define SECI_ENAB_SECI_ECI (1 << 2) ++#define SECI_ENAB_SECIOUT_DIS (1 << 3) ++#define SECI_MODE_MASK 0x7 ++#define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */ ++#define SECI_UPD_SECI (1 << 7) ++ ++#define SECI_SIGNOFF_0 0xDB ++#define SECI_SIGNOFF_1 0 ++ ++/* seci clk_ctl_st bits */ ++#define CLKCTL_STS_SECI_CLK_REQ (1 << 8) ++#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24) ++ ++#define SECI_UART_MSR_CTS_STATE (1 << 0) ++#define SECI_UART_MSR_RTS_STATE (1 << 1) ++#define SECI_UART_SECI_IN_STATE (1 << 2) ++#define SECI_UART_SECI_IN2_STATE (1 << 3) ++ ++/* SECI UART LCR/MCR register bits */ ++#define SECI_UART_LCR_STOP_BITS (1 << 0) /* 0 - 1bit, 1 - 2bits */ ++#define SECI_UART_LCR_PARITY_EN (1 << 1) ++#define SECI_UART_LCR_PARITY (1 << 2) /* 0 - odd, 1 - even */ ++#define SECI_UART_LCR_RX_EN (1 << 3) ++#define SECI_UART_LCR_LBRK_CTRL (1 << 4) /* 1 => SECI_OUT held low */ ++#define SECI_UART_LCR_TXO_EN (1 << 5) ++#define SECI_UART_LCR_RTSO_EN (1 << 6) ++#define SECI_UART_LCR_SLIPMODE_EN (1 << 7) ++#define SECI_UART_LCR_RXCRC_CHK (1 << 8) ++#define SECI_UART_LCR_TXCRC_INV (1 << 9) ++#define SECI_UART_LCR_TXCRC_LSBF (1 << 10) ++#define SECI_UART_LCR_TXCRC_EN (1 << 11) ++ ++#define SECI_UART_MCR_TX_EN (1 << 0) ++#define SECI_UART_MCR_PRTS (1 << 1) ++#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2) ++#define SECI_UART_MCR_HIGHRATE_EN (1 << 3) ++#define SECI_UART_MCR_LOOPBK_EN (1 << 4) ++#define SECI_UART_MCR_AUTO_RTS (1 << 5) ++#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6) ++#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7) ++#define SECI_UART_MCR_XONOFF_RPT (1 << 9) ++ ++/* WLAN channel numbers - used from wifi.h */ ++ ++/* WLAN BW */ ++#define ECI_BW_20 0x0 ++#define ECI_BW_25 0x1 ++#define ECI_BW_30 0x2 ++#define ECI_BW_35 0x3 ++#define ECI_BW_40 0x4 ++#define ECI_BW_45 0x5 ++#define ECI_BW_50 0x6 ++#define ECI_BW_ALL 0x7 ++ ++/* WLAN - number of antenna */ ++#define WLAN_NUM_ANT1 TXANT_0 ++#define WLAN_NUM_ANT2 TXANT_1 ++ ++#endif /* _SBCHIPC_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbconfig.h b/drivers/bcmdrivers/gmac/src/include/sbconfig.h +new file mode 100755 +index 0000000..cd13ce6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbconfig.h +@@ -0,0 +1,276 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SiliconBackplane hardware register definitions. ++ * ++ * $Id: sbconfig.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _SBCONFIG_H ++#define _SBCONFIG_H ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif ++ ++/* enumeration in SB is based on the premise that cores are contiguos in the ++ * enumeration space. ++ */ ++#define SB_BUS_SIZE 0x10000 /* Each bus gets 64Kbytes for cores */ ++#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) ++#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /* Max cores per bus */ ++ ++/* ++ * Sonics Configuration Space Registers. ++ */ ++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ ++ ++#define SBIPSFLAG 0x08 ++#define SBTPSFLAG 0x18 ++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ ++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ ++#define SBADMATCH3 0x60 ++#define SBADMATCH2 0x68 ++#define SBADMATCH1 0x70 ++#define SBIMSTATE 0x90 ++#define SBINTVEC 0x94 ++#define SBTMSTATELOW 0x98 ++#define SBTMSTATEHIGH 0x9c ++#define SBBWA0 0xa0 ++#define SBIMCONFIGLOW 0xa8 ++#define SBIMCONFIGHIGH 0xac ++#define SBADMATCH0 0xb0 ++#define SBTMCONFIGLOW 0xb8 ++#define SBTMCONFIGHIGH 0xbc ++#define SBBCONFIG 0xc0 ++#define SBBSTATE 0xc8 ++#define SBACTCNFG 0xd8 ++#define SBFLAGST 0xe8 ++#define SBIDLOW 0xf8 ++#define SBIDHIGH 0xfc ++ ++/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have ++ * a few registers *below* that line. I think it would be very confusing to try ++ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here, ++ */ ++ ++#define SBIMERRLOGA 0xea8 ++#define SBIMERRLOG 0xeb0 ++#define SBTMPORTCONNID0 0xed8 ++#define SBTMPORTLOCK0 0xef8 ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _sbconfig { ++ uint32 PAD[2]; ++ uint32 sbipsflag; /* initiator port ocp slave flag */ ++ uint32 PAD[3]; ++ uint32 sbtpsflag; /* target port ocp slave flag */ ++ uint32 PAD[11]; ++ uint32 sbtmerrloga; /* (sonics >= 2.3) */ ++ uint32 PAD; ++ uint32 sbtmerrlog; /* (sonics >= 2.3) */ ++ uint32 PAD[3]; ++ uint32 sbadmatch3; /* address match3 */ ++ uint32 PAD; ++ uint32 sbadmatch2; /* address match2 */ ++ uint32 PAD; ++ uint32 sbadmatch1; /* address match1 */ ++ uint32 PAD[7]; ++ uint32 sbimstate; /* initiator agent state */ ++ uint32 sbintvec; /* interrupt mask */ ++ uint32 sbtmstatelow; /* target state */ ++ uint32 sbtmstatehigh; /* target state */ ++ uint32 sbbwa0; /* bandwidth allocation table0 */ ++ uint32 PAD; ++ uint32 sbimconfiglow; /* initiator configuration */ ++ uint32 sbimconfighigh; /* initiator configuration */ ++ uint32 sbadmatch0; /* address match0 */ ++ uint32 PAD; ++ uint32 sbtmconfiglow; /* target configuration */ ++ uint32 sbtmconfighigh; /* target configuration */ ++ uint32 sbbconfig; /* broadcast configuration */ ++ uint32 PAD; ++ uint32 sbbstate; /* broadcast state */ ++ uint32 PAD[3]; ++ uint32 sbactcnfg; /* activate configuration */ ++ uint32 PAD[3]; ++ uint32 sbflagst; /* current sbflags */ ++ uint32 PAD[3]; ++ uint32 sbidlow; /* identification */ ++ uint32 sbidhigh; /* identification */ ++} sbconfig_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* sbipsflag */ ++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ ++#define SBIPS_INT1_SHIFT 0 ++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ ++#define SBIPS_INT2_SHIFT 8 ++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ ++#define SBIPS_INT3_SHIFT 16 ++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ ++#define SBIPS_INT4_SHIFT 24 ++ ++/* sbtpsflag */ ++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ ++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ ++ ++/* sbtmerrlog */ ++#define SBTMEL_CM 0x00000007 /* command */ ++#define SBTMEL_CI 0x0000ff00 /* connection id */ ++#define SBTMEL_EC 0x0f000000 /* error code */ ++#define SBTMEL_ME 0x80000000 /* multiple error */ ++ ++/* sbimstate */ ++#define SBIM_PC 0xf /* pipecount */ ++#define SBIM_AP_MASK 0x30 /* arbitration policy */ ++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ ++#define SBIM_AP_TS 0x10 /* use timesliaces only */ ++#define SBIM_AP_TK 0x20 /* use token only */ ++#define SBIM_AP_RSV 0x30 /* reserved */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++ ++/* sbtmstatelow */ ++#define SBTML_RESET 0x0001 /* reset */ ++#define SBTML_REJ_MASK 0x0006 /* reject field */ ++#define SBTML_REJ 0x0002 /* reject */ ++#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ ++ ++#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ ++ ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x0001 /* serror */ ++#define SBTMH_INT 0x0002 /* interrupt */ ++#define SBTMH_BUSY 0x0004 /* busy */ ++#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ ++ ++#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ ++ ++/* sbbwa0 */ ++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ ++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ ++#define SBBWA_TAB1_SHIFT 16 ++ ++/* sbimconfiglow */ ++#define SBIMCL_STO_MASK 0x7 /* service timeout */ ++#define SBIMCL_RTO_MASK 0x70 /* request timeout */ ++#define SBIMCL_RTO_SHIFT 4 ++#define SBIMCL_CID_MASK 0xff0000 /* connection id */ ++#define SBIMCL_CID_SHIFT 16 ++ ++/* sbimconfighigh */ ++#define SBIMCH_IEM_MASK 0xc /* inband error mode */ ++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ ++#define SBIMCH_TEM_SHIFT 4 ++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ ++#define SBIMCH_BEM_SHIFT 6 ++ ++/* sbadmatch0 */ ++#define SBAM_TYPE_MASK 0x3 /* address type */ ++#define SBAM_AD64 0x4 /* reserved */ ++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ ++#define SBAM_ADINT0_SHIFT 3 ++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ ++#define SBAM_ADINT1_SHIFT 3 ++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ ++#define SBAM_ADINT2_SHIFT 3 ++#define SBAM_ADEN 0x400 /* enable */ ++#define SBAM_ADNEG 0x800 /* negative decode */ ++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ ++#define SBAM_BASE0_SHIFT 8 ++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ ++#define SBAM_BASE1_SHIFT 12 ++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ ++#define SBAM_BASE2_SHIFT 16 ++ ++/* sbtmconfiglow */ ++#define SBTMCL_CD_MASK 0xff /* clock divide */ ++#define SBTMCL_CO_MASK 0xf800 /* clock offset */ ++#define SBTMCL_CO_SHIFT 11 ++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ ++#define SBTMCL_IF_SHIFT 18 ++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ ++#define SBTMCL_IM_SHIFT 24 ++ ++/* sbtmconfighigh */ ++#define SBTMCH_BM_MASK 0x3 /* busy mode */ ++#define SBTMCH_RM_MASK 0x3 /* retry mode */ ++#define SBTMCH_RM_SHIFT 2 ++#define SBTMCH_SM_MASK 0x30 /* stop mode */ ++#define SBTMCH_SM_SHIFT 4 ++#define SBTMCH_EM_MASK 0x300 /* sb error mode */ ++#define SBTMCH_EM_SHIFT 8 ++#define SBTMCH_IM_MASK 0xc00 /* int mode */ ++#define SBTMCH_IM_SHIFT 10 ++ ++/* sbbconfig */ ++#define SBBC_LAT_MASK 0x3 /* sb latency */ ++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ ++#define SBBC_MAX0_SHIFT 16 ++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ ++#define SBBC_MAX1_SHIFT 20 ++ ++/* sbbstate */ ++#define SBBS_SRD 0x1 /* st reg disable */ ++#define SBBS_HRD 0x2 /* hold reg disable */ ++ ++/* sbidlow */ ++#define SBIDL_CS_MASK 0x3 /* config space */ ++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ ++#define SBIDL_AR_SHIFT 3 ++#define SBIDL_SYNCH 0x40 /* sync */ ++#define SBIDL_INIT 0x80 /* initiator */ ++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ ++#define SBIDL_MINLAT_SHIFT 8 ++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ ++#define SBIDL_MAXLAT_SHIFT 12 ++#define SBIDL_FIRST 0x10000 /* this initiator is first */ ++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ ++#define SBIDL_CW_SHIFT 18 ++#define SBIDL_TP_MASK 0xf00000 /* target ports */ ++#define SBIDL_TP_SHIFT 20 ++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ ++#define SBIDL_IP_SHIFT 24 ++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ ++#define SBIDL_RV_SHIFT 28 ++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ ++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ ++ ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 ++ ++#define SB_COMMIT 0xfd8 /* update buffered registers value */ ++ ++/* vendor codes */ ++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ ++ ++#endif /* _SBCONFIG_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbhndarm.h b/drivers/bcmdrivers/gmac/src/include/sbhndarm.h +new file mode 100755 +index 0000000..f925da3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbhndarm.h +@@ -0,0 +1,293 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom SiliconBackplane ARM definitions ++ * ++ * $Id: sbhndarm.h 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#ifndef _sbhndarm_h_ ++#define _sbhndarm_h_ ++ ++#include ++#include ++ ++/* register offsets */ ++#define ARM7_CORECTL 0 ++ ++/* bits in corecontrol */ ++#define ACC_FORCED_RST 0x1 ++#define ACC_SERRINT 0x2 ++#define ACC_NOTSLEEPINGCLKREQ_SHIFT 24 ++ ++/* arm resetlog */ ++#define SBRESETLOG 0x1 ++#define SERRORLOG 0x2 ++ ++/* arm core-specific control flags */ ++#define SICF_REMAP_MSK 0x001c ++#define SICF_REMAP_NONE 0 ++#define SICF_REMAP_ROM 0x0004 ++#define SIFC_REMAP_FLASH 0x0008 ++ ++/* misc core-specific defines */ ++#if defined(__ARM_ARCH_4T__) ++/* arm7tdmi-s */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARM7S_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARM7S_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 SI_ARM7S_SRAM2 /* RAM backplane address when remap is 1 or 2 */ ++#elif defined(__ARM_ARCH_7M__) ++/* cortex-m3 */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCM3_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARMCM3_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 SI_ARMCM3_SRAM2 /* RAM backplane address when remap is 1 or 2 */ ++/* core registers offsets */ ++#define ARMCM3_CYCLECNT 0x90 /* Cortex-M3 core registers offsets */ ++#define ARMCM3_INTTIMER 0x94 ++#define ARMCM3_INTMASK 0x98 ++#define ARMCM3_INTSTATUS 0x9c ++/* interrupt/exception */ ++#define ARMCM3_NUMINTS 16 /* # of external interrupts */ ++#define ARMCM3_INTALL ((1 << ARMCM3_NUMINTS) - 1) /* Interrupt mask */ ++#define ARMCM3_FAULTMASK 0x40000000 /* Master fault enable/disable */ ++#define ARMCM3_PRIMASK 0x80000000 /* Master interrupt enable/disable */ ++#define ARMCM3_SHARED_INT 0 /* Interrupt shared by multiple cores */ ++#define ARMCM3_INT(i) (1 << (i)) /* Individual interrupt enable/disable */ ++/* compatible with arm7tdmi-s */ ++#define PS_I ARMCM3_PRIMASK ++#define PS_F ARMCM3_FAULTMASK ++/* intmask/intstatus bits */ ++#define ARMCM3_INTMASK_TIMER 0x1 ++#define ARMCM3_INTMASK_SYSRESET 0x4 ++#define ARMCM3_INTMASK_LOCKUP 0x8 ++ ++/* ++ * Overlay Support in Rev 5 ++ */ ++#define ARMCM3_OVL_VALID_SHIFT 0 ++#define ARMCM3_OVL_VALID 1 ++#define ARMCM3_OVL_SZ_SHIFT 1 ++#define ARMCM3_OVL_SZ_MASK 0x0000000e ++#define ARMCM3_OVL_SZ_512B 0 /* 512B */ ++#define ARMCM3_OVL_SZ_1KB 1 /* 1KB */ ++#define ARMCM3_OVL_SZ_2KB 2 /* 2KB */ ++#define ARMCM3_OVL_SZ_4KB 3 /* 4KB */ ++#define ARMCM3_OVL_SZ_8KB 4 /* 8KB */ ++#define ARMCM3_OVL_SZ_16KB 5 /* 16KB */ ++#define ARMCM3_OVL_SZ_32KB 6 /* 32KB */ ++#define ARMCM3_OVL_SZ_64KB 7 /* 64KB */ ++#define ARMCM3_OVL_ADDR_SHIFT 9 ++#define ARMCM3_OVL_ADDR_MASK 0x003FFE00 ++#define ARMCM3_OVL_MAX 16 ++ ++#elif defined(__ARM_ARCH_7R__) ++/* cortex-r4 */ ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCR4_CORE_ID /* arm coreid */ ++#define SI_ARM_ROM SI_ARMCR4_ROM /* ROM backplane/system address */ ++#define SI_ARM_SRAM2 0x0 /* In the cr4 the RAM is just not available ++ * when remap is 1 ++ */ ++ ++/* core registers offsets */ ++#define ARMCR4_CORECTL 0 ++#define ARMCR4_CORECAP 4 ++#define ARMCR4_COREST 8 ++ ++#define ARMCR4_FIQRSTATUS 0x10 ++#define ARMCR4_FIQMASK 0x14 ++#define ARMCR4_IRQMASK 0x18 ++ ++#define ARMCR4_INTSTATUS 0x20 ++#define ARMCR4_INTMASK 0x24 ++#define ARMCR4_CYCLECNT 0x28 ++#define ARMCR4_INTTIMER 0x2c ++ ++#define ARMCR4_GPIOSEL 0x30 ++#define ARMCR4_GPIOEN 0x34 ++ ++#define ARMCR4_BANKIDX 0x40 ++#define ARMCR4_BANKINFO 0x44 ++#define ARMCR4_BANKSTBY 0x48 ++#define ARMCR4_BANKPDA 0x4c ++ ++#define ARMCR4_TCAMPATCHCTRL 0x68 ++#define ARMCR4_TCAMPATCHTBLBASEADDR 0x6C ++#define ARMCR4_TCAMCMDREG 0x70 ++#define ARMCR4_TCAMDATAREG 0x74 ++#define ARMCR4_TCAMBANKXMASKREG 0x78 ++ ++#define ARMCR4_ROMNB_MASK 0xf00 ++#define ARMCR4_ROMNB_SHIFT 8 ++#define ARMCR4_TCBBNB_MASK 0xf0 ++#define ARMCR4_TCBBNB_SHIFT 4 ++#define ARMCR4_TCBANB_MASK 0xf ++#define ARMCR4_TCBANB_SHIFT 0 ++ ++#define ARMCR4_MT_MASK 0x300 ++#define ARMCR4_MT_SHIFT 8 ++#define ARMCR4_MT_ROM 0x100 ++#define ARMCR4_MT_RAM 0 ++ ++#define ARMCR4_BSZ_MASK 0x3f ++#define ARMCR4_BSZ_MULT 8192 ++ ++#define ARMCR4_TCAM_ENABLE (1 << 31) ++#define ARMCR4_TCAM_CLKENAB (1 << 30) ++#define ARMCR4_TCAM_PATCHCNT_MASK 0xf ++ ++#define ARMCR4_TCAM_CMD_DONE (1 << 31) ++#define ARMCR4_TCAM_MATCH (1 << 24) ++#define ARMCR4_TCAM_OPCODE_MASK (3 << 16) ++#define ARMCR4_TCAM_OPCODE_SHIFT 16 ++#define ARMCR4_TCAM_ADDR_MASK 0xffff ++#define ARMCR4_TCAM_NONE (0 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_READ (1 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_WRITE (2 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_COMPARE (3 << ARMCR4_TCAM_OPCODE_SHIFT) ++#define ARMCR4_TCAM_CMD_DONE_DLY 1000 ++ ++#define ARMCR4_DATA_MASK (~0x7) ++#define ARMCR4_DATA_VALID (1 << 0) ++ ++ ++/* arm core-specific conrol flags */ ++#define SICF_CPUHALT 0x0020 ++#define SICF_UPDATEFW 0x0040 ++ ++/* arm core-specific status flags */ ++#define SISF_SDRENABLE 0x0001 ++#define SISF_TCMPROT 0x0002 ++ ++#define CHIP_SDRENABLE(sih) (sih->boardflags2 & BFL2_SDR_EN) ++#define CHIP_TCMPROTENAB(sih) (si_arm_sflags(sih) & SISF_TCMPROT) ++ ++#elif defined(__ARM_ARCH_7A__) ++/* backplane related stuff */ ++#define ARM_CORE_ID ARMCA9_CORE_ID /* arm coreid */ ++ ++#else /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ ++#error Unrecognized ARM Architecture ++#endif /* !__ARM_ARCH_4T__ && !__ARM_ARCH_7M__ && !__ARM_ARCH_7R__ */ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++#if defined(__ARM_ARCH_4T__) ++/* arm7tdmi-s */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0 */ ++ uint32 sleepcontrol; /* 4 */ ++ uint32 PAD; ++ uint32 biststatus; /* 0xc */ ++ uint32 firqstatus; /* 0x10 */ ++ uint32 fiqmask; /* 0x14 */ ++ uint32 irqmask; /* 0x18 */ ++ uint32 PAD; ++ uint32 resetlog; /* 0x20 */ ++ uint32 gpioselect; /* 0x24 */ ++ uint32 gpioenable; /* 0x28 */ ++ uint32 PAD; ++ uint32 bpaddrlo; /* 0x30 */ ++ uint32 bpaddrhi; /* 0x34 */ ++ uint32 bpdata; /* 0x38 */ ++ uint32 bpindaccess; /* 0x3c */ ++ uint32 PAD[104]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; /* 0x1e4 */ ++} armregs_t; ++#define ARMREG(regs, reg) (&((armregs_t *)regs)->reg) ++#endif /* __ARM_ARCH_4T__ */ ++ ++#if defined(__ARM_ARCH_7M__) ++/* cortex-m3 */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0x0 */ ++ uint32 corestatus; /* 0x4 */ ++ uint32 PAD[1]; ++ uint32 biststatus; /* 0xc */ ++ uint32 nmiisrst; /* 0x10 */ ++ uint32 nmimask; /* 0x14 */ ++ uint32 isrmask; /* 0x18 */ ++ uint32 PAD[1]; ++ uint32 resetlog; /* 0x20 */ ++ uint32 gpioselect; /* 0x24 */ ++ uint32 gpioenable; /* 0x28 */ ++ uint32 PAD[1]; ++ uint32 bpaddrlo; /* 0x30 */ ++ uint32 bpaddrhi; /* 0x34 */ ++ uint32 bpdata; /* 0x38 */ ++ uint32 bpindaccess; /* 0x3c */ ++ uint32 ovlidx; /* 0x40 */ ++ uint32 ovlmatch; /* 0x44 */ ++ uint32 ovladdr; /* 0x48 */ ++ uint32 PAD[13]; ++ uint32 bwalloc; /* 0x80 */ ++ uint32 PAD[3]; ++ uint32 cyclecnt; /* 0x90 */ ++ uint32 inttimer; /* 0x94 */ ++ uint32 intmask; /* 0x98 */ ++ uint32 intstatus; /* 0x9c */ ++ uint32 PAD[80]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++} cm3regs_t; ++#define ARMREG(regs, reg) (&((cm3regs_t *)regs)->reg) ++#endif /* __ARM_ARCH_7M__ */ ++ ++#if defined(__ARM_ARCH_7R__) ++/* cortex-R4 */ ++typedef volatile struct { ++ uint32 corecontrol; /* 0x0 */ ++ uint32 corecapabilities; /* 0x4 */ ++ uint32 corestatus; /* 0x8 */ ++ uint32 biststatus; /* 0xc */ ++ uint32 nmiisrst; /* 0x10 */ ++ uint32 nmimask; /* 0x14 */ ++ uint32 isrmask; /* 0x18 */ ++ uint32 PAD[1]; ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; /* 0x24 */ ++ uint32 cyclecnt; /* 0x28 */ ++ uint32 inttimer; /* 0x2c */ ++ uint32 gpioselect; /* 0x30 */ ++ uint32 gpioenable; /* 0x34 */ ++ uint32 PAD[2]; ++ uint32 bankidx; /* 0x40 */ ++ uint32 bankinfo; /* 0x44 */ ++ uint32 bankstbyctl; /* 0x48 */ ++ uint32 bankpda; /* 0x4c */ ++ uint32 PAD[6]; ++ uint32 tcampatchctrl; /* 0x68 */ ++ uint32 tcampatchtblbaseaddr; /* 0x6c */ ++ uint32 tcamcmdreg; /* 0x70 */ ++ uint32 tcamdatareg; /* 0x74 */ ++ uint32 tcambankxmaskreg; /* 0x78 */ ++ uint32 PAD[89]; ++ uint32 clk_ctl_st; /* 0x1e0 */ ++} cr4regs_t; ++#define ARMREG(regs, reg) (&((cr4regs_t *)regs)->reg) ++#endif /* __ARM_ARCH_7R__ */ ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++#endif /* _sbhndarm_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbhnddma.h b/drivers/bcmdrivers/gmac/src/include/sbhnddma.h +new file mode 100755 +index 0000000..3003687 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbhnddma.h +@@ -0,0 +1,403 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: sbhnddma.h 321146 2012-03-14 08:27:23Z $ ++ */ ++ ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ ++ ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++ ++ ++/* 32 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 addr; /* descriptor ring base address (4K aligned) */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 status; /* current active descriptor, et al */ ++} dma32regs_t; ++ ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma32diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl; /* misc control bits & bufcount */ ++ uint32 addr; /* data buffer address */ ++} dma32dd_t; ++ ++/* ++ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. ++ */ ++#define D32RINGALIGN_BITS 12 ++#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) ++#define D32RINGALIGN (1 << D32RINGALIGN_BITS) ++ ++#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) ++ ++/* transmit channel control */ ++#define XC_XE ((uint32)1 << 0) /* transmit enable */ ++#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ ++#define XC_LE ((uint32)1 << 2) /* loopback enable */ ++#define XC_FL ((uint32)1 << 4) /* flush request */ ++#define XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define XC_MR_SHIFT 6 ++#define XC_PD ((uint32)1 << 11) /* parity check disable */ ++#define XC_AE ((uint32)3 << 16) /* address extension bits */ ++#define XC_AE_SHIFT 16 ++#define XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define XC_BL_SHIFT 18 ++#define XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define XC_PC_SHIFT 21 ++#define XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define XC_PT_SHIFT 24 ++ ++/* Multiple outstanding reads */ ++#define DMA_MR_1 0 ++#define DMA_MR_2 1 ++/* 2, 3: reserved */ ++ ++/* DMA Burst Length in bytes */ ++#define DMA_BL_16 0 ++#define DMA_BL_32 1 ++#define DMA_BL_64 2 ++#define DMA_BL_128 3 ++#define DMA_BL_256 4 ++#define DMA_BL_512 5 ++#define DMA_BL_1024 6 ++ ++/* Prefetch control */ ++#define DMA_PC_0 0 ++#define DMA_PC_4 1 ++#define DMA_PC_8 2 ++#define DMA_PC_16 3 ++/* others: reserved */ ++ ++/* Prefetch threshold */ ++#define DMA_PT_1 0 ++#define DMA_PT_2 1 ++#define DMA_PT_4 2 ++#define DMA_PT_8 3 ++ ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define XS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define XS_XS_MASK 0xf000 /* transmit state */ ++#define XS_XS_SHIFT 12 ++#define XS_XS_DISABLED 0x0000 /* disabled */ ++#define XS_XS_ACTIVE 0x1000 /* active */ ++#define XS_XS_IDLE 0x2000 /* idle wait */ ++#define XS_XS_STOPPED 0x3000 /* stopped */ ++#define XS_XS_SUSP 0x4000 /* suspend pending */ ++#define XS_XE_MASK 0xf0000 /* transmit errors */ ++#define XS_XE_SHIFT 16 ++#define XS_XE_NOERR 0x00000 /* no error */ ++#define XS_XE_DPE 0x10000 /* descriptor protocol error */ ++#define XS_XE_DFU 0x20000 /* data fifo underrun */ ++#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ ++#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ ++#define XS_AD_MASK 0xfff00000 /* active descriptor */ ++#define XS_AD_SHIFT 20 ++ ++/* receive channel control */ ++#define RC_RE ((uint32)1 << 0) /* receive enable */ ++#define RC_RO_MASK 0xfe /* receive frame offset */ ++#define RC_RO_SHIFT 1 ++#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ ++#define RC_SH ((uint32)1 << 9) /* separate rx header descriptor enable */ ++#define RC_OC ((uint32)1 << 10) /* overflow continue */ ++#define RC_PD ((uint32)1 << 11) /* parity check disable */ ++#define RC_AE ((uint32)3 << 16) /* address extension bits */ ++#define RC_AE_SHIFT 16 ++#define RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define RC_BL_SHIFT 18 ++#define RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define RC_PC_SHIFT 21 ++#define RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define RC_PT_SHIFT 24 ++ ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define RS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define RS_RS_MASK 0xf000 /* receive state */ ++#define RS_RS_SHIFT 12 ++#define RS_RS_DISABLED 0x0000 /* disabled */ ++#define RS_RS_ACTIVE 0x1000 /* active */ ++#define RS_RS_IDLE 0x2000 /* idle wait */ ++#define RS_RS_STOPPED 0x3000 /* reserved */ ++#define RS_RE_MASK 0xf0000 /* receive errors */ ++#define RS_RE_SHIFT 16 ++#define RS_RE_NOERR 0x00000 /* no error */ ++#define RS_RE_DPE 0x10000 /* descriptor protocol error */ ++#define RS_RE_DFO 0x20000 /* data fifo overflow */ ++#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ ++#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ ++#define RS_AD_MASK 0xfff00000 /* active descriptor */ ++#define RS_AD_SHIFT 20 ++ ++/* fifoaddr */ ++#define FA_OFF_MASK 0xffff /* offset */ ++#define FA_SEL_MASK 0xf0000 /* select */ ++#define FA_SEL_SHIFT 16 ++#define FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define FA_SEL_RDD 0x40000 /* receive dma data */ ++#define FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags */ ++#define CTRL_BC_MASK 0x00001fff /* buffer byte count, real data len must <= 4KB */ ++#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ ++#define CTRL_AE_SHIFT 16 ++#define CTRL_PARITY ((uint32)3 << 18) /* parity bit */ ++#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ ++#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ ++ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ ++ uint32 status0; /* current descriptor, xmt state */ ++ uint32 status1; /* active descriptor, xmt error */ ++} dma64regs_t; ++ ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma64diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl1; /* misc control bits */ ++ uint32 ctrl2; /* buffer count and address extension */ ++ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++} dma64dd_t; ++ ++/* ++ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. ++ */ ++#define D64RINGALIGN_BITS 13 ++#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) ++#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS) ++ ++#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) ++ ++/* for cores with large descriptor ring support, descriptor ring size can be up to 4096 */ ++#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t)) ++ ++/* for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross ++ * 64K boundary ++ */ ++#define D64RINGBOUNDARY_LARGE (1 << 16) ++ ++/* ++ * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11. ++ * When this field contains the value N, the burst length is 2**(N + 4) bytes. ++ */ ++#define D64_DEF_USBBURSTLEN 2 ++#define D64_DEF_SDIOBURSTLEN 1 ++ ++ ++#ifndef D64_USBBURSTLEN ++#define D64_USBBURSTLEN DMA_BL_64 ++#endif ++#ifndef D64_SDIOBURSTLEN ++#define D64_SDIOBURSTLEN DMA_BL_32 ++#endif ++ ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define D64_XC_MR_SHIFT 6 ++#define D64_XC_PD 0x00000800 /* parity check disable */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 ++#define D64_XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_XC_BL_SHIFT 18 ++#define D64_XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_XC_PC_SHIFT 21 ++#define D64_XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_XC_PT_SHIFT 24 ++ ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ ++/* receive channel control */ ++#define D64_RC_RE 0x00000001 /* receive enable */ ++#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ ++#define D64_RC_RO_SHIFT 1 ++#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ ++#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ ++#define D64_RC_OC 0x00000400 /* overflow continue */ ++#define D64_RC_PD 0x00000800 /* parity check disable */ ++#define D64_RC_GE 0x00004000 /* Glom enable */ ++#define D64_RC_AE 0x00030000 /* address extension bits */ ++#define D64_RC_AE_SHIFT 16 ++#define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_RC_BL_SHIFT 18 ++#define D64_RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_RC_PC_SHIFT 21 ++#define D64_RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_RC_PT_SHIFT 24 ++ ++/* flags for dma controller */ ++#define DMA_CTRL_PEN (1 << 0) /* partity enable */ ++#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */ ++#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */ ++#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */ ++#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4) ++#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /* DMA avoidance WAR for 4331 */ ++#define DMA_CTRL_RXSINGLE (1 << 6) /* always single buffer */ ++ ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++ ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags 1 */ ++#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ ++#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* descriptor control flags 2 */ ++#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */ ++#define D64_CTRL2_AE 0x00030000 /* address extension bits */ ++#define D64_CTRL2_AE_SHIFT 16 ++#define D64_CTRL2_PARITY 0x00040000 /* parity bit */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 ++ ++#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ ++#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ ++#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1, d11corerev >= 22 */ ++#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ ++ ++/* receive frame status */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++} dma_rxh_t; ++ ++#endif /* _sbhnddma_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/sbsocram.h b/drivers/bcmdrivers/gmac/src/include/sbsocram.h +new file mode 100755 +index 0000000..1afd2e3 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/sbsocram.h +@@ -0,0 +1,193 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * BCM47XX Sonics SiliconBackplane embedded ram core ++ * ++ * $Id: sbsocram.h 271781 2011-07-13 20:00:06Z $ ++ */ ++ ++#ifndef _SBSOCRAM_H ++#define _SBSOCRAM_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* Memcsocram core registers */ ++typedef volatile struct sbsocramregs { ++ uint32 coreinfo; ++ uint32 bwalloc; ++ uint32 extracoreinfo; ++ uint32 biststat; ++ uint32 bankidx; ++ uint32 standbyctrl; ++ ++ uint32 errlogstatus; /* rev 6 */ ++ uint32 errlogaddr; /* rev 6 */ ++ /* used for patching rev 3 & 5 */ ++ uint32 cambankidx; ++ uint32 cambankstandbyctrl; ++ uint32 cambankpatchctrl; ++ uint32 cambankpatchtblbaseaddr; ++ uint32 cambankcmdreg; ++ uint32 cambankdatareg; ++ uint32 cambankmaskreg; ++ uint32 PAD[1]; ++ uint32 bankinfo; /* corev 8 */ ++ uint32 PAD[15]; ++ uint32 extmemconfig; ++ uint32 extmemparitycsr; ++ uint32 extmemparityerrdata; ++ uint32 extmemparityerrcnt; ++ uint32 extmemwrctrlandsize; ++ uint32 PAD[84]; ++ uint32 workaround; ++ uint32 pwrctl; /* corerev >= 2 */ ++ uint32 PAD[133]; ++ uint32 sr_control; /* corerev >= 15 */ ++ uint32 sr_status; /* corerev >= 15 */ ++ uint32 sr_address; /* corerev >= 15 */ ++ uint32 sr_data; /* corerev >= 15 */ ++} sbsocramregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Register offsets */ ++#define SR_COREINFO 0x00 ++#define SR_BWALLOC 0x04 ++#define SR_BISTSTAT 0x0c ++#define SR_BANKINDEX 0x10 ++#define SR_BANKSTBYCTL 0x14 ++#define SR_PWRCTL 0x1e8 ++ ++/* Coreinfo register */ ++#define SRCI_PT_MASK 0x00070000 /* corerev >= 6; port type[18:16] */ ++#define SRCI_PT_SHIFT 16 ++/* port types : SRCI_PT__ */ ++#define SRCI_PT_OCP_OCP 0 ++#define SRCI_PT_AXI_OCP 1 ++#define SRCI_PT_ARM7AHB_OCP 2 ++#define SRCI_PT_CM3AHB_OCP 3 ++#define SRCI_PT_AXI_AXI 4 ++#define SRCI_PT_AHB_AXI 5 ++/* corerev >= 3 */ ++#define SRCI_LSS_MASK 0x00f00000 ++#define SRCI_LSS_SHIFT 20 ++#define SRCI_LRS_MASK 0x0f000000 ++#define SRCI_LRS_SHIFT 24 ++ ++/* In corerev 0, the memory size is 2 to the power of the ++ * base plus 16 plus to the contents of the memsize field plus 1. ++ */ ++#define SRCI_MS0_MASK 0xf ++#define SR_MS0_BASE 16 ++ ++/* ++ * In corerev 1 the bank size is 2 ^ the bank size field plus 14, ++ * the memory size is number of banks times bank size. ++ * The same applies to rom size. ++ */ ++#define SRCI_ROMNB_MASK 0xf000 ++#define SRCI_ROMNB_SHIFT 12 ++#define SRCI_ROMBSZ_MASK 0xf00 ++#define SRCI_ROMBSZ_SHIFT 8 ++#define SRCI_SRNB_MASK 0xf0 ++#define SRCI_SRNB_SHIFT 4 ++#define SRCI_SRBSZ_MASK 0xf ++#define SRCI_SRBSZ_SHIFT 0 ++ ++#define SR_BSZ_BASE 14 ++ ++/* Standby control register */ ++#define SRSC_SBYOVR_MASK 0x80000000 ++#define SRSC_SBYOVR_SHIFT 31 ++#define SRSC_SBYOVRVAL_MASK 0x60000000 ++#define SRSC_SBYOVRVAL_SHIFT 29 ++#define SRSC_SBYEN_MASK 0x01000000 /* rev >= 3 */ ++#define SRSC_SBYEN_SHIFT 24 ++ ++/* Power control register */ ++#define SRPC_PMU_STBYDIS_MASK 0x00000010 /* rev >= 3 */ ++#define SRPC_PMU_STBYDIS_SHIFT 4 ++#define SRPC_STBYOVRVAL_MASK 0x00000008 ++#define SRPC_STBYOVRVAL_SHIFT 3 ++#define SRPC_STBYOVR_MASK 0x00000007 ++#define SRPC_STBYOVR_SHIFT 0 ++ ++/* Extra core capability register */ ++#define SRECC_NUM_BANKS_MASK 0x000000F0 ++#define SRECC_NUM_BANKS_SHIFT 4 ++#define SRECC_BANKSIZE_MASK 0x0000000F ++#define SRECC_BANKSIZE_SHIFT 0 ++ ++#define SRECC_BANKSIZE(value) (1 << (value)) ++ ++/* CAM bank patch control */ ++#define SRCBPC_PATCHENABLE 0x80000000 ++ ++#define SRP_ADDRESS 0x0001FFFC ++#define SRP_VALID 0x8000 ++ ++/* CAM bank command reg */ ++#define SRCMD_WRITE 0x00020000 ++#define SRCMD_READ 0x00010000 ++#define SRCMD_DONE 0x80000000 ++ ++#define SRCMD_DONE_DLY 1000 ++ ++/* bankidx and bankinfo reg defines corerev >= 8 */ ++#define SOCRAM_BANKINFO_SZMASK 0x7f ++#define SOCRAM_BANKIDX_ROM_MASK 0x100 ++ ++#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 ++/* socram bankinfo memtype */ ++#define SOCRAM_MEMTYPE_RAM 0 ++#define SOCRAM_MEMTYPE_R0M 1 ++#define SOCRAM_MEMTYPE_DEVRAM 2 ++ ++#define SOCRAM_BANKINFO_REG 0x40 ++#define SOCRAM_BANKIDX_REG 0x10 ++#define SOCRAM_BANKINFO_STDBY_MASK 0x400 ++#define SOCRAM_BANKINFO_STDBY_TIMER 0x800 ++ ++/* bankinfo rev >= 10 */ ++#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT 13 ++#define SOCRAM_BANKINFO_DEVRAMSEL_MASK 0x2000 ++#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT 14 ++#define SOCRAM_BANKINFO_DEVRAMPRO_MASK 0x4000 ++#define SOCRAM_BANKINFO_SLPSUPP_SHIFT 15 ++#define SOCRAM_BANKINFO_SLPSUPP_MASK 0x8000 ++#define SOCRAM_BANKINFO_RETNTRAM_SHIFT 16 ++#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 ++#define SOCRAM_BANKINFO_PDASZ_SHIFT 17 ++#define SOCRAM_BANKINFO_PDASZ_MASK 0x003E0000 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT 24 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK 0x01000000 ++ ++/* extracoreinfo register */ ++#define SOCRAM_DEVRAMBANK_MASK 0xF000 ++#define SOCRAM_DEVRAMBANK_SHIFT 12 ++ ++/* bank info to calculate bank size */ ++#define SOCRAM_BANKINFO_SZBASE 8192 ++#define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */ ++ ++ ++#endif /* _SBSOCRAM_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/siutils.h b/drivers/bcmdrivers/gmac/src/include/siutils.h +new file mode 100755 +index 0000000..5e4ce7d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/siutils.h +@@ -0,0 +1,256 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing the SOC Interconnects ++ * of Broadcom HNBU chips. ++ * ++ * $Id: siutils.h 323456 2012-03-24 07:17:39Z $ ++ */ ++ ++#ifndef _siutils_h_ ++#define _siutils_h_ ++ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++#include "bcm_rpc.h" ++#endif ++/* ++ * Data structure to export all chip specific common variables ++ * public (read-only) portion of siutils handle returned by si_attach()/si_kattach() ++ */ ++struct si_pub { ++ uint socitype; /* SOCI_SB, SOCI_AI */ ++ ++ uint bustype; /* SI_BUS, PCI_BUS */ ++ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ uint32 cccaps; /* chip common capabilities */ ++ uint32 cccaps_ext; /* chip common capabilities extension */ ++ int pmurev; /* pmu core rev */ ++ uint32 pmucaps; /* pmu capabilities */ ++ uint boardtype; /* board type */ ++ uint boardrev; /* board rev */ ++ uint boardvendor; /* board vendor */ ++ uint boardflags; /* board flags */ ++ uint boardflags2; /* board flags2 */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ uint32 chipst; /* chip status */ ++ bool issim; /* chip is in simulation or emulation */ ++ uint socirev; /* SOC interconnect rev */ ++ bool pci_pr32414; ++ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++ rpc_info_t *rpc; ++#endif ++#ifdef SI_ENUM_BASE_VARIABLE ++ uint32 si_enum_base; ++#endif /* SI_ENUM_BASE_VARIABLE */ ++}; ++ ++/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver ++ * for monolithic driver, it is readonly to prevent accident change ++ */ ++#if defined(WLC_HIGH) && !defined(WLC_LOW) ++typedef struct si_pub si_t; ++#else ++typedef const struct si_pub si_t; ++#endif ++ ++#ifdef ATE_BUILD ++typedef struct _ate_params { ++ void* wl; ++ uint8 gpio_input; ++ uint8 gpio_output; ++ bool cmd_proceed; ++ uint16 cmd_idx; ++ bool ate_cmd_done; ++} ate_params_t; ++#endif /* ATE_BUILD */ ++ ++/* ++ * Many of the routines below take an 'sih' handle as their first arg. ++ * Allocate this by calling si_attach(). Free it by calling si_detach(). ++ * At any one time, the sih is logically focused on one particular si core ++ * (the "current core"). ++ * Use si_setcore() or si_setcoreidx() to change the association to another core. ++ */ ++#define SI_OSH NULL /* Use for si_kattach when no osh is available */ ++ ++#define BADIDX (SI_MAXCORES + 1) ++ ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ ++ ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ ++ ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ ++#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ ++ ++/* GPIO pull up/down */ ++#define GPIO_PULLUP 0 ++#define GPIO_PULLDN 1 ++ ++/* GPIO event regtype */ ++#define GPIO_REGEVT 0 /* GPIO register event */ ++#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ ++#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ ++ ++/* device path */ ++#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ ++ ++/* SI routine enumeration: to be used by update function with multiple hooks */ ++#define SI_DOATTACH 1 ++#define SI_PCIDOWN 2 ++#define SI_PCIUP 3 ++ ++#if defined(BCMQT) ++#define ISSIM_ENAB(sih) ((sih)->issim) ++#else ++#define ISSIM_ENAB(sih) 0 ++#endif ++ ++/* PMU clock/power control */ ++#if defined(BCMPMUCTL) ++#define PMUCTL_ENAB(sih) (BCMPMUCTL) ++#else ++#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) ++#endif ++ ++/* chipcommon clock/power control (exclusive with PMU's) */ ++#if defined(BCMPMUCTL) && BCMPMUCTL ++#define CCCTL_ENAB(sih) (0) ++#define CCPLL_ENAB(sih) (0) ++#else ++#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) ++#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) ++#endif ++ ++typedef void (*gpio_handler_t)(uint32 stat, void *arg); ++/* External BT Coex enable mask */ ++#define CC_BTCOEX_EN_MASK 0x01 ++/* External PA enable mask */ ++#define GPIO_CTRL_EPA_EN_MASK 0x40 ++/* WL/BT control enable mask */ ++#define GPIO_CTRL_5_6_EN_MASK 0x60 ++#define GPIO_CTRL_7_6_EN_MASK 0xC0 ++#define GPIO_OUT_7_EN_MASK 0x80 ++ ++ ++ ++ ++/* === exported functions === */ ++extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *si_kattach(osl_t *osh); ++extern void si_detach(si_t *sih); ++ ++extern uint si_corelist(si_t *sih, uint coreid[]); ++extern uint si_coreid(si_t *sih); ++extern uint si_flag(si_t *sih); ++extern uint si_intflag(si_t *sih); ++extern uint si_coreidx(si_t *sih); ++extern uint si_coreunit(si_t *sih); ++extern uint si_corevendor(si_t *sih); ++extern uint si_corerev(si_t *sih); ++extern void *si_osh(si_t *sih); ++extern void si_setosh(si_t *sih, osl_t *osh); ++extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void *si_coreregs(si_t *sih); ++extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); ++#ifdef WLC_HIGH_ONLY ++extern bool wlc_bmac_iscoreup(si_t *sih); ++#define si_iscoreup(sih) wlc_bmac_iscoreup(sih) ++#else ++extern bool si_iscoreup(si_t *sih); ++#endif /* __CONFIG_USBAP__ */ ++extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit); ++extern void *si_setcoreidx(si_t *sih, uint coreidx); ++extern void *si_setcore(si_t *sih, uint coreid, uint coreunit); ++extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); ++extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); ++extern int si_numaddrspaces(si_t *sih); ++extern uint32 si_addrspace(si_t *sih, uint asidx); ++extern uint32 si_addrspacesize(si_t *sih, uint asidx); ++extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern int si_corebist(si_t *sih); ++extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void si_core_disable(si_t *sih, uint32 bits); ++extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); ++extern uint32 si_clock(si_t *sih); ++extern uint32 si_alp_clock(si_t *sih); ++extern void si_setint(si_t *sih, int siflag); ++extern bool si_backplane64(si_t *sih); ++extern void si_clkctl_init(si_t *sih); ++extern bool si_clkctl_cc(si_t *sih, uint mode); ++extern int si_clkctl_xtal(si_t *sih, uint what, bool on); ++ ++extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool si_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool si_pci_fastpmecap(struct osl_info *osh); ++ ++/* SPROM availability */ ++#ifdef SI_SPROM_PROBE ++extern void si_sprom_init(si_t *sih); ++#endif /* SI_SPROM_PROBE */ ++ ++/* Fab-id information */ ++#define DEFAULT_FAB 0x0 /* Original/first fab used for this chip */ ++#define CSM_FAB7 0x1 /* CSM Fab7 chip */ ++#define TSMC_FAB12 0x2 /* TSMC Fab12/Fab14 chip */ ++#define SMIC_FAB4 0x3 /* SMIC Fab4 chip */ ++ ++/* ++ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. ++ * The returned path is NULL terminated and has trailing '/'. ++ * Return 0 on success, nonzero otherwise. ++ */ ++extern int si_devpath(si_t *sih, char *path, int size); ++/* Read variable with prepending the devpath to the name */ ++extern int si_getdevpathintvar(si_t *sih, const char *name); ++extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name); ++ ++ ++extern void si_war42780_clkreq(si_t *sih, bool clkreq); ++extern void si_pcie_extendL1timer(si_t *sih, bool extend); ++ ++/* === debug routines === */ ++ ++#ifdef BCMDBG ++extern void si_view(si_t *sih, bool verbose); ++extern void si_viewall(si_t *sih, bool verbose); ++#endif ++ ++#if defined(BCMDBG) ++struct bcmstrbuf; ++extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b); ++#endif ++ ++ ++#endif /* _siutils_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/trxhdr.h b/drivers/bcmdrivers/gmac/src/include/trxhdr.h +new file mode 100755 +index 0000000..4926311 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/trxhdr.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * TRX image file header format. ++ * ++ * $Id: trxhdr.h 314841 2012-02-14 18:28:33Z $ ++ */ ++ ++#ifndef _TRX_HDR_H ++#define _TRX_HDR_H ++ ++#include ++ ++#define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_MAX_LEN 0x3B0000 /* Max length */ ++#define TRX_NO_HEADER 1 /* Do not write TRX header */ ++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ ++#define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ ++#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ ++#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ ++#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */ ++ ++#define TRX_V1 1 ++#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */ ++ ++#ifndef BCMTRXV2 ++#define TRX_VERSION TRX_V1 /* Version 1 */ ++#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS ++#endif ++ ++/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as ++ * Ver 2 of trx header. To make it generic, trx_header is structure is modified ++ * as below where size of "offsets" field will vary as per the TRX version. ++ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well. ++ * To make sure, other applications like "dhdl" which are yet to be enhanced to support ++ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2 ++ * is defined. ++ */ ++struct trx_header { ++ uint32 magic; /* "HDR0" */ ++ uint32 len; /* Length of file including header */ ++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32 flag_version; /* 0:15 flags, 16:31 version */ ++#ifndef BCMTRXV2 ++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++#else ++ uint32 offsets[1]; /* Offsets of partitions from start of header */ ++#endif ++}; ++ ++#ifdef BCMTRXV2 ++#define TRX_VERSION TRX_V2 /* Version 2 */ ++#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS ++ ++#define TRX_V2 2 ++/* V2: Max number of individual files ++ * To support SDR signature + Config data region ++ */ ++#define TRX_V2_MAX_OFFSETS 5 ++#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32)) ++#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32)) ++#define TRX_VER(trx) (trx->flag_version>>16) ++#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1) ++#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2) ++/* For V2, return size of V2 size: others, return V1 size */ ++#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1) ++#else ++#define SIZEOF_TRX(trx) (sizeof(struct trx_header)) ++#endif /* BCMTRXV2 */ ++ ++/* Compatibility */ ++typedef struct trx_header TRXHDR, *PTRXHDR; ++ ++#endif /* _TRX_HDR_H */ +diff --git a/drivers/bcmdrivers/gmac/src/include/typedefs.h b/drivers/bcmdrivers/gmac/src/include/typedefs.h +new file mode 100644 +index 0000000..5caa36a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/typedefs.h +@@ -0,0 +1,452 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * $Id: typedefs.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++#ifndef _TYPEDEFS_H_ ++#define _TYPEDEFS_H_ ++ ++#ifdef SITE_TYPEDEFS ++ ++/* ++ * Define SITE_TYPEDEFS in the compile to include a site-specific ++ * typedef file "site_typedefs.h". ++ * ++ * If SITE_TYPEDEFS is not defined, then the code section below makes ++ * inferences about the compile environment based on defined symbols and ++ * possibly compiler pragmas. ++ * ++ * Following these two sections is the Default Typedefs section. ++ * This section is only processed if USE_TYPEDEF_DEFAULTS is ++ * defined. This section has a default set of typedefs and a few ++ * preprocessor symbols (TRUE, FALSE, NULL, ...). ++ */ ++ ++#include "site_typedefs.h" ++ ++#else ++ ++/* ++ * Infer the compile environment based on preprocessor symbols and pragmas. ++ * Override type definitions as needed, and include configuration-dependent ++ * header files to define types. ++ */ ++ ++#ifdef __cplusplus ++ ++#define TYPEDEF_BOOL ++#ifndef FALSE ++#define FALSE false ++#endif ++#ifndef TRUE ++#define TRUE true ++#endif ++ ++#else /* ! __cplusplus */ ++ ++#if defined(_WIN32) ++ ++#define TYPEDEF_BOOL ++typedef unsigned char bool; /* consistent w/BOOL */ ++ ++#endif /* _WIN32 */ ++ ++#endif /* ! __cplusplus */ ++ ++#if defined(_WIN64) && !defined(EFI) ++/* use the Windows ULONG_PTR type when compiling for 64 bit */ ++#include ++#define TYPEDEF_UINTPTR ++typedef ULONG_PTR uintptr; ++#elif defined(__x86_64__) ++#define TYPEDEF_UINTPTR ++typedef unsigned long long int uintptr; ++#endif ++ ++ ++#if defined(_MINOSL_) ++#define _NEED_SIZE_T_ ++#endif ++ ++#if defined(EFI) && !defined(_WIN64) ++#define _NEED_SIZE_T_ ++#endif ++ ++#if defined(TARGETOS_nucleus) ++/* for 'size_t' type */ ++#include ++ ++/* float_t types conflict with the same typedefs from the standard ANSI-C ++** math.h header file. Don't re-typedef them here. ++*/ ++#define TYPEDEF_FLOAT_T ++#endif /* TARGETOS_nucleus */ ++ ++#if defined(_NEED_SIZE_T_) ++typedef long unsigned int size_t; ++#endif ++ ++#ifdef _MSC_VER /* Microsoft C */ ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++typedef signed __int64 int64; ++typedef unsigned __int64 uint64; ++#endif ++ ++#if defined(MACOSX) ++#define TYPEDEF_BOOL ++#endif ++ ++#if defined(__NetBSD__) ++#define TYPEDEF_BOOL ++#ifndef _KERNEL ++#include ++#endif ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* defined(__NetBSD__) */ ++ ++#if defined(__sparc__) ++#define TYPEDEF_ULONG ++#endif ++ ++ ++#ifdef linux ++/* ++ * If this is either a Linux hybrid build or the per-port code of a hybrid build ++ * then use the Linux header files to get some of the typedefs. Otherwise, define ++ * them entirely in this file. We can't always define the types because we get ++ * a duplicate typedef error; there is no way to "undefine" a typedef. ++ * We know when it's per-port code because each file defines LINUX_PORT at the top. ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#define TYPEDEF_UINT ++#ifndef TARGETENV_android ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* TARGETENV_android */ ++#ifdef __KERNEL__ ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) ++#define TYPEDEF_BOOL ++#endif /* >= 2.6.19 */ ++/* special detection for 2.6.18-128.7.1.0.1.el5 */ ++#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18)) ++#include ++#ifdef noinline_for_stack ++#define TYPEDEF_BOOL ++#endif ++#endif /* == 2.6.18 */ ++#endif /* __KERNEL__ */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++#endif /* linux */ ++ ++#if defined(__ECOS) ++#define TYPEDEF_UCHAR ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#define TYPEDEF_BOOL ++#endif ++ ++#if !defined(linux) && !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && \ ++ !defined(__DJGPP__) && !defined(__ECOS) && !defined(__BOB__) && \ ++ !defined(TARGETOS_nucleus) && !defined(EFI) && !defined(__FreeBSD__) ++#define TYPEDEF_UINT ++#define TYPEDEF_USHORT ++#endif ++ ++ ++/* Do not support the (u)int64 types with strict ansi for GNU C */ ++#if defined(__GNUC__) && defined(__STRICT_ANSI__) ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++#endif ++ ++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode ++ * for signed or unsigned ++ */ ++#if defined(__ICL) ++ ++#define TYPEDEF_INT64 ++ ++#if defined(__STDC__) ++#define TYPEDEF_UINT64 ++#endif ++ ++#endif /* __ICL */ ++ ++#if !defined(_WIN32) && !defined(_CFE_) && !defined(_MINOSL_) && !defined(__DJGPP__) && \ ++ !defined(__BOB__) && !defined(TARGETOS_nucleus) && !defined(EFI) ++ ++/* pick up ushort & uint from standard types.h */ ++#if defined(linux) && defined(__KERNEL__) ++ ++/* See note above */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#ifdef USER_MODE ++#include ++#else ++#include /* sys/types.h and linux/types.h are oil and water */ ++#endif /* USER_MODE */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++#else ++ ++#if defined(__ECOS) ++#include ++#include ++#include ++#endif ++ ++#include ++ ++#endif /* linux && __KERNEL__ */ ++ ++#endif ++ ++#if defined(CONFIG_MACH_NSP) || defined(CONFIG_MACH_HX4) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) /* JIRA:LINUXDEV- */ ++#ifdef CONFIG_CPU_BIG_ENDIAN ++#define IL_BIGENDIAN ++#endif /* CONFIG_CPU_BIG_ENDIAN */ ++#else ++ ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++ ++#endif ++ ++#if defined(MACOSX) ++ ++#ifdef __BIG_ENDIAN__ ++#define IL_BIGENDIAN ++#else ++#ifdef IL_BIGENDIAN ++#error "IL_BIGENDIAN was defined for a little-endian compile" ++#endif ++#endif /* __BIG_ENDIAN__ */ ++ ++#if !defined(__cplusplus) ++ ++#if defined(__i386__) ++typedef unsigned char bool; ++#else ++typedef unsigned int bool; ++#endif ++#define TYPE_BOOL 1 ++enum { ++ false = 0, ++ true = 1 ++}; ++ ++#if defined(KERNEL) ++#include ++#endif /* KERNEL */ ++ ++#endif /* __cplusplus */ ++ ++#endif /* MACOSX */ ++ ++ ++/* use the default typedefs in the next section of this file */ ++#define USE_TYPEDEF_DEFAULTS ++ ++#endif /* SITE_TYPEDEFS */ ++ ++ ++/* ++ * Default Typedefs ++ */ ++ ++#ifdef USE_TYPEDEF_DEFAULTS ++#undef USE_TYPEDEF_DEFAULTS ++ ++#ifndef TYPEDEF_BOOL ++typedef /* @abstract@ */ unsigned char bool; ++#endif ++ ++/* define uchar, ushort, uint, ulong */ ++ ++#ifndef TYPEDEF_UCHAR ++typedef unsigned char uchar; ++#endif ++ ++#ifndef TYPEDEF_USHORT ++typedef unsigned short ushort; ++#endif ++ ++#ifndef TYPEDEF_UINT ++typedef unsigned int uint; ++#endif ++ ++#ifndef TYPEDEF_ULONG ++typedef unsigned long ulong; ++#endif ++ ++/* define [u]int8/16/32/64, uintptr */ ++ ++#ifndef TYPEDEF_UINT8 ++typedef unsigned char uint8; ++#endif ++ ++#ifndef TYPEDEF_UINT16 ++typedef unsigned short uint16; ++#endif ++ ++#ifndef TYPEDEF_UINT32 ++typedef unsigned int uint32; ++#endif ++ ++#ifndef TYPEDEF_UINT64 ++typedef unsigned long long uint64; ++#endif ++ ++#ifndef TYPEDEF_UINTPTR ++typedef unsigned int uintptr; ++#endif ++ ++#ifndef TYPEDEF_INT8 ++typedef signed char int8; ++#endif ++ ++#ifndef TYPEDEF_INT16 ++typedef signed short int16; ++#endif ++ ++#ifndef TYPEDEF_INT32 ++typedef signed int int32; ++#endif ++ ++#ifndef TYPEDEF_INT64 ++typedef signed long long int64; ++#endif ++ ++/* define float32/64, float_t */ ++ ++#ifndef TYPEDEF_FLOAT32 ++typedef float float32; ++#endif ++ ++#ifndef TYPEDEF_FLOAT64 ++typedef double float64; ++#endif ++ ++/* ++ * abstracted floating point type allows for compile time selection of ++ * single or double precision arithmetic. Compiling with -DFLOAT32 ++ * selects single precision; the default is double precision. ++ */ ++ ++#ifndef TYPEDEF_FLOAT_T ++ ++#if defined(FLOAT32) ++typedef float32 float_t; ++#else /* default to double precision floating point */ ++typedef float64 float_t; ++#endif ++ ++#endif /* TYPEDEF_FLOAT_T */ ++ ++/* define macro values */ ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 /* TRUE */ ++#endif ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++#ifndef OFF ++#define OFF 0 ++#endif ++ ++#ifndef ON ++#define ON 1 /* ON = 1 */ ++#endif ++ ++#define AUTO (-1) /* Auto = -1 */ ++ ++/* define PTRSZ, INLINE */ ++ ++#ifndef PTRSZ ++#define PTRSZ sizeof(char*) ++#endif ++ ++ ++/* Detect compiler type. */ ++#ifdef _MSC_VER ++ #define BWL_COMPILER_MICROSOFT ++#elif defined(__GNUC__) || defined(__lint) ++ #define BWL_COMPILER_GNU ++#elif defined(__CC_ARM) && __CC_ARM ++ #define BWL_COMPILER_ARMCC ++#else ++ #error "Unknown compiler!" ++#endif /* _MSC_VER */ ++ ++ ++#ifndef INLINE ++ #if defined(BWL_COMPILER_MICROSOFT) ++ #define INLINE __inline ++ #elif defined(BWL_COMPILER_GNU) ++ #define INLINE __inline__ ++ #elif defined(BWL_COMPILER_ARMCC) ++ #define INLINE __inline ++ #else ++ #define INLINE ++ #endif /* _MSC_VER */ ++#endif /* INLINE */ ++ ++#undef TYPEDEF_BOOL ++#undef TYPEDEF_UCHAR ++#undef TYPEDEF_USHORT ++#undef TYPEDEF_UINT ++#undef TYPEDEF_ULONG ++#undef TYPEDEF_UINT8 ++#undef TYPEDEF_UINT16 ++#undef TYPEDEF_UINT32 ++#undef TYPEDEF_UINT64 ++#undef TYPEDEF_UINTPTR ++#undef TYPEDEF_INT8 ++#undef TYPEDEF_INT16 ++#undef TYPEDEF_INT32 ++#undef TYPEDEF_INT64 ++#undef TYPEDEF_FLOAT32 ++#undef TYPEDEF_FLOAT64 ++#undef TYPEDEF_FLOAT_T ++ ++#endif /* USE_TYPEDEF_DEFAULTS */ ++ ++/* Suppress unused parameter warning */ ++#define UNUSED_PARAMETER(x) (void)(x) ++ ++/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ ++#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) ++ ++/* ++ * Including the bcmdefs.h here, to make sure everyone including typedefs.h ++ * gets this automatically ++*/ ++#include ++#endif /* _TYPEDEFS_H_ */ +diff --git a/drivers/bcmdrivers/gmac/src/include/wlioctl.h b/drivers/bcmdrivers/gmac/src/include/wlioctl.h +new file mode 100755 +index 0000000..3aef8ca +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/include/wlioctl.h +@@ -0,0 +1,4883 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Custom OID/ioctl definitions for ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * $Id: wlioctl.h 324203 2012-03-28 09:55:17Z $ ++ */ ++ ++#ifndef _wlioctl_h_ ++#define _wlioctl_h_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#ifdef __NetBSD__ ++/* NetBSD 2.0 does not have SIOCDEVPRIVATE. */ ++#define SIOCDEVPRIVATE _IOWR('i', 139, struct ifreq) ++#endif ++ ++#ifndef INTF_NAME_SIZ ++#define INTF_NAME_SIZ 16 ++#endif ++ ++/* Used to send ioctls over the transport pipe */ ++typedef struct remote_ioctl { ++ cdc_ioctl_t msg; ++ uint data_len; ++#ifndef OLYMPIC_RWL ++ char intf_name[INTF_NAME_SIZ]; ++#endif ++} rem_ioctl_t; ++#define REMOTE_SIZE sizeof(rem_ioctl_t) ++#ifdef EFI ++#define BCMWL_IOCTL_GUID \ ++ {0xB4910A35, 0x88C5, 0x4328, { 0x90, 0x08, 0x9F, 0xB2, 0x00, 0x00, 0x0, 0x0 } } ++#endif /* EFI */ ++ ++#define ACTION_FRAME_SIZE 1800 ++ ++typedef struct wl_action_frame { ++ struct ether_addr da; ++ uint16 len; ++ uint32 packetId; ++ uint8 data[ACTION_FRAME_SIZE]; ++} wl_action_frame_t; ++ ++#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) ++ ++typedef struct ssid_info ++{ ++ uint8 ssid_len; /* the length of SSID */ ++ uint8 ssid[32]; /* SSID string */ ++} ssid_info_t; ++ ++typedef struct wl_af_params { ++ uint32 channel; ++ int32 dwell_time; ++ struct ether_addr BSSID; ++ wl_action_frame_t action_frame; ++} wl_af_params_t; ++ ++#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params) ++ ++#define MFP_TEST_FLAG_NORMAL 0 ++#define MFP_TEST_FLAG_ANY_KEY 1 ++typedef struct wl_sa_query { ++ uint32 flag; ++ uint8 action; ++ uint16 id; ++ struct ether_addr da; ++} wl_sa_query_t; ++ ++ ++/* require default structure packing */ ++#define BWL_DEFAULT_PACKING ++#include ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Legacy structure to help keep backward compatible wl tool and tray app */ ++ ++#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ ++ ++typedef struct wl_bss_info_107 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ uint8 channel; /* Channel no. */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* variable length Information Elements */ ++} wl_bss_info_107_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* ++ * Per-BSS information structure. ++ */ ++ ++#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info_108 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint32 reserved32[1]; /* Reserved for expansion of BSS properties */ ++ uint8 flags; /* flags */ ++ uint8 reserved[3]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_108_t; ++ ++#define WL_BSS_INFO_VERSION 109 /* current version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint16 vht_rxmcsmap; /* VHT rx mcs map */ ++ uint16 vht_txmcsmap; /* VHT tx mcs map */ ++ uint8 flags; /* flags */ ++ uint8 vht_cap; /* BSS is vht capable */ ++ uint8 reserved[2]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ int16 SNR; /* average SNR of during frame reception */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_t; ++ ++typedef struct wl_bsscfg { ++ uint32 wsec; ++ uint32 WPA_auth; ++ uint32 wsec_index; ++ uint32 associated; ++ uint32 BSS; ++ uint32 phytest_on; ++ struct ether_addr prev_BSSID; ++ struct ether_addr BSSID; ++} wl_bsscfg_t; ++ ++typedef struct wl_bss_config { ++ uint32 atim_window; ++ uint32 beacon_period; ++ uint32 chanspec; ++} wl_bss_config_t; ++ ++#define DLOAD_HANDLER_VER 1 /* Downloader version */ ++#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ ++#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ ++ ++#define DL_CRC_NOT_INUSE 0x0001 ++ ++/* generic download types & flags */ ++enum { ++ DL_TYPE_UCODE = 1, ++ DL_TYPE_CLM = 2 ++}; ++ ++/* ucode type values */ ++enum { ++ UCODE_FW, ++ INIT_VALS, ++ BS_INIT_VALS ++}; ++ ++struct wl_dload_data { ++ uint16 flag; ++ uint16 dload_type; ++ uint32 len; ++ uint32 crc; ++ uint8 data[1]; ++}; ++typedef struct wl_dload_data wl_dload_data_t; ++ ++struct wl_ucode_info { ++ uint32 ucode_type; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_num; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_ucode_info wl_ucode_info_t; ++ ++struct wl_clm_dload_info { ++ uint32 ds_id; ++ uint32 clm_total_len; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_offset; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_clm_dload_info wl_clm_dload_info_t; ++ ++typedef struct wlc_ssid { ++ uint32 SSID_len; ++ uchar SSID[32]; ++} wlc_ssid_t; ++ ++#define MAX_PREFERRED_AP_NUM 5 ++typedef struct wlc_fastssidinfo { ++ uint32 SSID_channel[MAX_PREFERRED_AP_NUM]; ++ wlc_ssid_t SSID_info[MAX_PREFERRED_AP_NUM]; ++} wlc_fastssidinfo_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct wnm_url { ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT wnm_url_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct chan_scandata { ++ uint8 txpower; ++ uint8 pad; ++ chanspec_t channel; /* Channel num, bw, ctrl_sb and band */ ++ uint32 channel_mintime; ++ uint32 channel_maxtime; ++} chan_scandata_t; ++ ++typedef enum wl_scan_type { ++ EXTDSCAN_FOREGROUND_SCAN, ++ EXTDSCAN_BACKGROUND_SCAN, ++ EXTDSCAN_FORCEDBACKGROUND_SCAN ++} wl_scan_type_t; ++ ++#define WLC_EXTDSCAN_MAX_SSID 5 ++ ++#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ ++#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ ++#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info was received on channel (vs offchannel) */ ++ ++typedef struct wl_extdscan_params { ++ int8 nprobes; /* 0, passive, otherwise active */ ++ int8 split_scan; /* split scan */ ++ int8 band; /* band */ ++ int8 pad; ++ wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */ ++ uint32 tx_rate; /* in 500ksec units */ ++ wl_scan_type_t scan_type; /* enum */ ++ int32 channel_num; ++ chan_scandata_t channel_list[1]; /* list of chandata structs */ ++} wl_extdscan_params_t; ++ ++#define WL_EXTDSCAN_PARAMS_FIXED_SIZE (sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t)) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_BSSTYPE_INFRA 1 ++#define WL_BSSTYPE_INDEP 0 ++#define WL_BSSTYPE_ANY 2 ++ ++/* Bitmask for scan_type */ ++#define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ ++#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ ++#define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ ++ ++#define WL_SCAN_PARAMS_SSID_MAX 10 ++ ++typedef struct wl_scan_params { ++ wlc_ssid_t ssid; /* default: {0, ""} */ ++ struct ether_addr bssid; /* default: bcast */ ++ int8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ uint8 scan_type; /* flags, 0 use default */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++ int32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in channel_list, 0 ++ * means default (use all available channels) ++ * ++ * high half is entries in wlc_ssid_t array that ++ * follows channel_list, aligned for int32 (4 bytes) ++ * meaning an odd channel count implies a 2-byte pad ++ * between end of channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the fixed ++ * parameter portion is assumed, otherwise ssid in ++ * the fixed portion is ignored ++ */ ++ uint16 channel_list[1]; /* list of chanspecs */ ++} wl_scan_params_t; ++ ++/* size of wl_scan_params not including variable length array */ ++#define WL_SCAN_PARAMS_FIXED_SIZE 64 ++ ++/* masks for channel and ssid count */ ++#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff ++#define WL_SCAN_PARAMS_NSSID_SHIFT 16 ++ ++#define WL_SCAN_ACTION_START 1 ++#define WL_SCAN_ACTION_CONTINUE 2 ++#define WL_SCAN_ACTION_ABORT 3 ++ ++#define ISCAN_REQ_VERSION 1 ++ ++/* incremental scan struct */ ++typedef struct wl_iscan_params { ++ uint32 version; ++ uint16 action; ++ uint16 scan_duration; ++ wl_scan_params_t params; ++} wl_iscan_params_t; ++ ++/* 3 fields + size of wl_scan_params, not including variable length array */ ++#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_scan_results { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ wl_bss_info_t bss_info[1]; ++} wl_scan_results_t; ++ ++/* size of wl_scan_results not including variable length array */ ++#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t)) ++ ++/* wl_iscan_results status values */ ++#define WL_SCAN_RESULTS_SUCCESS 0 ++#define WL_SCAN_RESULTS_PARTIAL 1 ++#define WL_SCAN_RESULTS_PENDING 2 ++#define WL_SCAN_RESULTS_ABORTED 3 ++#define WL_SCAN_RESULTS_NO_MEM 4 ++ ++/* Used in EXT_STA */ ++#define DNGL_RXCTXT_SIZE 45 ++ ++#if defined(SIMPLE_ISCAN) ++#define ISCAN_RETRY_CNT 5 ++#define ISCAN_STATE_IDLE 0 ++#define ISCAN_STATE_SCANING 1 ++#define ISCAN_STATE_PENDING 2 ++ ++/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */ ++#define WLC_IW_ISCAN_MAXLEN 2048 ++typedef struct iscan_buf { ++ struct iscan_buf * next; ++ char iscan_buf[WLC_IW_ISCAN_MAXLEN]; ++} iscan_buf_t; ++#endif /* SIMPLE_ISCAN */ ++ ++#define ESCAN_REQ_VERSION 1 ++ ++typedef struct wl_escan_params { ++ uint32 version; ++ uint16 action; ++ uint16 sync_id; ++ wl_scan_params_t params; ++} wl_escan_params_t; ++ ++#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_escan_result { ++ uint32 buflen; ++ uint32 version; ++ uint16 sync_id; ++ uint16 bss_count; ++ wl_bss_info_t bss_info[1]; ++} wl_escan_result_t; ++ ++#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) ++ ++/* incremental scan results struct */ ++typedef struct wl_iscan_results { ++ uint32 status; ++ wl_scan_results_t results; ++} wl_iscan_results_t; ++ ++/* size of wl_iscan_results not including variable length array */ ++#define WL_ISCAN_RESULTS_FIXED_SIZE \ ++ (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results)) ++ ++typedef struct wl_probe_params { ++ wlc_ssid_t ssid; ++ struct ether_addr bssid; ++ struct ether_addr mac; ++} wl_probe_params_t; ++ ++#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */ ++typedef struct wl_rateset { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++} wl_rateset_t; ++ ++typedef struct wl_rateset_args { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ ++} wl_rateset_args_t; ++ ++/* uint32 list */ ++typedef struct wl_uint32_list { ++ /* in - # of elements, out - # of entries */ ++ uint32 count; ++ /* variable length uint32 list */ ++ uint32 element[1]; ++} wl_uint32_list_t; ++ ++/* used for association with a specific BSSID and chanspec list */ ++typedef struct wl_assoc_params { ++ struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ ++ int32 chanspec_num; /* 0: all available channels, ++ * otherwise count of chanspecs in chanspec_list ++ */ ++ chanspec_t chanspec_list[1]; /* list of chanspecs */ ++} wl_assoc_params_t; ++#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list) ++ ++/* used for reassociation/roam to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_reassoc_params_t; ++#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for association to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_join_assoc_params_t; ++#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for join with or without a specific bssid and channel list */ ++typedef struct wl_join_params { ++ wlc_ssid_t ssid; ++ wl_assoc_params_t params; /* optional field, but it must include the fixed portion ++ * of the wl_assoc_params_t struct when it does present. ++ */ ++} wl_join_params_t; ++#define WL_JOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_join_params_t, params) + \ ++ WL_ASSOC_PARAMS_FIXED_SIZE) ++/* scan params for extended join */ ++typedef struct wl_join_scan_params { ++ uint8 scan_type; /* 0 use default, active or passive scan */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++} wl_join_scan_params_t; ++ ++/* extended join params */ ++typedef struct wl_extjoin_params { ++ wlc_ssid_t ssid; /* {0, ""}: wildcard scan */ ++ wl_join_scan_params_t scan; ++ wl_join_assoc_params_t assoc; /* optional field, but it must include the fixed portion ++ * of the wl_join_assoc_params_t struct when it does ++ * present. ++ */ ++} wl_extjoin_params_t; ++#define WL_EXTJOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_extjoin_params_t, assoc) + \ ++ WL_JOIN_ASSOC_PARAMS_FIXED_SIZE) ++ ++/* All builds use the new 11ac ratespec/chanspec */ ++#undef D11AC_IOTYPES ++#define D11AC_IOTYPES ++ ++#ifndef D11AC_IOTYPES ++ ++/* defines used by the nrate iovar */ ++#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ ++#define NRATE_SGI_SHIFT 23 /* sgi mode */ ++#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ ++ ++#define NRATE_STF_SISO 0 /* stf mode SISO */ ++#define NRATE_STF_CDD 1 /* stf mode CDD */ ++#define NRATE_STF_STBC 2 /* stf mode STBC */ ++#define NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#else /* D11AC_IOTYPES */ ++ ++/* WL_RSPEC defines for rate information */ ++#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */ ++#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */ ++#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */ ++#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */ ++#define WL_RSPEC_TXEXP_MASK 0x00000300 ++#define WL_RSPEC_TXEXP_SHIFT 8 ++#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ ++#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ ++#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ ++#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ ++#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ ++#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ ++#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */ ++#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */ ++ ++/* WL_RSPEC_ENCODING field defs */ ++#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */ ++ ++/* WL_RSPEC_BW field defs */ ++#define WL_RSPEC_BW_UNSPECIFIED 0 ++#define WL_RSPEC_BW_20MHZ 0x00010000 ++#define WL_RSPEC_BW_40MHZ 0x00020000 ++#define WL_RSPEC_BW_80MHZ 0x00030000 ++#define WL_RSPEC_BW_160MHZ 0x00040000 ++ ++/* Legacy defines for the nrate iovar */ ++#define OLD_NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define OLD_NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define OLD_NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define OLD_NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define OLD_NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define OLD_NRATE_SGI 0x00800000 /* sgi mode */ ++#define OLD_NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++ ++#define OLD_NRATE_STF_SISO 0 /* stf mode SISO */ ++#define OLD_NRATE_STF_CDD 1 /* stf mode CDD */ ++#define OLD_NRATE_STF_STBC 2 /* stf mode STBC */ ++#define OLD_NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#endif /* D11AC_IOTYPES */ ++ ++#define ANTENNA_NUM_1 1 /* total number of antennas to be used */ ++#define ANTENNA_NUM_2 2 ++#define ANTENNA_NUM_3 3 ++#define ANTENNA_NUM_4 4 ++ ++#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ ++#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ ++#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */ ++#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ ++#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ ++#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ ++#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ ++ ++#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ ++ ++typedef struct { ++ uint8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ ++ uint8 num_antcfg; /* number of available antenna configurations */ ++} wlc_antselcfg_t; ++ ++#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ ++ ++#define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */ ++#define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */ ++ ++#define IBSS_MED 15 /* Mediom in-bss congestion percentage */ ++#define IBSS_HI 25 /* Hi in-bss congestion percentage */ ++#define OBSS_MED 12 ++#define OBSS_HI 25 ++#define INTERFER_MED 5 ++#define INTERFER_HI 10 ++ ++#define CCA_FLAG_2G_ONLY 0x01 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_5G_ONLY 0x02 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_IGNORE_DURATION 0x04 /* Ignore dwell time for each channel */ ++#define CCA_FLAGS_PREFER_1_6_11 0x10 ++#define CCA_FLAG_IGNORE_INTERFER 0x20 /* do not exlude channel based on interfer level */ ++ ++#define CCA_ERRNO_BAND 1 /* After filtering for band pref, no choices left */ ++#define CCA_ERRNO_DURATION 2 /* After filtering for duration, no choices left */ ++#define CCA_ERRNO_PREF_CHAN 3 /* After filtering for chan pref, no choices left */ ++#define CCA_ERRNO_INTERFER 4 /* After filtering for interference, no choices left */ ++#define CCA_ERRNO_TOO_FEW 5 /* Only 1 channel was input */ ++ ++typedef struct { ++ uint32 duration; /* millisecs spent sampling this channel */ ++ uint32 congest_ibss; /* millisecs in our bss (presumably this traffic will */ ++ /* move if cur bss moves channels) */ ++ uint32 congest_obss; /* traffic not in our bss */ ++ uint32 interference; /* millisecs detecting a non 802.11 interferer. */ ++ uint32 timestamp; /* second timestamp */ ++} cca_congest_t; ++ ++typedef struct { ++ chanspec_t chanspec; /* Which channel? */ ++ uint8 num_secs; /* How many secs worth of data */ ++ cca_congest_t secs[1]; /* Data */ ++} cca_congest_channel_req_t; ++ ++/* interference source detection and identification mode */ ++#define ITFR_MODE_DISABLE 0 /* disable feature */ ++#define ITFR_MODE_MANUAL_ENABLE 1 /* enable manual detection */ ++#define ITFR_MODE_AUTO_ENABLE 2 /* enable auto detection */ ++ ++/* interference sources */ ++enum interference_source { ++ ITFR_NONE = 0, /* interference */ ++ ITFR_PHONE, /* wireless phone */ ++ ITFR_VIDEO_CAMERA, /* wireless video camera */ ++ ITFR_MICROWAVE_OVEN, /* microwave oven */ ++ ITFR_BABY_MONITOR, /* wireless baby monitor */ ++ ITFR_BLUETOOTH, /* bluetooth */ ++ ITFR_VIDEO_CAMERA_OR_BABY_MONITOR, /* wireless camera or baby monitor */ ++ ITFR_BLUETOOTH_OR_BABY_MONITOR, /* bluetooth or baby monitor */ ++ ITFR_VIDEO_CAMERA_OR_PHONE, /* video camera or phone */ ++ ITFR_UNIDENTIFIED /* interference from unidentified source */ ++}; ++ ++/* structure for interference source report */ ++typedef struct { ++ uint32 flags; /* flags. bit definitions below */ ++ uint32 source; /* last detected interference source */ ++ uint32 timestamp; /* second timestamp on interferenced flag change */ ++} interference_source_rep_t; ++ ++/* bit definitions for flags in interference source report */ ++#define ITFR_INTERFERENCED 1 /* interference detected */ ++#define ITFR_HOME_CHANNEL 2 /* home channel has interference */ ++#define ITFR_NOISY_ENVIRONMENT 4 /* noisy environemnt so feature stopped */ ++ ++#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ ++ ++typedef struct wl_country { ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in ++ * the Country IE ++ */ ++ int32 rev; /* revision specifier for ccode ++ * on set, -1 indicates unspecified. ++ * on get, rev >= 0 ++ */ ++ char ccode[WLC_CNTRY_BUF_SZ]; /* nul-terminated built-in country code. ++ * variable length, but fixed size in ++ * struct allows simple allocation for ++ * expected country strings <= 3 chars. ++ */ ++} wl_country_t; ++ ++typedef struct wl_channels_in_country { ++ uint32 buflen; ++ uint32 band; ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; ++ uint32 count; ++ uint32 channel[1]; ++} wl_channels_in_country_t; ++ ++typedef struct wl_country_list { ++ uint32 buflen; ++ uint32 band_set; ++ uint32 band; ++ uint32 count; ++ char country_abbrev[1]; ++} wl_country_list_t; ++ ++#define WL_NUM_RPI_BINS 8 ++#define WL_RM_TYPE_BASIC 1 ++#define WL_RM_TYPE_CCA 2 ++#define WL_RM_TYPE_RPI 3 ++ ++#define WL_RM_FLAG_PARALLEL (1<<0) ++ ++#define WL_RM_FLAG_LATE (1<<1) ++#define WL_RM_FLAG_INCAPABLE (1<<2) ++#define WL_RM_FLAG_REFUSED (1<<3) ++ ++typedef struct wl_rm_req_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++} wl_rm_req_elt_t; ++ ++typedef struct wl_rm_req { ++ uint32 token; /* overall measurement set token */ ++ uint32 count; /* number of measurement requests */ ++ void *cb; /* completion callback function: may be NULL */ ++ void *cb_arg; /* arg to completion callback function */ ++ wl_rm_req_elt_t req[1]; /* variable length block of requests */ ++} wl_rm_req_t; ++#define WL_RM_REQ_FIXED_LEN OFFSETOF(wl_rm_req_t, req) ++ ++typedef struct wl_rm_rep_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++ uint32 len; /* byte length of data block */ ++ uint8 data[1]; /* variable length data block */ ++} wl_rm_rep_elt_t; ++#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */ ++ ++#define WL_RPI_REP_BIN_NUM 8 ++typedef struct wl_rm_rpi_rep { ++ uint8 rpi[WL_RPI_REP_BIN_NUM]; ++ int8 rpi_max[WL_RPI_REP_BIN_NUM]; ++} wl_rm_rpi_rep_t; ++ ++typedef struct wl_rm_rep { ++ uint32 token; /* overall measurement set token */ ++ uint32 len; /* length of measurement report block */ ++ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ ++} wl_rm_rep_t; ++#define WL_RM_REP_FIXED_LEN 8 ++ ++ ++#if defined(BCMSUP_PSK) ++typedef enum sup_auth_status { ++ /* Basic supplicant authentication states */ ++ WLC_SUP_DISCONNECTED = 0, ++ WLC_SUP_CONNECTING, ++ WLC_SUP_IDREQUIRED, ++ WLC_SUP_AUTHENTICATING, ++ WLC_SUP_AUTHENTICATED, ++ WLC_SUP_KEYXCHANGE, ++ WLC_SUP_KEYED, ++ WLC_SUP_TIMEOUT, ++ WLC_SUP_LAST_BASIC_STATE, ++ ++ /* Extended supplicant authentication states */ ++ /* Waiting to receive handshake msg M1 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, ++ /* Preparing to send handshake msg M2 */ ++ WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, ++ /* Waiting to receive handshake msg M3 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, ++ WLC_SUP_KEYXCHANGE_PREP_M4, /* Preparing to send handshake msg M4 */ ++ WLC_SUP_KEYXCHANGE_WAIT_G1, /* Waiting to receive handshake msg G1 */ ++ WLC_SUP_KEYXCHANGE_PREP_G2 /* Preparing to send handshake msg G2 */ ++} sup_auth_status_t; ++#endif ++ ++/* Enumerate crypto algorithms */ ++#define CRYPTO_ALGO_OFF 0 ++#define CRYPTO_ALGO_WEP1 1 ++#define CRYPTO_ALGO_TKIP 2 ++#define CRYPTO_ALGO_WEP128 3 ++#define CRYPTO_ALGO_AES_CCM 4 ++#define CRYPTO_ALGO_AES_OCB_MSDU 5 ++#define CRYPTO_ALGO_AES_OCB_MPDU 6 ++#define CRYPTO_ALGO_NALG 7 ++#define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ ++ ++#define WSEC_GEN_MIC_ERROR 0x0001 ++#define WSEC_GEN_REPLAY 0x0002 ++#define WSEC_GEN_ICV_ERROR 0x0004 ++#define WSEC_GEN_MFP_ACT_ERROR 0x0008 ++#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010 ++#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020 ++ ++#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ ++#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ ++#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ ++#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ ++#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ ++ ++typedef struct wl_wsec_key { ++ uint32 index; /* key index */ ++ uint32 len; /* key length */ ++ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */ ++ uint32 pad_1[18]; ++ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ uint32 flags; /* misc flags */ ++ uint32 pad_2[2]; ++ int pad_3; ++ int iv_initialized; /* has IV been initialized already? */ ++ int pad_4; ++ /* Rx IV */ ++ struct { ++ uint32 hi; /* upper 32 bits of IV */ ++ uint16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ uint32 pad_5[2]; ++ struct ether_addr ea; /* per station */ ++} wl_wsec_key_t; ++ ++#define WSEC_MIN_PSK_LEN 8 ++#define WSEC_MAX_PSK_LEN 64 ++ ++/* Flag for key material needing passhash'ing */ ++#define WSEC_PASSPHRASE (1<<0) ++ ++/* receptacle for WLC_SET_WSEC_PMK parameter */ ++typedef struct { ++ ushort key_len; /* octets in key material */ ++ ushort flags; /* key handling qualification */ ++ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */ ++} wsec_pmk_t; ++ ++/* wireless security bitvec */ ++#define WEP_ENABLED 0x0001 ++#define TKIP_ENABLED 0x0002 ++#define AES_ENABLED 0x0004 ++#define WSEC_SWFLAG 0x0008 ++#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ ++ ++/* wsec macros for operating on the above definitions */ ++#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED) ++#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) ++#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) ++ ++#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) ++ ++#ifdef MFP ++#define MFP_CAPABLE 0x0200 ++#define MFP_REQUIRED 0x0400 ++#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ ++#endif /* MFP */ ++ ++/* WPA authentication mode bitvec */ ++#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ ++#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ ++#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ ++#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ ++/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ ++#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ ++#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ ++#define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ ++#define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ ++#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ ++#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ ++#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++/* pmkid */ ++#define MAXPMKID 16 ++ ++typedef struct _pmkid { ++ struct ether_addr BSSID; ++ uint8 PMKID[WPA2_PMKID_LEN]; ++} pmkid_t; ++ ++typedef struct _pmkid_list { ++ uint32 npmkid; ++ pmkid_t pmkid[1]; ++} pmkid_list_t; ++ ++typedef struct _pmkid_cand { ++ struct ether_addr BSSID; ++ uint8 preauth; ++} pmkid_cand_t; ++ ++typedef struct _pmkid_cand_list { ++ uint32 npmkid_cand; ++ pmkid_cand_t pmkid_cand[1]; ++} pmkid_cand_list_t; ++ ++typedef struct wl_assoc_info { ++ uint32 req_len; ++ uint32 resp_len; ++ uint32 flags; ++ struct dot11_assoc_req req; ++ struct ether_addr reassoc_bssid; /* used in reassoc's */ ++ struct dot11_assoc_resp resp; ++} wl_assoc_info_t; ++ ++/* flags */ ++#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct wl_led_info { ++ uint32 index; /* led index */ ++ uint32 behavior; ++ uint8 activehi; ++} wl_led_info_t; ++ ++ ++/* srom read/write struct passed through ioctl */ ++typedef struct { ++ uint byteoff; /* byte offset */ ++ uint nbytes; /* number of bytes */ ++ uint16 buf[1]; ++} srom_rw_t; ++ ++/* similar cis (srom or otp) struct [iovar: may not be aligned] */ ++typedef struct { ++ uint32 source; /* cis source */ ++ uint32 byteoff; /* byte offset */ ++ uint32 nbytes; /* number of bytes */ ++ /* data follows here */ ++} cis_rw_t; ++ ++#define WLC_CIS_DEFAULT 0 /* built-in default */ ++#define WLC_CIS_SROM 1 /* source is sprom */ ++#define WLC_CIS_OTP 2 /* source is otp */ ++ ++/* R_REG and W_REG struct passed through ioctl */ ++typedef struct { ++ uint32 byteoff; /* byte offset of the field in d11regs_t */ ++ uint32 val; /* read/write value of the field */ ++ uint32 size; /* sizeof the field */ ++ uint band; /* band (optional) */ ++} rw_reg_t; ++ ++/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ ++/* PCL - Power Control Loop */ ++/* current gain setting is replaced by user input */ ++#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ ++#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ ++/* current gain setting is maintained */ ++#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ ++ ++typedef struct { ++ uint16 auto_ctrl; /* WL_ATTEN_XX */ ++ uint16 bb; /* Baseband attenuation */ ++ uint16 radio; /* Radio attenuation */ ++ uint16 txctl1; /* Radio TX_CTL1 value */ ++} atten_t; ++ ++/* Per-AC retry parameters */ ++struct wme_tx_params_s { ++ uint8 short_retry; ++ uint8 short_fallback; ++ uint8 long_retry; ++ uint8 long_fallback; ++ uint16 max_rate; /* In units of 512 Kbps */ ++}; ++ ++typedef struct wme_tx_params_s wme_tx_params_t; ++ ++#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) ++ ++/* defines used by poweridx iovar - it controls power in a-band */ ++/* current gain setting is maintained */ ++#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ ++#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ ++#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ ++#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ ++/* value >= 0 causes ++ * - input to be set to that value ++ * - PCL to be off ++ */ ++ ++/* Used to get specific link/ac parameters */ ++typedef struct { ++ int ac; ++ uint8 val; ++ struct ether_addr ea; ++} link_val_t; ++ ++#define BCM_MAC_STATUS_INDICATION (0x40010200L) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint16 cap; /* sta's advertised capabilities */ ++ uint32 flags; /* flags defined below */ ++ uint32 idle; /* time since data pkt rx'd from sta */ ++ struct ether_addr ea; /* Station address */ ++ wl_rateset_t rateset; /* rateset in use */ ++ uint32 in; /* seconds elapsed since associated */ ++ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */ ++ uint32 tx_pkts; /* # of packets transmitted */ ++ uint32 tx_failures; /* # of packets failed */ ++ uint32 rx_ucast_pkts; /* # of unicast packets received */ ++ uint32 rx_mcast_pkts; /* # of multicast packets received */ ++ uint32 tx_rate; /* Rate of last successful tx frame */ ++ uint32 rx_rate; /* Rate of last successful rx frame */ ++ uint32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ ++ uint32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */ ++} sta_info_t; ++ ++#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_pkts) ++ ++#define WL_STA_VER 3 ++ ++/* Flags for sta_info_t indicating properties of STA */ ++#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ ++#define WL_STA_WME 0x2 /* WMM association */ ++#define WL_STA_UNUSED 0x4 ++#define WL_STA_AUTHE 0x8 /* Authenticated */ ++#define WL_STA_ASSOC 0x10 /* Associated */ ++#define WL_STA_AUTHO 0x20 /* Authorized */ ++#define WL_STA_WDS 0x40 /* Wireless Distribution System */ ++#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ ++#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ ++#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ ++#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ ++#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ ++#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ ++#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ ++#define WL_STA_SCBSTATS 0x4000 /* Per STA debug stats */ ++ ++#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++/* Used to get specific STA parameters */ ++typedef struct { ++ uint32 val; ++ struct ether_addr ea; ++} scb_val_t; ++ ++/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */ ++typedef struct { ++ uint32 code; ++ scb_val_t ioctl_args; ++} authops_t; ++ ++/* channel encoding */ ++typedef struct channel_info { ++ int hw_channel; ++ int target_channel; ++ int scan_channel; ++} channel_info_t; ++ ++/* For ioctls that take a list of MAC addresses */ ++struct maclist { ++ uint count; /* number of MAC addresses */ ++ struct ether_addr ea[1]; /* variable length array of MAC addresses */ ++}; ++ ++/* get pkt count struct passed through ioctl */ ++typedef struct get_pktcnt { ++ uint rx_good_pkt; ++ uint rx_bad_pkt; ++ uint tx_good_pkt; ++ uint tx_bad_pkt; ++ uint rx_ocast_good_pkt; /* unicast packets destined for others */ ++} get_pktcnt_t; ++ ++/* NINTENDO2 */ ++#define LQ_IDX_MIN 0 ++#define LQ_IDX_MAX 1 ++#define LQ_IDX_AVG 2 ++#define LQ_IDX_SUM 2 ++#define LQ_IDX_LAST 3 ++#define LQ_STOP_MONITOR 0 ++#define LQ_START_MONITOR 1 ++ ++/* Get averages RSSI, Rx PHY rate and SNR values */ ++typedef struct { ++ int rssi[LQ_IDX_LAST]; /* Array to keep min, max, avg rssi */ ++ int snr[LQ_IDX_LAST]; /* Array to keep min, max, avg snr */ ++ int isvalid; /* Flag indicating whether above data is valid */ ++} wl_lq_t; /* Link Quality */ ++ ++typedef enum wl_wakeup_reason_type { ++ LCD_ON = 1, ++ LCD_OFF, ++ DRC1_WAKE, ++ DRC2_WAKE, ++ REASON_LAST ++} wl_wr_type_t; ++ ++typedef struct { ++/* Unique filter id */ ++ uint32 id; ++ ++/* stores the reason for the last wake up */ ++ uint8 reason; ++} wl_wr_t; ++ ++/* Get MAC specific rate histogram command */ ++typedef struct { ++ struct ether_addr ea; /* MAC Address */ ++ uint8 ac_cat; /* Access Category */ ++ uint8 num_pkts; /* Number of packet entries to be averaged */ ++} wl_mac_ratehisto_cmd_t; /* MAC Specific Rate Histogram command */ ++ ++/* Get MAC rate histogram response */ ++typedef struct { ++ uint32 rate[WLC_MAXRATE + 1]; /* Rates */ ++ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ ++ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ ++ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ ++} wl_mac_ratehisto_res_t; /* MAC Specific Rate Histogram Response */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++#define WL_IOCTL_ACTION_GET 0x0 ++#define WL_IOCTL_ACTION_SET 0x1 ++#define WL_IOCTL_ACTION_OVL_IDX_MASK 0x1e ++#define WL_IOCTL_ACTION_OVL_RSV 0x20 ++#define WL_IOCTL_ACTION_OVL 0x40 ++#define WL_IOCTL_ACTION_MASK 0x7e ++#define WL_IOCTL_ACTION_OVL_SHIFT 1 ++ ++/* Linux network driver ioctl encoding */ ++typedef struct wl_ioctl { ++ uint cmd; /* common ioctl definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ uint8 set; /* 1=set IOCTL; 0=query IOCTL */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++} wl_ioctl_t; ++ ++/* reference to wl_ioctl_t struct used by usermode driver */ ++#define ioctl_subtype set /* subtype param */ ++#define ioctl_pid used /* pid param */ ++#define ioctl_status needed /* status param */ ++ ++/* ++ * Structure for passing hardware and software ++ * revision info up from the driver. ++ */ ++typedef struct wlc_rev_info { ++ uint vendorid; /* PCI vendor id */ ++ uint deviceid; /* device id of chip */ ++ uint radiorev; /* radio revision */ ++ uint chiprev; /* chip revision */ ++ uint corerev; /* core revision */ ++ uint boardid; /* board identifier (usu. PCI sub-device id) */ ++ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */ ++ uint boardrev; /* board revision */ ++ uint driverrev; /* driver version */ ++ uint ucoderev; /* microcode version */ ++ uint bus; /* bus type */ ++ uint chipnum; /* chip number */ ++ uint phytype; /* phy type */ ++ uint phyrev; /* phy revision */ ++ uint anarev; /* anacore rev */ ++ uint chippkg; /* chip package info */ ++} wlc_rev_info_t; ++ ++#define WL_REV_INFO_LEGACY_LENGTH 48 ++ ++#define WL_BRAND_MAX 10 ++typedef struct wl_instance_info { ++ uint instance; ++ char brand[WL_BRAND_MAX]; ++} wl_instance_info_t; ++ ++/* structure to change size of tx fifo */ ++typedef struct wl_txfifo_sz { ++ uint16 magic; ++ uint16 fifo; ++ uint16 size; ++} wl_txfifo_sz_t; ++/* magic pattern used for mismatch driver and wl */ ++#define WL_TXFIFO_SZ_MAGIC 0xa5a5 ++ ++/* Transfer info about an IOVar from the driver */ ++/* Max supported IOV name size in bytes, + 1 for nul termination */ ++#define WLC_IOV_NAME_LEN 30 ++typedef struct wlc_iov_trx_s { ++ uint8 module; ++ uint8 type; ++ char name[WLC_IOV_NAME_LEN]; ++} wlc_iov_trx_t; ++ ++/* check this magic number */ ++#define WLC_IOCTL_MAGIC 0x14e46c77 ++ ++/* bump this number if you change the ioctl interface */ ++#ifdef D11AC_IOTYPES ++#define WLC_IOCTL_VERSION 2 ++#define WLC_IOCTL_VERSION_LEGACY_IOTYPES 1 ++#else ++#define WLC_IOCTL_VERSION 1 ++#endif /* D11AC_IOTYPES */ ++ ++#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ ++#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ ++#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ ++#ifdef WLC_HIGH_ONLY ++#define WLC_SAMPLECOLLECT_MAXLEN 1024 /* limit sample size for bmac */ ++#else ++#if defined(LCNCONF) || defined(LCN40CONF) ++#define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */ ++#else ++#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ ++#endif ++#endif /* WLC_HIGH_ONLY */ ++ ++/* common ioctl definitions */ ++#define WLC_GET_MAGIC 0 ++#define WLC_GET_VERSION 1 ++#define WLC_UP 2 ++#define WLC_DOWN 3 ++#define WLC_GET_LOOP 4 ++#define WLC_SET_LOOP 5 ++#define WLC_DUMP 6 ++#define WLC_GET_MSGLEVEL 7 ++#define WLC_SET_MSGLEVEL 8 ++#define WLC_GET_PROMISC 9 ++#define WLC_SET_PROMISC 10 ++/* #define WLC_OVERLAY_IOCTL 11 */ /* not supported */ ++#define WLC_GET_RATE 12 ++#define WLC_GET_MAX_RATE 13 ++#define WLC_GET_INSTANCE 14 ++/* #define WLC_GET_FRAG 15 */ /* no longer supported */ ++/* #define WLC_SET_FRAG 16 */ /* no longer supported */ ++/* #define WLC_GET_RTS 17 */ /* no longer supported */ ++/* #define WLC_SET_RTS 18 */ /* no longer supported */ ++#define WLC_GET_INFRA 19 ++#define WLC_SET_INFRA 20 ++#define WLC_GET_AUTH 21 ++#define WLC_SET_AUTH 22 ++#define WLC_GET_BSSID 23 ++#define WLC_SET_BSSID 24 ++#define WLC_GET_SSID 25 ++#define WLC_SET_SSID 26 ++#define WLC_RESTART 27 ++#define WLC_TERMINATED 28 ++/* #define WLC_DUMP_SCB 28 */ /* no longer supported */ ++#define WLC_GET_CHANNEL 29 ++#define WLC_SET_CHANNEL 30 ++#define WLC_GET_SRL 31 ++#define WLC_SET_SRL 32 ++#define WLC_GET_LRL 33 ++#define WLC_SET_LRL 34 ++#define WLC_GET_PLCPHDR 35 ++#define WLC_SET_PLCPHDR 36 ++#define WLC_GET_RADIO 37 ++#define WLC_SET_RADIO 38 ++#define WLC_GET_PHYTYPE 39 ++#define WLC_DUMP_RATE 40 ++#define WLC_SET_RATE_PARAMS 41 ++#define WLC_GET_FIXRATE 42 ++#define WLC_SET_FIXRATE 43 ++/* #define WLC_GET_WEP 42 */ /* no longer supported */ ++/* #define WLC_SET_WEP 43 */ /* no longer supported */ ++#define WLC_GET_KEY 44 ++#define WLC_SET_KEY 45 ++#define WLC_GET_REGULATORY 46 ++#define WLC_SET_REGULATORY 47 ++#define WLC_GET_PASSIVE_SCAN 48 ++#define WLC_SET_PASSIVE_SCAN 49 ++#define WLC_SCAN 50 ++#define WLC_SCAN_RESULTS 51 ++#define WLC_DISASSOC 52 ++#define WLC_REASSOC 53 ++#define WLC_GET_ROAM_TRIGGER 54 ++#define WLC_SET_ROAM_TRIGGER 55 ++#define WLC_GET_ROAM_DELTA 56 ++#define WLC_SET_ROAM_DELTA 57 ++#define WLC_GET_ROAM_SCAN_PERIOD 58 ++#define WLC_SET_ROAM_SCAN_PERIOD 59 ++#define WLC_EVM 60 /* diag */ ++#define WLC_GET_TXANT 61 ++#define WLC_SET_TXANT 62 ++#define WLC_GET_ANTDIV 63 ++#define WLC_SET_ANTDIV 64 ++/* #define WLC_GET_TXPWR 65 */ /* no longer supported */ ++/* #define WLC_SET_TXPWR 66 */ /* no longer supported */ ++#define WLC_GET_CLOSED 67 ++#define WLC_SET_CLOSED 68 ++#define WLC_GET_MACLIST 69 ++#define WLC_SET_MACLIST 70 ++#define WLC_GET_RATESET 71 ++#define WLC_SET_RATESET 72 ++/* #define WLC_GET_LOCALE 73 */ /* no longer supported */ ++#define WLC_LONGTRAIN 74 ++#define WLC_GET_BCNPRD 75 ++#define WLC_SET_BCNPRD 76 ++#define WLC_GET_DTIMPRD 77 ++#define WLC_SET_DTIMPRD 78 ++#define WLC_GET_SROM 79 ++#define WLC_SET_SROM 80 ++#define WLC_GET_WEP_RESTRICT 81 ++#define WLC_SET_WEP_RESTRICT 82 ++#define WLC_GET_COUNTRY 83 ++#define WLC_SET_COUNTRY 84 ++#define WLC_GET_PM 85 ++#define WLC_SET_PM 86 ++#define WLC_GET_WAKE 87 ++#define WLC_SET_WAKE 88 ++/* #define WLC_GET_D11CNTS 89 */ /* -> "counters" iovar */ ++#define WLC_GET_FORCELINK 90 /* ndis only */ ++#define WLC_SET_FORCELINK 91 /* ndis only */ ++#define WLC_FREQ_ACCURACY 92 /* diag */ ++#define WLC_CARRIER_SUPPRESS 93 /* diag */ ++#define WLC_GET_PHYREG 94 ++#define WLC_SET_PHYREG 95 ++#define WLC_GET_RADIOREG 96 ++#define WLC_SET_RADIOREG 97 ++#define WLC_GET_REVINFO 98 ++#define WLC_GET_UCANTDIV 99 ++#define WLC_SET_UCANTDIV 100 ++#define WLC_R_REG 101 ++#define WLC_W_REG 102 ++/* #define WLC_DIAG_LOOPBACK 103 old tray diag */ ++/* #define WLC_RESET_D11CNTS 104 */ /* -> "reset_d11cnts" iovar */ ++#define WLC_GET_MACMODE 105 ++#define WLC_SET_MACMODE 106 ++#define WLC_GET_MONITOR 107 ++#define WLC_SET_MONITOR 108 ++#define WLC_GET_GMODE 109 ++#define WLC_SET_GMODE 110 ++#define WLC_GET_LEGACY_ERP 111 ++#define WLC_SET_LEGACY_ERP 112 ++#define WLC_GET_RX_ANT 113 ++#define WLC_GET_CURR_RATESET 114 /* current rateset */ ++#define WLC_GET_SCANSUPPRESS 115 ++#define WLC_SET_SCANSUPPRESS 116 ++#define WLC_GET_AP 117 ++#define WLC_SET_AP 118 ++#define WLC_GET_EAP_RESTRICT 119 ++#define WLC_SET_EAP_RESTRICT 120 ++#define WLC_SCB_AUTHORIZE 121 ++#define WLC_SCB_DEAUTHORIZE 122 ++#define WLC_GET_WDSLIST 123 ++#define WLC_SET_WDSLIST 124 ++#define WLC_GET_ATIM 125 ++#define WLC_SET_ATIM 126 ++#define WLC_GET_RSSI 127 ++#define WLC_GET_PHYANTDIV 128 ++#define WLC_SET_PHYANTDIV 129 ++#define WLC_AP_RX_ONLY 130 ++#define WLC_GET_TX_PATH_PWR 131 ++#define WLC_SET_TX_PATH_PWR 132 ++#define WLC_GET_WSEC 133 ++#define WLC_SET_WSEC 134 ++#define WLC_GET_PHY_NOISE 135 ++#define WLC_GET_BSS_INFO 136 ++#define WLC_GET_PKTCNTS 137 ++#define WLC_GET_LAZYWDS 138 ++#define WLC_SET_LAZYWDS 139 ++#define WLC_GET_BANDLIST 140 ++#define WLC_GET_BAND 141 ++#define WLC_SET_BAND 142 ++#define WLC_SCB_DEAUTHENTICATE 143 ++#define WLC_GET_SHORTSLOT 144 ++#define WLC_GET_SHORTSLOT_OVERRIDE 145 ++#define WLC_SET_SHORTSLOT_OVERRIDE 146 ++#define WLC_GET_SHORTSLOT_RESTRICT 147 ++#define WLC_SET_SHORTSLOT_RESTRICT 148 ++#define WLC_GET_GMODE_PROTECTION 149 ++#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 ++#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 ++#define WLC_UPGRADE 152 ++/* #define WLC_GET_MRATE 153 */ /* no longer supported */ ++/* #define WLC_SET_MRATE 154 */ /* no longer supported */ ++#define WLC_GET_IGNORE_BCNS 155 ++#define WLC_SET_IGNORE_BCNS 156 ++#define WLC_GET_SCB_TIMEOUT 157 ++#define WLC_SET_SCB_TIMEOUT 158 ++#define WLC_GET_ASSOCLIST 159 ++#define WLC_GET_CLK 160 ++#define WLC_SET_CLK 161 ++#define WLC_GET_UP 162 ++#define WLC_OUT 163 ++#define WLC_GET_WPA_AUTH 164 ++#define WLC_SET_WPA_AUTH 165 ++#define WLC_GET_UCFLAGS 166 ++#define WLC_SET_UCFLAGS 167 ++#define WLC_GET_PWRIDX 168 ++#define WLC_SET_PWRIDX 169 ++#define WLC_GET_TSSI 170 ++#define WLC_GET_SUP_RATESET_OVERRIDE 171 ++#define WLC_SET_SUP_RATESET_OVERRIDE 172 ++/* #define WLC_SET_FAST_TIMER 173 */ /* no longer supported */ ++/* #define WLC_GET_FAST_TIMER 174 */ /* no longer supported */ ++/* #define WLC_SET_SLOW_TIMER 175 */ /* no longer supported */ ++/* #define WLC_GET_SLOW_TIMER 176 */ /* no longer supported */ ++/* #define WLC_DUMP_PHYREGS 177 */ /* no longer supported */ ++#define WLC_GET_PROTECTION_CONTROL 178 ++#define WLC_SET_PROTECTION_CONTROL 179 ++#define WLC_GET_PHYLIST 180 ++#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */ ++#define WLC_DECRYPT_STATUS 182 /* ndis only */ ++#define WLC_GET_KEY_SEQ 183 ++#define WLC_GET_SCAN_CHANNEL_TIME 184 ++#define WLC_SET_SCAN_CHANNEL_TIME 185 ++#define WLC_GET_SCAN_UNASSOC_TIME 186 ++#define WLC_SET_SCAN_UNASSOC_TIME 187 ++#define WLC_GET_SCAN_HOME_TIME 188 ++#define WLC_SET_SCAN_HOME_TIME 189 ++#define WLC_GET_SCAN_NPROBES 190 ++#define WLC_SET_SCAN_NPROBES 191 ++#define WLC_GET_PRB_RESP_TIMEOUT 192 ++#define WLC_SET_PRB_RESP_TIMEOUT 193 ++#define WLC_GET_ATTEN 194 ++#define WLC_SET_ATTEN 195 ++#define WLC_GET_SHMEM 196 /* diag */ ++#define WLC_SET_SHMEM 197 /* diag */ ++/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */ ++/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */ ++#define WLC_SET_WSEC_TEST 200 ++#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 ++#define WLC_TKIP_COUNTERMEASURES 202 ++#define WLC_GET_PIOMODE 203 ++#define WLC_SET_PIOMODE 204 ++#define WLC_SET_ASSOC_PREFER 205 ++#define WLC_GET_ASSOC_PREFER 206 ++#define WLC_SET_ROAM_PREFER 207 ++#define WLC_GET_ROAM_PREFER 208 ++#define WLC_SET_LED 209 ++#define WLC_GET_LED 210 ++#define WLC_GET_INTERFERENCE_MODE 211 ++#define WLC_SET_INTERFERENCE_MODE 212 ++#define WLC_GET_CHANNEL_QA 213 ++#define WLC_START_CHANNEL_QA 214 ++#define WLC_GET_CHANNEL_SEL 215 ++#define WLC_START_CHANNEL_SEL 216 ++#define WLC_GET_VALID_CHANNELS 217 ++#define WLC_GET_FAKEFRAG 218 ++#define WLC_SET_FAKEFRAG 219 ++#define WLC_GET_PWROUT_PERCENTAGE 220 ++#define WLC_SET_PWROUT_PERCENTAGE 221 ++#define WLC_SET_BAD_FRAME_PREEMPT 222 ++#define WLC_GET_BAD_FRAME_PREEMPT 223 ++#define WLC_SET_LEAP_LIST 224 ++#define WLC_GET_LEAP_LIST 225 ++#define WLC_GET_CWMIN 226 ++#define WLC_SET_CWMIN 227 ++#define WLC_GET_CWMAX 228 ++#define WLC_SET_CWMAX 229 ++#define WLC_GET_WET 230 ++#define WLC_SET_WET 231 ++#define WLC_GET_PUB 232 ++/* #define WLC_SET_GLACIAL_TIMER 233 */ /* no longer supported */ ++/* #define WLC_GET_GLACIAL_TIMER 234 */ /* no longer supported */ ++#define WLC_GET_KEY_PRIMARY 235 ++#define WLC_SET_KEY_PRIMARY 236 ++/* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */ ++#define WLC_GET_ACI_ARGS 238 ++#define WLC_SET_ACI_ARGS 239 ++#define WLC_UNSET_CALLBACK 240 ++#define WLC_SET_CALLBACK 241 ++#define WLC_GET_RADAR 242 ++#define WLC_SET_RADAR 243 ++#define WLC_SET_SPECT_MANAGMENT 244 ++#define WLC_GET_SPECT_MANAGMENT 245 ++#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */ ++#define WLC_WDS_GET_WPA_SUP 247 ++#define WLC_SET_CS_SCAN_TIMER 248 ++#define WLC_GET_CS_SCAN_TIMER 249 ++#define WLC_MEASURE_REQUEST 250 ++#define WLC_INIT 251 ++#define WLC_SEND_QUIET 252 ++#define WLC_KEEPALIVE 253 ++#define WLC_SEND_PWR_CONSTRAINT 254 ++#define WLC_UPGRADE_STATUS 255 ++#define WLC_CURRENT_PWR 256 ++#define WLC_GET_SCAN_PASSIVE_TIME 257 ++#define WLC_SET_SCAN_PASSIVE_TIME 258 ++#define WLC_LEGACY_LINK_BEHAVIOR 259 ++#define WLC_GET_CHANNELS_IN_COUNTRY 260 ++#define WLC_GET_COUNTRY_LIST 261 ++#define WLC_GET_VAR 262 /* get value of named variable */ ++#define WLC_SET_VAR 263 /* set named variable to value */ ++#define WLC_NVRAM_GET 264 /* deprecated */ ++#define WLC_NVRAM_SET 265 ++#define WLC_NVRAM_DUMP 266 ++#define WLC_REBOOT 267 ++#define WLC_SET_WSEC_PMK 268 ++#define WLC_GET_AUTH_MODE 269 ++#define WLC_SET_AUTH_MODE 270 ++#define WLC_GET_WAKEENTRY 271 ++#define WLC_SET_WAKEENTRY 272 ++#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */ ++#define WLC_NVOTPW 274 ++#define WLC_OTPW 275 ++#define WLC_IOV_BLOCK_GET 276 ++#define WLC_IOV_MODULES_GET 277 ++#define WLC_SOFT_RESET 278 ++#define WLC_GET_ALLOW_MODE 279 ++#define WLC_SET_ALLOW_MODE 280 ++#define WLC_GET_DESIRED_BSSID 281 ++#define WLC_SET_DESIRED_BSSID 282 ++#define WLC_DISASSOC_MYAP 283 ++#define WLC_GET_NBANDS 284 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES 285 /* for Dongle EXT_STA support */ ++#define WLC_GET_WLC_BSS_INFO 286 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_INFO 287 /* for Dongle EXT_STA support */ ++#define WLC_GET_OID_PHY 288 /* for Dongle EXT_STA support */ ++#define WLC_SET_OID_PHY 289 /* for Dongle EXT_STA support */ ++#define WLC_SET_ASSOC_TIME 290 /* for Dongle EXT_STA support */ ++#define WLC_GET_DESIRED_SSID 291 /* for Dongle EXT_STA support */ ++#define WLC_GET_CHANSPEC 292 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_STATE 293 /* for Dongle EXT_STA support */ ++#define WLC_SET_PHY_STATE 294 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCAN_PENDING 295 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCANREQ_PENDING 296 /* for Dongle EXT_STA support */ ++#define WLC_GET_PREV_ROAM_REASON 297 /* for Dongle EXT_STA support */ ++#define WLC_SET_PREV_ROAM_REASON 298 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES_PI 299 /* for Dongle EXT_STA support */ ++#define WLC_GET_PHY_STATE 300 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA_RSN 301 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA2_RSN 302 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_BCN_TS 303 /* for Dongle EXT_STA support */ ++#define WLC_GET_INT_DISASSOC 304 /* for Dongle EXT_STA support */ ++#define WLC_SET_NUM_PEERS 305 /* for Dongle EXT_STA support */ ++#define WLC_GET_NUM_BSS 306 /* for Dongle EXT_STA support */ ++#define WLC_PHY_SAMPLE_COLLECT 307 /* phy sample collect mode */ ++/* #define WLC_UM_PRIV 308 */ /* Deprecated: usermode driver */ ++#define WLC_GET_CMD 309 ++/* #define WLC_LAST 310 */ /* Never used - can be reused */ ++#define WLC_SET_INTERFERENCE_OVERRIDE_MODE 311 /* set inter mode override */ ++#define WLC_GET_INTERFERENCE_OVERRIDE_MODE 312 /* get inter mode override */ ++/* #define WLC_GET_WAI_RESTRICT 313 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_RESTRICT 314 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */ ++#define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */ ++#define WLC_GET_NAT_STATE 317 ++#define WLC_LAST 318 ++ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* vx wlc ioctl's offset */ ++#define CMN_IOCTL_OFF 0x180 ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++ ++/* begin 0x1f values beyond the start of the ET driver range. */ ++#define WL_OID_BASE 0xFFE41420 ++ ++/* NDIS overrides */ ++#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) ++#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK) ++#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK) ++#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH) ++#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS) ++#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR) ++#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) ++ ++/* EXT_STA Dongle suuport */ ++#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC) ++#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS) ++#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY) ++#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY) ++#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME) ++#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID) ++#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE) ++#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING) ++#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING) ++#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON) ++#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON) ++#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE) ++#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC) ++#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS) ++#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS) ++ ++/* NAT filter driver support */ ++#define OID_NAT_SET_CONFIG (WL_OID_BASE + WLC_SET_NAT_CONFIG) ++#define OID_NAT_GET_STATE (WL_OID_BASE + WLC_GET_NAT_STATE) ++ ++#define WL_DECRYPT_STATUS_SUCCESS 1 ++#define WL_DECRYPT_STATUS_FAILURE 2 ++#define WL_DECRYPT_STATUS_UNKNOWN 3 ++ ++/* allows user-mode app to poll the status of USB image upgrade */ ++#define WLC_UPGRADE_SUCCESS 0 ++#define WLC_UPGRADE_PENDING 1 ++ ++#ifdef CONFIG_USBRNDIS_RETAIL ++/* struct passed in for WLC_NDCONFIG_ITEM */ ++typedef struct { ++ char *name; ++ void *param; ++} ndconfig_item_t; ++#endif ++ ++ ++/* WLC_GET_AUTH, WLC_SET_AUTH values */ ++#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ ++#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ ++ ++/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ ++#define WL_RADIO_SW_DISABLE (1<<0) ++#define WL_RADIO_HW_DISABLE (1<<1) ++#define WL_RADIO_MPC_DISABLE (1<<2) ++#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ ++ ++#define WL_SPURAVOID_OFF 0 ++#define WL_SPURAVOID_ON1 1 ++#define WL_SPURAVOID_ON2 2 ++ ++/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ ++#define WL_TXPWR_OVERRIDE (1U<<31) ++#define WL_TXPWR_NEG (1U<<30) ++ ++#define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ ++ ++#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */ ++#define WL_PHY_PAVAR_VER 1 /* pavars version */ ++typedef struct wl_pavars2 { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* len of this structure */ ++ uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */ ++ uint16 phy_type; /* phy type */ ++ uint16 bandrange; ++ uint16 chain; ++ uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */ ++} wl_pavars2_t; ++ ++typedef struct wl_po { ++ uint16 phy_type; /* Phy type */ ++ uint16 band; ++ uint16 cckpo; ++ uint32 ofdmpo; ++ uint16 mcspo[8]; ++} wl_po_t; ++ ++/* a large TX Power as an init value to factor out of MIN() calculations, ++ * keep low enough to fit in an int8, units are .25 dBm ++ */ ++#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++/* "diag" iovar argument and error code */ ++#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */ ++#define WL_DIAG_LOOPBACK 2 /* d11 loopback data test */ ++#define WL_DIAG_MEMORY 3 /* d11 memory test */ ++#define WL_DIAG_LED 4 /* LED test */ ++#define WL_DIAG_REG 5 /* d11/phy register test */ ++#define WL_DIAG_SROM 6 /* srom read/crc test */ ++#define WL_DIAG_DMA 7 /* DMA test */ ++#define WL_DIAG_LOOPBACK_EXT 8 /* enhenced d11 loopback data test */ ++ ++#define WL_DIAGERR_SUCCESS 0 ++#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */ ++#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */ ++#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */ ++#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */ ++#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */ ++#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */ ++#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */ ++#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */ ++#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */ ++#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */ ++ ++#define WL_DIAGERR_MEMORY_TIMEOUT 11 /* d11 memory test didn't finish in time */ ++#define WL_DIAGERR_MEMORY_BADPATTERN 12 /* d11 memory test result in bad pattern */ ++ ++/* band types */ ++#define WLC_BAND_AUTO 0 /* auto-select */ ++#define WLC_BAND_5G 1 /* 5 Ghz */ ++#define WLC_BAND_2G 2 /* 2.4 Ghz */ ++#define WLC_BAND_ALL 3 /* all bands */ ++ ++/* band range returned by band_range iovar */ ++#define WL_CHAN_FREQ_RANGE_2G 0 ++#define WL_CHAN_FREQ_RANGE_5GL 1 ++#define WL_CHAN_FREQ_RANGE_5GM 2 ++#define WL_CHAN_FREQ_RANGE_5GH 3 ++ ++#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 ++#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 ++#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 ++#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 ++#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 ++ ++#define WL_CHAN_FREQ_RANGE_5G_BAND0 1 ++#define WL_CHAN_FREQ_RANGE_5G_BAND1 2 ++#define WL_CHAN_FREQ_RANGE_5G_BAND2 3 ++#define WL_CHAN_FREQ_RANGE_5G_BAND3 4 ++ ++#define WL_CHAN_FREQ_RANGE_5G_4BAND 5 ++ ++/* phy types (returned by WLC_GET_PHYTPE) */ ++#define WLC_PHY_TYPE_A 0 ++#define WLC_PHY_TYPE_B 1 ++#define WLC_PHY_TYPE_G 2 ++#define WLC_PHY_TYPE_N 4 ++#define WLC_PHY_TYPE_LP 5 ++#define WLC_PHY_TYPE_SSN 6 ++#define WLC_PHY_TYPE_HT 7 ++#define WLC_PHY_TYPE_LCN 8 ++#define WLC_PHY_TYPE_LCN40 10 ++#define WLC_PHY_TYPE_AC 11 ++#define WLC_PHY_TYPE_NULL 0xf ++ ++/* MAC list modes */ ++#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */ ++#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */ ++#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */ ++ ++/* ++ * 54g modes (basic bits may still be overridden) ++ * ++ * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11 ++ * Preamble: Long ++ * Shortslot: Off ++ * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: Auto ++ * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 ++ * Extended Rateset: 6b, 9, 12b, 48 ++ * Preamble: Short required ++ * Shortslot: Auto ++ * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: On ++ * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 ++ * Preamble: Short required ++ * Shortslot: On and required ++ * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b ++ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 ++ * Preamble: Long ++ * Shortslot: Auto ++ */ ++#define GMODE_LEGACY_B 0 ++#define GMODE_AUTO 1 ++#define GMODE_ONLY 2 ++#define GMODE_B_DEFERRED 3 ++#define GMODE_PERFORMANCE 4 ++#define GMODE_LRS 5 ++#define GMODE_MAX 6 ++ ++/* values for PLCPHdr_override */ ++#define WLC_PLCP_AUTO -1 ++#define WLC_PLCP_SHORT 0 ++#define WLC_PLCP_LONG 1 ++ ++/* values for g_protection_override and n_protection_override */ ++#define WLC_PROTECTION_AUTO -1 ++#define WLC_PROTECTION_OFF 0 ++#define WLC_PROTECTION_ON 1 ++#define WLC_PROTECTION_MMHDR_ONLY 2 ++#define WLC_PROTECTION_CTS_ONLY 3 ++ ++/* values for g_protection_control and n_protection_control */ ++#define WLC_PROTECTION_CTL_OFF 0 ++#define WLC_PROTECTION_CTL_LOCAL 1 ++#define WLC_PROTECTION_CTL_OVERLAP 2 ++ ++/* values for n_protection */ ++#define WLC_N_PROTECTION_OFF 0 ++#define WLC_N_PROTECTION_OPTIONAL 1 ++#define WLC_N_PROTECTION_20IN40 2 ++#define WLC_N_PROTECTION_MIXEDMODE 3 ++ ++/* values for n_preamble_type */ ++#define WLC_N_PREAMBLE_MIXEDMODE 0 ++#define WLC_N_PREAMBLE_GF 1 ++#define WLC_N_PREAMBLE_GF_BRCM 2 ++ ++/* values for band specific 40MHz capabilities (deprecated) */ ++#define WLC_N_BW_20ALL 0 ++#define WLC_N_BW_40ALL 1 ++#define WLC_N_BW_20IN2G_40IN5G 2 ++ ++#define WLC_BW_20MHZ_BIT (1<<0) ++#define WLC_BW_40MHZ_BIT (1<<1) ++#define WLC_BW_80MHZ_BIT (1<<2) ++ ++/* Bandwidth capabilities */ ++#define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_UNRESTRICTED 0xFF ++ ++#define WL_BW_CAP_20MHZ(bw_cap) (((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_40MHZ(bw_cap) (((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_80MHZ(bw_cap) (((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE) ++ ++/* values to force tx/rx chain */ ++#define WLC_N_TXRX_CHAIN0 0 ++#define WLC_N_TXRX_CHAIN1 1 ++ ++/* bitflags for SGI support (sgi_rx iovar) */ ++#define WLC_N_SGI_20 0x01 ++#define WLC_N_SGI_40 0x02 ++ ++/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ ++#define WLC_SGI_ALL 0x02 ++ ++/* Values for PM */ ++#define PM_OFF 0 ++#define PM_MAX 1 ++#define PM_FAST 2 ++#define PM_FORCE_OFF 3 /* use this bit to force PM off even bt is active */ ++ ++#define LISTEN_INTERVAL 10 ++/* interference mitigation options */ ++#define INTERFERE_OVRRIDE_OFF -1 /* interference override off */ ++#define INTERFERE_NONE 0 /* off */ ++#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */ ++#define WLAN_MANUAL 2 /* ACI: no auto detection */ ++#define WLAN_AUTO 3 /* ACI: auto detect */ ++#define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */ ++#define AUTO_ACTIVE (1 << 7) /* Auto is currently active */ ++ ++typedef struct wl_aci_args { ++ int enter_aci_thresh; /* Trigger level to start detecting ACI */ ++ int exit_aci_thresh; /* Trigger level to exit ACI mode */ ++ int usec_spin; /* microsecs to delay between rssi samples */ ++ int glitch_delay; /* interval between ACI scans when glitch count is consistently high */ ++ uint16 nphy_adcpwr_enter_thresh; /* ADC power to enter ACI mitigation mode */ ++ uint16 nphy_adcpwr_exit_thresh; /* ADC power to exit ACI mitigation mode */ ++ uint16 nphy_repeat_ctr; /* Number of tries per channel to compute power */ ++ uint16 nphy_num_samples; /* Number of samples to compute power on one channel */ ++ uint16 nphy_undetect_window_sz; /* num of undetects to exit ACI Mitigation mode */ ++ uint16 nphy_b_energy_lo_aci; /* low ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_md_aci; /* mid ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_hi_aci; /* high ACI power energy threshold for bphy */ ++ uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */ ++ uint16 nphy_noise_noassoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_glitch_th_up; ++ uint16 nphy_noise_assoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_aci_glitch_th_up; ++ uint16 nphy_noise_assoc_aci_glitch_th_dn; ++ uint16 nphy_noise_assoc_enter_th; ++ uint16 nphy_noise_noassoc_enter_th; ++ uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th; ++ uint16 nphy_noise_noassoc_crsidx_incr; ++ uint16 nphy_noise_assoc_crsidx_incr; ++ uint16 nphy_noise_crsidx_decr; ++} wl_aci_args_t; ++ ++#define TRIGGER_NOW 0 ++#define TRIGGER_CRS 0x01 ++#define TRIGGER_CRSDEASSERT 0x02 ++#define TRIGGER_GOODFCS 0x04 ++#define TRIGGER_BADFCS 0x08 ++#define TRIGGER_BADPLCP 0x10 ++#define TRIGGER_CRSGLITCH 0x20 ++#define WL_ACI_ARGS_LEGACY_LENGTH 16 /* bytes of pre NPHY aci args */ ++#define WL_SAMPLECOLLECT_T_VERSION 2 /* version of wl_samplecollect_args_t struct */ ++typedef struct wl_samplecollect_args { ++ /* version 0 fields */ ++ uint8 coll_us; ++ int cores; ++ /* add'l version 1 fields */ ++ uint16 version; /* see definition of WL_SAMPLECOLLECT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ int8 trigger; ++ uint16 timeout; ++ uint16 mode; ++ uint32 pre_dur; ++ uint32 post_dur; ++ uint8 gpio_sel; ++ bool downsamp; ++ bool be_deaf; ++ bool agc; /* loop from init gain and going down */ ++ bool filter; /* override high pass corners to lowest */ ++ /* add'l version 2 fields */ ++ uint8 trigger_state; ++ uint8 module_sel1; ++ uint8 module_sel2; ++ uint16 nsamps; ++} wl_samplecollect_args_t; ++ ++#define WL_SAMPLEDATA_HEADER_TYPE 1 ++#define WL_SAMPLEDATA_HEADER_SIZE 80 /* sample collect header size (bytes) */ ++#define WL_SAMPLEDATA_TYPE 2 ++#define WL_SAMPLEDATA_SEQ 0xff /* sequence # */ ++#define WL_SAMPLEDATA_MORE_DATA 0x100 /* more data mask */ ++#define WL_SAMPLEDATA_T_VERSION 1 /* version of wl_samplecollect_args_t struct */ ++/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */ ++#define WL_SAMPLEDATA_T_VERSION_SPEC_AN 2 ++ ++typedef struct wl_sampledata { ++ uint16 version; /* structure version */ ++ uint16 size; /* size of structure */ ++ uint16 tag; /* Header/Data */ ++ uint16 length; /* data length */ ++ uint32 flag; /* bit def */ ++} wl_sampledata_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* wl_radar_args_t */ ++typedef struct { ++ int npulses; /* required number of pulses at n * t_int */ ++ int ncontig; /* required number of pulses at t_int */ ++ int min_pw; /* minimum pulse width (20 MHz clocks) */ ++ int max_pw; /* maximum pulse width (20 MHz clocks) */ ++ uint16 thresh0; /* Radar detection, thresh 0 */ ++ uint16 thresh1; /* Radar detection, thresh 1 */ ++ uint16 blank; /* Radar detection, blank control */ ++ uint16 fmdemodcfg; /* Radar detection, fmdemod config */ ++ int npulses_lp; /* Radar detection, minimum long pulses */ ++ int min_pw_lp; /* Minimum pulsewidth for long pulses */ ++ int max_pw_lp; /* Maximum pulsewidth for long pulses */ ++ int min_fm_lp; /* Minimum fm for long pulses */ ++ int max_span_lp; /* Maximum deltat for long pulses */ ++ int min_deltat; /* Minimum spacing between pulses */ ++ int max_deltat; /* Maximum spacing between pulses */ ++ uint16 autocorr; /* Radar detection, autocorr on or off */ ++ uint16 st_level_time; /* Radar detection, start_timing level */ ++ uint16 t2_min; /* minimum clocks needed to remain in state 2 */ ++ uint32 version; /* version */ ++ uint32 fra_pulse_err; /* sample error margin for detecting French radar pulsed */ ++ int npulses_fra; /* Radar detection, minimum French pulses set */ ++ int npulses_stg2; /* Radar detection, minimum staggered-2 pulses set */ ++ int npulses_stg3; /* Radar detection, minimum staggered-3 pulses set */ ++ uint16 percal_mask; /* defines which period cal is masked from radar detection */ ++ int quant; /* quantization resolution to pulse positions */ ++ uint32 min_burst_intv_lp; /* minimum burst to burst interval for bin3 radar */ ++ uint32 max_burst_intv_lp; /* maximum burst to burst interval for bin3 radar */ ++ int nskip_rst_lp; /* number of skipped pulses before resetting lp buffer */ ++ int max_pw_tol; /* maximum tollerance allowed in detected pulse width for radar detection */ ++ uint16 feature_mask; /* 16-bit mask to specify enabled features */ ++} wl_radar_args_t; ++ ++#define WL_RADAR_ARGS_VERSION 2 ++ ++typedef struct { ++ uint32 version; /* version */ ++ uint16 thresh0_20_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh1_20_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh0_40_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh1_40_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh0_80_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh1_80_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh0_160_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh1_160_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh0_20_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh1_20_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh0_40_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh1_40_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh0_80_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh1_80_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh0_160_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */ ++ uint16 thresh1_160_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */ ++} wl_radar_thr_t; ++ ++#define WL_RADAR_THR_VERSION 2 ++#define WL_THRESHOLD_LO_BAND 70 /* range from 5250MHz - 5350MHz */ ++ ++/* radar iovar SET defines */ ++#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */ ++#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */ ++#define WL_RADAR_SIMULATED 2 /* force radar detector to declare ++ * detection once ++ */ ++#define WL_RSSI_ANT_VERSION 1 /* current version of wl_rssi_ant_t */ ++#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ ++#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ ++#define WL_ANT_IDX_1 0 /* antenna index 1 */ ++#define WL_ANT_IDX_2 1 /* antenna index 2 */ ++ ++#ifndef WL_RSSI_ANT_MAX ++#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ ++#elif WL_RSSI_ANT_MAX != 4 ++#error "WL_RSSI_ANT_MAX does not match" ++#endif ++ ++/* RSSI per antenna */ ++typedef struct { ++ uint32 version; /* version field */ ++ uint32 count; /* number of valid antenna rssi */ ++ int8 rssi_ant[WL_RSSI_ANT_MAX]; /* rssi per antenna */ ++} wl_rssi_ant_t; ++ ++/* dfs_status iovar-related defines */ ++ ++/* cac - channel availability check, ++ * ism - in-service monitoring ++ * csa - channel switching announcement ++ */ ++ ++/* cac state values */ ++#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */ ++#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */ ++#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */ ++#define WL_DFS_CACSTATE_CSA 3 /* csa */ ++#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */ ++#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */ ++#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */ ++#define WL_DFS_CACSTATES 7 /* this many states exist */ ++ ++/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */ ++typedef struct { ++ uint state; /* noted by WL_DFS_CACSTATE_XX. */ ++ uint duration; /* time spent in ms in state. */ ++ /* as dfs enters ISM state, it removes the operational channel from quiet channel ++ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared ++ */ ++ chanspec_t chanspec_cleared; ++ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */ ++ uint16 pad; ++} wl_dfs_status_t; ++ ++#define NUM_PWRCTRL_RATES 12 ++ ++typedef struct { ++ uint8 txpwr_band_max[NUM_PWRCTRL_RATES]; /* User set target */ ++ uint8 txpwr_limit[NUM_PWRCTRL_RATES]; /* reg and local power limit */ ++ uint8 txpwr_local_max; /* local max according to the AP */ ++ uint8 txpwr_local_constraint; /* local constraint according to the AP */ ++ uint8 txpwr_chan_reg_max; /* Regulatory max for this channel */ ++ uint8 txpwr_target[2][NUM_PWRCTRL_RATES]; /* Latest target for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_opo[NUM_PWRCTRL_RATES]; /* On G phy, OFDM power offset */ ++ uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; /* Max CCK power for this band (SROM) */ ++ uint8 txpwr_bphy_ofdm_max; /* Max OFDM power for this band (SROM) */ ++ uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES]; /* Max power for A band (SROM) */ ++ int8 txpwr_antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_power_legacy_t; ++ ++#define WL_TX_POWER_RATES_LEGACY 45 ++#define WL_TX_POWER_MCS20_FIRST 12 ++#define WL_TX_POWER_MCS20_NUM 16 ++#define WL_TX_POWER_MCS40_FIRST 28 ++#define WL_TX_POWER_MCS40_NUM 17 ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF ++ * chain without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */ ++ uint8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */ ++ uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */ ++ uint8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */ ++} tx_power_legacy2_t; ++ ++/* TX Power index defines */ ++#define WL_NUM_RATES_CCK 4 /* 1, 2, 5.5, 11 Mbps */ ++#define WL_NUM_RATES_OFDM 8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */ ++#define WL_NUM_RATES_MCS_1STREAM 8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */ ++#define WL_NUM_RATES_EXTRA_VHT 2 /* Additional VHT 11AC rates */ ++#define WL_NUM_RATES_VHT 10 ++#define WL_NUM_RATES_MCS32 1 ++ ++#define WLC_NUM_RATES_CCK WL_NUM_RATES_CCK ++#define WLC_NUM_RATES_OFDM WL_NUM_RATES_OFDM ++#define WLC_NUM_RATES_MCS_1_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS_2_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS32 WL_NUM_RATES_MCS32 ++#define WL_TX_POWER_CCK_NUM WL_NUM_RATES_CCK ++#define WL_TX_POWER_OFDM_NUM WL_NUM_RATES_OFDM ++#define WL_TX_POWER_MCS_1_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_2_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_32_NUM WL_NUM_RATES_MCS32 ++ ++#define WL_NUM_2x2_ELEMENTS 4 ++#define WL_NUM_3x3_ELEMENTS 6 ++ ++typedef struct txppr { ++ /* start of 20MHz tx power limits */ ++ uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40MHz tx power limits */ ++ uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in40MHz tx power limits */ ++ uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ ++ uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 80MHz tx power limits */ ++ uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in80MHz tx power limits */ ++ uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40in80MHz tx power limits */ ++ uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ ++ uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ ++} txppr_t; ++ ++/* 20MHz */ ++#define WL_TX_POWER_CCK_FIRST OFFSETOF(txppr_t, b20_1x1dsss) ++#define WL_TX_POWER_OFDM20_FIRST OFFSETOF(txppr_t, b20_1x1ofdm) ++#define WL_TX_POWER_MCS20_SISO_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++#define WL_TX_POWER_20_S1x1_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2dsss) ++#define WL_TX_POWER_OFDM20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_20_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS20_STBC_FIRST OFFSETOF(txppr_t, b20_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS20_SDM_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++#define WL_TX_POWER_20_S2x2_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3dsss) ++#define WL_TX_POWER_OFDM20_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_ofdm) ++#define WL_TX_POWER_20_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_mcs0) ++#define WL_TX_POWER_20_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3stbc_mcs0) ++#define WL_TX_POWER_20_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3sdm_mcs8) ++#define WL_TX_POWER_20_S3x3_FIRST OFFSETOF(txppr_t, b20_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20_S1X1_VHT OFFSETOF(txppr_t, b20_1x1vht) ++#define WL_TX_POWER_20_S1X2_CDD_VHT OFFSETOF(txppr_t, b20_1x2cdd_vht) ++#define WL_TX_POWER_20_S2X2_STBC_VHT OFFSETOF(txppr_t, b20_2x2stbc_vht) ++#define WL_TX_POWER_20_S2X2_VHT OFFSETOF(txppr_t, b20_2x2sdm_vht) ++#define WL_TX_POWER_20_S1X3_CDD_VHT OFFSETOF(txppr_t, b20_1x3cdd_vht) ++#define WL_TX_POWER_20_S2X3_STBC_VHT OFFSETOF(txppr_t, b20_2x3stbc_vht) ++#define WL_TX_POWER_20_S2X3_VHT OFFSETOF(txppr_t, b20_2x3sdm_vht) ++#define WL_TX_POWER_20_S3X3_VHT OFFSETOF(txppr_t, b20_3x3sdm_vht) ++ ++/* 40MHz */ ++#define WL_TX_POWER_40_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40_dummy1x1dsss) ++#define WL_TX_POWER_OFDM40_FIRST OFFSETOF(txppr_t, b40_1x1ofdm) ++#define WL_TX_POWER_MCS40_SISO_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++#define WL_TX_POWER_40_S1x1_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40_dummy1x2dsss) ++#define WL_TX_POWER_OFDM40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_40_S1x2_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS40_STBC_FIRST OFFSETOF(txppr_t, b40_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS40_SDM_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++#define WL_TX_POWER_40_S2x2_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_dummy1x3dsss) ++#define WL_TX_POWER_OFDM40_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_ofdm) ++#define WL_TX_POWER_40_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_mcs0) ++#define WL_TX_POWER_40_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3stbc_mcs0) ++#define WL_TX_POWER_40_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3sdm_mcs8) ++#define WL_TX_POWER_40_S3x3_FIRST OFFSETOF(txppr_t, b40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40_S1X1_VHT OFFSETOF(txppr_t, b40_1x1vht) ++#define WL_TX_POWER_40_S1X2_CDD_VHT OFFSETOF(txppr_t, b40_1x2cdd_vht) ++#define WL_TX_POWER_40_S2X2_STBC_VHT OFFSETOF(txppr_t, b40_2x2stbc_vht) ++#define WL_TX_POWER_40_S2X2_VHT OFFSETOF(txppr_t, b40_2x2sdm_vht) ++#define WL_TX_POWER_40_S1X3_CDD_VHT OFFSETOF(txppr_t, b40_1x3cdd_vht) ++#define WL_TX_POWER_40_S2X3_STBC_VHT OFFSETOF(txppr_t, b40_2x3stbc_vht) ++#define WL_TX_POWER_40_S2X3_VHT OFFSETOF(txppr_t, b40_2x3sdm_vht) ++#define WL_TX_POWER_40_S3X3_VHT OFFSETOF(txppr_t, b40_3x3sdm_vht) ++ ++/* 20 in 40MHz */ ++#define WL_TX_POWER_20UL_CCK_FIRST OFFSETOF(txppr_t, b20in40_1x1dsss) ++#define WL_TX_POWER_20UL_OFDM_FIRST OFFSETOF(txppr_t, b20in40_1x1ofdm) ++#define WL_TX_POWER_20UL_S1x1_FIRST OFFSETOF(txppr_t, b20in40_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3sdm_mcs8) ++#define WL_TX_POWER_20UL_S3x3_FIRST OFFSETOF(txppr_t, b20in40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UL_S1X1_VHT OFFSETOF(txppr_t, b20in40_1x1vht) ++#define WL_TX_POWER_20UL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in40_1x2cdd_vht) ++#define WL_TX_POWER_20UL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in40_2x2stbc_vht) ++#define WL_TX_POWER_20UL_S2X2_VHT OFFSETOF(txppr_t, b20in40_2x2sdm_vht) ++#define WL_TX_POWER_20UL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in40_1x3cdd_vht) ++#define WL_TX_POWER_20UL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in40_2x3stbc_vht) ++#define WL_TX_POWER_20UL_S2X3_VHT OFFSETOF(txppr_t, b20in40_2x3sdm_vht) ++#define WL_TX_POWER_20UL_S3X3_VHT OFFSETOF(txppr_t, b20in40_3x3sdm_vht) ++ ++/* 80MHz */ ++#define WL_TX_POWER_80_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b80_dummy1x1dsss) ++#define WL_TX_POWER_OFDM80_FIRST OFFSETOF(txppr_t, b80_1x1ofdm) ++#define WL_TX_POWER_MCS80_SISO_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++#define WL_TX_POWER_80_S1x1_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b80_dummy1x2dsss) ++#define WL_TX_POWER_OFDM80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_80_S1x2_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS80_STBC_FIRST OFFSETOF(txppr_t, b80_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS80_SDM_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++#define WL_TX_POWER_80_S2x2_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_dummy1x3dsss) ++#define WL_TX_POWER_OFDM80_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_ofdm) ++#define WL_TX_POWER_80_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_mcs0) ++#define WL_TX_POWER_80_STBC_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3stbc_mcs0) ++#define WL_TX_POWER_80_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3sdm_mcs8) ++#define WL_TX_POWER_80_S3x3_FIRST OFFSETOF(txppr_t, b80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_80_S1X1_VHT OFFSETOF(txppr_t, b80_1x1vht) ++#define WL_TX_POWER_80_S1X2_CDD_VHT OFFSETOF(txppr_t, b80_1x2cdd_vht) ++#define WL_TX_POWER_80_S2X2_STBC_VHT OFFSETOF(txppr_t, b80_2x2stbc_vht) ++#define WL_TX_POWER_80_S2X2_VHT OFFSETOF(txppr_t, b80_2x2sdm_vht) ++#define WL_TX_POWER_80_S1X3_CDD_VHT OFFSETOF(txppr_t, b80_1x3cdd_vht) ++#define WL_TX_POWER_80_S2X3_STBC_VHT OFFSETOF(txppr_t, b80_2x3stbc_vht) ++#define WL_TX_POWER_80_S2X3_VHT OFFSETOF(txppr_t, b80_2x3sdm_vht) ++#define WL_TX_POWER_80_S3X3_VHT OFFSETOF(txppr_t, b80_3x3sdm_vht) ++ ++/* 20 in 80MHz */ ++#define WL_TX_POWER_20UUL_CCK_FIRST OFFSETOF(txppr_t, b20in80_1x1dsss) ++#define WL_TX_POWER_20UUL_OFDM_FIRST OFFSETOF(txppr_t, b20in80_1x1ofdm) ++#define WL_TX_POWER_20UUL_S1x1_FIRST OFFSETOF(txppr_t, b20in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3sdm_mcs8) ++#define WL_TX_POWER_20UUL_S3x3_FIRST OFFSETOF(txppr_t, b20in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UUL_S1X1_VHT OFFSETOF(txppr_t, b20in80_1x1vht) ++#define WL_TX_POWER_20UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in80_1x2cdd_vht) ++#define WL_TX_POWER_20UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in80_2x2stbc_vht) ++#define WL_TX_POWER_20UUL_S2X2_VHT OFFSETOF(txppr_t, b20in80_2x2sdm_vht) ++#define WL_TX_POWER_20UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in80_1x3cdd_vht) ++#define WL_TX_POWER_20UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in80_2x3stbc_vht) ++#define WL_TX_POWER_20UUL_S2X3_VHT OFFSETOF(txppr_t, b20in80_2x3sdm_vht) ++#define WL_TX_POWER_20UUL_S3X3_VHT OFFSETOF(txppr_t, b20in80_3x3sdm_vht) ++ ++/* 40 in 80MHz */ ++#define WL_TX_POWER_40UUL_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40in80_dummy1x1dsss) ++#define WL_TX_POWER_40UUL_OFDM_FIRST OFFSETOF(txppr_t, b40in80_1x1ofdm) ++#define WL_TX_POWER_40UUL_S1x1_FIRST OFFSETOF(txppr_t, b40in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40in80_dummy1x2dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x2_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_dummy1x3dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3sdm_mcs8) ++#define WL_TX_POWER_40UUL_S3x3_FIRST OFFSETOF(txppr_t, b40in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40UUL_S1X1_VHT OFFSETOF(txppr_t, b40in80_1x1vht) ++#define WL_TX_POWER_40UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b40in80_1x2cdd_vht) ++#define WL_TX_POWER_40UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b40in80_2x2stbc_vht) ++#define WL_TX_POWER_40UUL_S2X2_VHT OFFSETOF(txppr_t, b40in80_2x2sdm_vht) ++#define WL_TX_POWER_40UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b40in80_1x3cdd_vht) ++#define WL_TX_POWER_40UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b40in80_2x3stbc_vht) ++#define WL_TX_POWER_40UUL_S2X3_VHT OFFSETOF(txppr_t, b40in80_2x3sdm_vht) ++#define WL_TX_POWER_40UUL_S3X3_VHT OFFSETOF(txppr_t, b40in80_3x3sdm_vht) ++ ++#define WL_TX_POWER_MCS_32 OFFSETOF(txppr_t, mcs32) /* C_CHECK remove later */ ++ ++#define WL_TX_POWER_RATES sizeof(struct txppr) ++ ++/* sslpnphy specifics */ ++#define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST ++#define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ ++} wl_txppr_t; ++ ++#define WL_TXPPR_VERSION 0 ++#define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) ++#define TX_POWER_T_VERSION 43 ++ ++/* Defines used with channel_bandwidth for curpower */ ++#define WL_BW_20MHZ 0 ++#define WL_BW_40MHZ 1 ++#define WL_BW_80MHZ 2 ++ ++/* tx_power_t.flags bits */ ++#ifdef PPR_API ++#define WL_TX_POWER2_F_ENABLED 1 ++#define WL_TX_POWER2_F_HW 2 ++#define WL_TX_POWER2_F_MIMO 4 ++#define WL_TX_POWER2_F_SISO 8 ++#define WL_TX_POWER2_F_HT 0x10 ++#else ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++#define WL_TX_POWER_F_HT 0x10 ++#endif ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ uint8 user_limit[WL_TX_POWER_RATES]; /* User limit */ ++ int8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */ ++ int8 target[WL_TX_POWER_RATES]; /* Latest target power */ ++ int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ ++ int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ ++ int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ ++ int8 sar; /* SAR limit for display by wl executable */ ++ int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ ++ uint8 version; /* Version of the data format wlu <--> driver */ ++ uint8 display_core; /* Displayed curpower core */ ++#ifdef PPR_API ++} tx_power_new_t; ++#else ++} tx_power_t; ++#endif ++ ++typedef struct tx_inst_power { ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_inst_power_t; ++ ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ txppr_t user_limit; /* User limit */ ++ txppr_t reg_limit; /* Regulatory power limit */ ++ txppr_t board_limit; /* Max power board can support (SROM) */ ++ txppr_t target; /* Latest target power */ ++} wl_txpwr_t; ++ ++#define WL_NUM_TXCHAIN_MAX 4 ++typedef struct wl_txchain_pwr_offsets { ++ int8 offset[WL_NUM_TXCHAIN_MAX]; /* quarter dBm signed offset for each chain */ ++} wl_txchain_pwr_offsets_t; ++ ++/* 802.11h measurement types */ ++#define WLC_MEASURE_TPC 1 ++#define WLC_MEASURE_CHANNEL_BASIC 2 ++#define WLC_MEASURE_CHANNEL_CCA 3 ++#define WLC_MEASURE_CHANNEL_RPI 4 ++ ++/* regulatory enforcement levels */ ++#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */ ++#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */ ++#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */ ++#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */ ++/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE ++ * adoption is done regardless of capability spectrum_management ++ */ ++#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */ ++ ++#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ ++#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */ ++#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ ++#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ ++#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */ ++#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */ ++#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ ++ ++/* BTC mode used by "btc_mode" iovar */ ++#define WL_BTC_DISABLE 0 /* disable BT coexistence */ ++#define WL_BTC_FULLTDM 1 /* full TDM COEX */ ++#define WL_BTC_ENABLE 1 /* full TDM COEX to maintain backward compatiblity */ ++#define WL_BTC_PREMPT 2 /* full TDM COEX with preemption */ ++#define WL_BTC_LITE 3 /* light weight coex for large isolation platform */ ++#define WL_BTC_PARALLEL 4 /* BT and WLAN run in parallel with separate antenna */ ++#define WL_BTC_HYBRID 5 /* hybrid coex, only ack is allowed to transmit in BT slot */ ++#define WL_BTC_DEFAULT 8 /* set the default mode for the device */ ++#define WL_INF_BTC_DISABLE 0 ++#define WL_INF_BTC_ENABLE 1 ++#define WL_INF_BTC_AUTO 3 ++ ++/* BTC wire used by "btc_wire" iovar */ ++#define WL_BTC_DEFWIRE 0 /* use default wire setting */ ++#define WL_BTC_2WIRE 2 /* use 2-wire BTC */ ++#define WL_BTC_3WIRE 3 /* use 3-wire BTC */ ++#define WL_BTC_4WIRE 4 /* use 4-wire BTC */ ++ ++/* BTC flags: BTC configuration that can be set by host */ ++#define WL_BTC_FLAG_PREMPT (1 << 0) ++#define WL_BTC_FLAG_BT_DEF (1 << 1) ++#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2) ++#define WL_BTC_FLAG_SIM_RSP (1 << 3) ++#define WL_BTC_FLAG_PS_PROTECT (1 << 4) ++#define WL_BTC_FLAG_SIM_TX_LP (1 << 5) ++#define WL_BTC_FLAG_ECI (1 << 6) ++#define WL_BTC_FLAG_LIGHT (1 << 7) ++#define WL_BTC_FLAG_PARALLEL (1 << 8) ++#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */ ++ ++/* Message levels */ ++#define WL_ERROR_VAL 0x00000001 ++#define WL_TRACE_VAL 0x00000002 ++#define WL_PRHDRS_VAL 0x00000004 ++#define WL_PRPKT_VAL 0x00000008 ++#define WL_INFORM_VAL 0x00000010 ++#define WL_TMP_VAL 0x00000020 ++#define WL_OID_VAL 0x00000040 ++#define WL_RATE_VAL 0x00000080 ++#define WL_ASSOC_VAL 0x00000100 ++#define WL_PRUSR_VAL 0x00000200 ++#define WL_PS_VAL 0x00000400 ++#define WL_TXPWR_VAL 0x00000800 /* retired in TOT on 6/10/2009 */ ++#define WL_PORT_VAL 0x00001000 ++#define WL_DUAL_VAL 0x00002000 ++#define WL_WSEC_VAL 0x00004000 ++#define WL_WSEC_DUMP_VAL 0x00008000 ++#define WL_LOG_VAL 0x00010000 ++#define WL_NRSSI_VAL 0x00020000 /* retired in TOT on 6/10/2009 */ ++#define WL_LOFT_VAL 0x00040000 /* retired in TOT on 6/10/2009 */ ++#define WL_REGULATORY_VAL 0x00080000 ++#define WL_PHYCAL_VAL 0x00100000 /* retired in TOT on 6/10/2009 */ ++#define WL_RADAR_VAL 0x00200000 /* retired in TOT on 6/10/2009 */ ++#define WL_MPC_VAL 0x00400000 ++#define WL_APSTA_VAL 0x00800000 ++#define WL_DFS_VAL 0x01000000 ++#define WL_BA_VAL 0x02000000 /* retired in TOT on 6/14/2010 */ ++#define WL_ACI_VAL 0x04000000 ++#define WL_MBSS_VAL 0x04000000 ++#define WL_CAC_VAL 0x08000000 ++#define WL_AMSDU_VAL 0x10000000 ++#define WL_AMPDU_VAL 0x20000000 ++#define WL_FFPLD_VAL 0x40000000 ++ ++/* wl_msg_level is full. For new bits take the next one and AND with ++ * wl_msg_level2 in wl_dbg.h ++ */ ++#define WL_DPT_VAL 0x00000001 ++#define WL_SCAN_VAL 0x00000002 ++#define WL_WOWL_VAL 0x00000004 ++#define WL_COEX_VAL 0x00000008 ++#define WL_RTDC_VAL 0x00000010 ++#define WL_PROTO_VAL 0x00000020 ++#define WL_BTA_VAL 0x00000040 ++#define WL_CHANINT_VAL 0x00000080 ++#define WL_THERMAL_VAL 0x00000100 /* retired in TOT on 6/10/2009 */ ++#define WL_P2P_VAL 0x00000200 ++#define WL_ITFR_VAL 0x00000400 ++#define WL_MCHAN_VAL 0x00000800 ++#define WL_TDLS_VAL 0x00001000 ++#define WL_MCNX_VAL 0x00002000 ++#define WL_PROT_VAL 0x00004000 ++#define WL_PSTA_VAL 0x00008000 ++#define WL_TSO_VAL 0x00010000 ++/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier ++ * rather than a message-type of its own ++ */ ++#define WL_TIMESTAMP_VAL 0x80000000 ++ ++/* max # of leds supported by GPIO (gpio pin# == led index#) */ ++#define WL_LED_NUMGPIO 32 /* gpio 0-31 */ ++ ++/* led per-pin behaviors */ ++#define WL_LED_OFF 0 /* always off */ ++#define WL_LED_ON 1 /* always on */ ++#define WL_LED_ACTIVITY 2 /* activity */ ++#define WL_LED_RADIO 3 /* radio enabled */ ++#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */ ++#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */ ++#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */ ++#define WL_LED_WI1 7 ++#define WL_LED_WI2 8 ++#define WL_LED_WI3 9 ++#define WL_LED_ASSOC 10 /* associated state indicator */ ++#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */ ++#define WL_LED_ASSOCACT 12 /* on when associated; blink fast for activity */ ++#define WL_LED_WI4 13 ++#define WL_LED_WI5 14 ++#define WL_LED_BLINKSLOW 15 /* blink slow */ ++#define WL_LED_BLINKMED 16 /* blink med */ ++#define WL_LED_BLINKFAST 17 /* blink fast */ ++#define WL_LED_BLINKCUSTOM 18 /* blink custom */ ++#define WL_LED_BLINKPERIODIC 19 /* blink periodic (custom 1000ms / off 400ms) */ ++#define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ ++ /* keep on for 300 sec */ ++#define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ ++#define WL_LED_NUMBEHAVIOR 22 ++ ++/* led behavior numeric value format */ ++#define WL_LED_BEH_MASK 0x7f /* behavior mask */ ++#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */ ++ ++/* maximum channels returned by the get valid channels iovar */ ++#define WL_NUMCHANNELS 64 ++ ++/* max number of chanspecs (used by the iovar to calc. buf space) */ ++#define WL_NUMCHANSPECS 110 ++ ++/* WDS link local endpoint WPA role */ ++#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ ++#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */ ++#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */ ++ ++/* number of bytes needed to define a 128-bit mask for MAC event reporting */ ++#define WL_EVENTING_MASK_LEN 16 ++ ++/* ++ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type, ++ * a one-byte length, and a variable length value. RSSI type tuple must be present ++ * in the array. ++ * ++ * Types are defined in "join preference types" section. ++ * ++ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple ++ * and must be set to zero. ++ * ++ * Values are defined below. ++ * ++ * 1. RSSI - 2 octets ++ * offset 0: reserved ++ * offset 1: reserved ++ * ++ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below) ++ * offset 0: reserved ++ * offset 1: # of tuples ++ * offset 2: tuple 1 ++ * offset 14: tuple 2 ++ * ... ++ * offset 2 + 12 * (n - 1) octets: tuple n ++ * ++ * struct wpa_cfg_tuple { ++ * uint8 akm[DOT11_OUI_LEN+1]; akm suite ++ * uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite ++ * uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite ++ * }; ++ * ++ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY. ++ * ++ * 3. BAND - 2 octets ++ * offset 0: reserved ++ * offset 1: see "band preference" and "band types" ++ * ++ * 4. BAND RSSI - 2 octets ++ * offset 0: band types ++ * offset 1: +ve RSSI boost balue in dB ++ */ ++ ++/* join preference types */ ++#define WL_JOIN_PREF_RSSI 1 /* by RSSI */ ++#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers */ ++#define WL_JOIN_PREF_BAND 3 /* by 802.11 band */ ++#define WL_JOIN_PREF_RSSI_DELTA 4 /* by 802.11 band only if RSSI delta condition matches */ ++#define WL_JOIN_PREF_TRANS_PREF 5 /* defined by requesting AP */ ++ ++/* band preference */ ++#define WLJP_BAND_ASSOC_PREF 255 /* use what WLC_SET_ASSOC_PREFER ioctl specifies */ ++ ++/* any multicast cipher suite */ ++#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" ++ ++struct tsinfo_arg { ++ uint8 octets[3]; ++}; ++ ++#define NFIFO 6 /* # tx/rx fifopairs */ ++ ++#define WL_CNT_T_VERSION 8 /* current version of wl_cnt_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; /* obsolete */ ++ uint32 frmscons; /* obsolete */ ++ uint32 txnack; /* obsolete */ ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 dma_hang; /* count for dma hang */ ++ uint32 reinit; /* count for reinit */ ++ ++ uint32 pstatxucast; /* count of ucast frames xmitted on all psta assoc */ ++ uint32 pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ ++ uint32 pstarxucast; /* count of ucast frames received on all psta assoc */ ++ uint32 pstarxbcmc; /* count of bcmc frames received on all psta */ ++ uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ ++ ++ uint32 cso_passthrough; /* hw cso required but passthrough */ ++ uint32 cso_normal; /* hw cso hdr for normal process */ ++ uint32 chained; /* number of frames chained */ ++ uint32 chainedsz1; /* number of chain size 1 frames */ ++ uint32 unchained; /* number of frames not chained */ ++ uint32 maxchainsz; /* max chain size so far */ ++ uint32 currchainsz; /* current chain size */ ++} wl_cnt_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; ++ uint32 frmscons; ++ uint32 txnack; ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++} wl_cnt_ver_six_t; ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WL_DELTA_STATS_T_VERSION 1 /* current version of wl_delta_stats_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_DELTA_STATS_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txfail; /* tx failures */ ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++} wl_delta_stats_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */ ++ ++typedef struct { ++ uint32 packets; ++ uint32 bytes; ++} wl_traffic_stats_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_WME_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */ ++ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */ ++ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */ ++ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */ ++ ++ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */ ++ ++ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */ ++ ++} wl_wme_cnt_t; ++ ++struct wl_msglevel2 { ++ uint32 low; ++ uint32 high; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ uint16 version; /* Version for mkeep_alive */ ++ uint16 length; /* length of fixed parameters in the structure */ ++ uint32 period_msec; ++ uint16 len_bytes; ++ uint8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ uint8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#define WL_MKEEP_ALIVE_VERSION 1 ++#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) ++#define WL_MKEEP_ALIVE_PRECISION 500 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#ifdef WLBA ++ ++#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */ ++ ++/* block ack related stats */ ++typedef struct wlc_ba_cnt { ++ uint16 version; /* WLC_BA_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txpdu; /* pdus sent */ ++ uint32 txsdu; /* sdus sent */ ++ uint32 txfc; /* tx side flow controlled packets */ ++ uint32 txfci; /* tx side flow control initiated */ ++ uint32 txretrans; /* retransmitted pdus */ ++ uint32 txbatimer; /* ba resend due to timer */ ++ uint32 txdrop; /* dropped packets */ ++ uint32 txaddbareq; /* addba req sent */ ++ uint32 txaddbaresp; /* addba resp sent */ ++ uint32 txdelba; /* delba sent */ ++ uint32 txba; /* ba sent */ ++ uint32 txbar; /* bar sent */ ++ uint32 txpad[4]; /* future */ ++ ++ /* receive side counters */ ++ uint32 rxpdu; /* pdus recd */ ++ uint32 rxqed; /* pdus buffered before sending up */ ++ uint32 rxdup; /* duplicate pdus */ ++ uint32 rxnobuf; /* pdus discarded due to no buf */ ++ uint32 rxaddbareq; /* addba req recd */ ++ uint32 rxaddbaresp; /* addba resp recd */ ++ uint32 rxdelba; /* delba recd */ ++ uint32 rxba; /* ba recd */ ++ uint32 rxbar; /* bar recd */ ++ uint32 rxinvba; /* invalid ba recd */ ++ uint32 rxbaholes; /* ba recd with holes */ ++ uint32 rxunexp; /* unexpected packets */ ++ uint32 rxpad[4]; /* future */ ++} wlc_ba_cnt_t; ++#endif /* WLBA */ ++ ++/* structure for per-tid ampdu control */ ++struct ampdu_tid_control { ++ uint8 tid; /* tid */ ++ uint8 enable; /* enable/disable */ ++}; ++ ++/* structure for identifying ea/tid for sending addba/delba */ ++struct ampdu_ea_tid { ++ struct ether_addr ea; /* Station address */ ++ uint8 tid; /* tid */ ++}; ++/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */ ++struct ampdu_retry_tid { ++ uint8 tid; /* tid */ ++ uint8 retry; /* retry value */ ++}; ++ ++/* Different discovery modes for dpt */ ++#define DPT_DISCOVERY_MANUAL 0x01 /* manual discovery mode */ ++#define DPT_DISCOVERY_AUTO 0x02 /* auto discovery mode */ ++#define DPT_DISCOVERY_SCAN 0x04 /* scan-based discovery mode */ ++ ++/* different path selection values */ ++#define DPT_PATHSEL_AUTO 0 /* auto mode for path selection */ ++#define DPT_PATHSEL_DIRECT 1 /* always use direct DPT path */ ++#define DPT_PATHSEL_APPATH 2 /* always use AP path */ ++ ++/* different ops for deny list */ ++#define DPT_DENY_LIST_ADD 1 /* add to dpt deny list */ ++#define DPT_DENY_LIST_REMOVE 2 /* remove from dpt deny list */ ++ ++/* different ops for manual end point */ ++#define DPT_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define DPT_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define DPT_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++ ++/* structure for dpt iovars */ ++typedef struct dpt_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ uint32 pad; /* future */ ++} dpt_iovar_t; ++ ++/* flags to indicate DPT status */ ++#define DPT_STATUS_ACTIVE 0x01 /* link active (though may be suspended) */ ++#define DPT_STATUS_AES 0x02 /* link secured through AES encryption */ ++#define DPT_STATUS_FAILED 0x04 /* DPT link failed */ ++ ++#define DPT_FNAME_LEN 48 /* Max length of friendly name */ ++ ++typedef struct dpt_status { ++ uint8 status; /* flags to indicate status */ ++ uint8 fnlen; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++ uint32 rssi; /* RSSI of the link */ ++ sta_info_t sta; /* sta info */ ++} dpt_status_t; ++ ++/* structure for dpt list */ ++typedef struct dpt_list { ++ uint32 num; /* number of entries in struct */ ++ dpt_status_t status[1]; /* per station info */ ++} dpt_list_t; ++ ++/* structure for dpt friendly name */ ++typedef struct dpt_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++} dpt_fname_t; ++ ++#define BDD_FNAME_LEN 32 /* Max length of friendly name */ ++typedef struct bdd_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[BDD_FNAME_LEN]; /* friendly name */ ++} bdd_fname_t; ++ ++/* structure for addts arguments */ ++/* For ioctls that take a list of TSPEC */ ++struct tslist { ++ int count; /* number of tspecs */ ++ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ ++}; ++ ++#ifdef WLTDLS ++/* different ops for manual end point */ ++#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++#define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ ++#define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ ++#define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ ++#define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ ++ ++/* structure for tdls iovars */ ++typedef struct tdls_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ chanspec_t chanspec; ++ uint32 pad; /* future */ ++} tdls_iovar_t; ++#endif /* WLTDLS */ ++ ++/* structure for addts/delts arguments */ ++typedef struct tspec_arg { ++ uint16 version; /* see definition of TSPEC_ARG_VERSION */ ++ uint16 length; /* length of entire structure */ ++ uint flag; /* bit field */ ++ /* TSPEC Arguments */ ++ struct tsinfo_arg tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint min_srv_interval; /* Minimum Service Interval (us) */ ++ uint max_srv_interval; /* Maximum Service Interval (us) */ ++ uint inactivity_interval; /* Inactivity Interval (us) */ ++ uint suspension_interval; /* Suspension Interval (us) */ ++ uint srv_start_time; /* Service Start Time (us) */ ++ uint min_data_rate; /* Minimum Data Rate (bps) */ ++ uint mean_data_rate; /* Mean Data Rate (bps) */ ++ uint peak_data_rate; /* Peak Data Rate (bps) */ ++ uint max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint delay_bound; /* Delay Bound (us) */ ++ uint min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++ uint8 dialog_token; /* dialog token */ ++} tspec_arg_t; ++ ++/* tspec arg for desired station */ ++typedef struct tspec_per_sta_arg { ++ struct ether_addr ea; ++ struct tspec_arg ts; ++} tspec_per_sta_arg_t; ++ ++/* structure for max bandwidth for each access category */ ++typedef struct wme_max_bandwidth { ++ uint32 ac[AC_COUNT]; /* max bandwidth for each access category */ ++} wme_max_bandwidth_t; ++ ++#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t)) ++ ++/* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */ ++#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */ ++#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */ ++ ++ ++#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80 ++#define WLC_WOWL_MAX_KEEPALIVE 2 ++ ++/* define for flag */ ++#define TSPEC_PENDING 0 /* TSPEC pending */ ++#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ ++#define TSPEC_REJECTED 2 /* TSPEC rejected */ ++#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ ++#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ ++ ++ ++/* Software feature flag defines used by wlfeatureflag */ ++#ifdef WLAFTERBURNER ++#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ ++#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ ++#endif /* WLAFTERBURNER */ ++#define WL_SWFL_NOHWRADIO 0x0004 ++#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ ++#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ ++ ++#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ ++ ++/* Packet lifetime configuration per ac */ ++typedef struct wl_lifetime { ++ uint32 ac; /* access class */ ++ uint32 lifetime; /* Packet lifetime value in ms */ ++} wl_lifetime_t; ++ ++/* Channel Switch Announcement param */ ++typedef struct wl_chan_switch { ++ uint8 mode; /* value 0 or 1 */ ++ uint8 count; /* count # of beacons before switching */ ++ chanspec_t chspec; /* chanspec */ ++ uint8 reg; /* regulatory class */ ++} wl_chan_switch_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER. ++ * ++ * (-100 < value < 0) value is used directly as a roaming trigger in dBm ++ * (0 <= value) value specifies a logical roaming trigger level from ++ * the list below ++ * ++ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never ++ * the logical roam trigger value. ++ */ ++#define WLC_ROAM_TRIGGER_DEFAULT 0 /* default roaming trigger */ ++#define WLC_ROAM_TRIGGER_BANDWIDTH 1 /* optimize for bandwidth roaming trigger */ ++#define WLC_ROAM_TRIGGER_DISTANCE 2 /* optimize for distance roaming trigger */ ++#define WLC_ROAM_TRIGGER_AUTO 3 /* auto-detect environment */ ++#define WLC_ROAM_TRIGGER_MAX_VALUE 3 /* max. valid value */ ++ ++#define WLC_ROAM_NEVER_ROAM_TRIGGER (-100) /* Avoid Roaming by setting a large value */ ++ ++/* Preferred Network Offload (PNO, formerly PFN) defines */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++enum { ++ PFN_LIST_ORDER, ++ PFN_RSSI ++}; ++ ++enum { ++ DISABLE, ++ ENABLE ++}; ++ ++enum { ++ OFF_ADAPT, ++ SMART_ADAPT, ++ STRICT_ADAPT, ++ SLOW_ADAPT ++}; ++ ++#define SORT_CRITERIA_BIT 0 ++#define AUTO_NET_SWITCH_BIT 1 ++#define ENABLE_BKGRD_SCAN_BIT 2 ++#define IMMEDIATE_SCAN_BIT 3 ++#define AUTO_CONNECT_BIT 4 ++#define ENABLE_BD_SCAN_BIT 5 ++#define ENABLE_ADAPTSCAN_BIT 6 ++#define IMMEDIATE_EVENT_BIT 8 ++ ++#define SORT_CRITERIA_MASK 0x0001 ++#define AUTO_NET_SWITCH_MASK 0x0002 ++#define ENABLE_BKGRD_SCAN_MASK 0x0004 ++#define IMMEDIATE_SCAN_MASK 0x0008 ++#define AUTO_CONNECT_MASK 0x0010 ++ ++#define ENABLE_BD_SCAN_MASK 0x0020 ++#define ENABLE_ADAPTSCAN_MASK 0x00c0 ++#define IMMEDIATE_EVENT_MASK 0x0100 ++ ++#define PFN_VERSION 2 ++#define PFN_SCANRESULT_VERSION 1 ++#define MAX_PFN_LIST_COUNT 16 ++ ++#define PFN_COMPLETE 1 ++#define PFN_INCOMPLETE 0 ++ ++#define DEFAULT_BESTN 2 ++#define DEFAULT_MSCAN 0 ++#define DEFAULT_REPEAT 10 ++#define DEFAULT_EXP 2 ++ ++/* PFN network info structure */ ++typedef struct wl_pfn_subnet_info { ++ struct ether_addr BSSID; ++ uint8 channel; /* channel number only */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++} wl_pfn_subnet_info_t; ++ ++typedef struct wl_pfn_net_info { ++ wl_pfn_subnet_info_t pfnsubnet; ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ uint16 timestamp; /* age in seconds */ ++} wl_pfn_net_info_t; ++ ++typedef struct wl_pfn_scanresults { ++ uint32 version; ++ uint32 status; ++ uint32 count; ++ wl_pfn_net_info_t netinfo[1]; ++} wl_pfn_scanresults_t; ++ ++/* PFN data structure */ ++typedef struct wl_pfn_param { ++ int32 version; /* PNO parameters version */ ++ int32 scan_freq; /* Scan frequency */ ++ int32 lost_network_timeout; /* Timeout in sec. to declare ++ * discovered network as lost ++ */ ++ int16 flags; /* Bit field to control features ++ * of PFN such as sort criteria auto ++ * enable switch and background scan ++ */ ++ int16 rssi_margin; /* Margin to avoid jitter for choosing a ++ * PFN based on RSSI sort criteria ++ */ ++ uint8 bestn; /* number of best networks in each scan */ ++ uint8 mscan; /* number of scans recorded */ ++ uint8 repeat; /* Minimum number of scan intervals ++ *before scan frequency changes in adaptive scan ++ */ ++ uint8 exp; /* Exponent of 2 for maximum scan interval */ ++#if !defined(WLC_PATCH) || !defined(BCM43362A2) ++ int32 slow_freq; /* slow scan period */ ++#endif /* !WLC_PATCH || !BCM43362A2 */ ++} wl_pfn_param_t; ++ ++typedef struct wl_pfn { ++ wlc_ssid_t ssid; /* ssid name and its length */ ++ int32 bss_type; /* IBSS or infrastructure */ ++ int32 infra; /* BSS Vs IBSS */ ++ int32 auth; /* Open Vs Closed */ ++ int32 wpa_auth; /* WPA type */ ++ int32 wsec; /* wsec value */ ++} wl_pfn_t; ++#define WL_PFN_HIDDEN_BIT 2 ++#define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ ++#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ ++#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ ++#define WL_PFN_HIDDEN_MASK 0x4 ++ ++/* TCP Checksum Offload defines */ ++#define TOE_TX_CSUM_OL 0x00000001 ++#define TOE_RX_CSUM_OL 0x00000002 ++ ++/* TCP Checksum Offload error injection for testing */ ++#define TOE_ERRTEST_TX_CSUM 0x00000001 ++#define TOE_ERRTEST_RX_CSUM 0x00000002 ++#define TOE_ERRTEST_RX_CSUM2 0x00000004 ++ ++struct toe_ol_stats_t { ++ /* Num of tx packets that don't need to be checksummed */ ++ uint32 tx_summed; ++ ++ /* Num of tx packets where checksum is filled by offload engine */ ++ uint32 tx_iph_fill; ++ uint32 tx_tcp_fill; ++ uint32 tx_udp_fill; ++ uint32 tx_icmp_fill; ++ ++ /* Num of rx packets where toe finds out if checksum is good or bad */ ++ uint32 rx_iph_good; ++ uint32 rx_iph_bad; ++ uint32 rx_tcp_good; ++ uint32 rx_tcp_bad; ++ uint32 rx_udp_good; ++ uint32 rx_udp_bad; ++ uint32 rx_icmp_good; ++ uint32 rx_icmp_bad; ++ ++ /* Num of tx packets in which csum error is injected */ ++ uint32 tx_tcp_errinj; ++ uint32 tx_udp_errinj; ++ uint32 tx_icmp_errinj; ++ ++ /* Num of rx packets in which csum error is injected */ ++ uint32 rx_tcp_errinj; ++ uint32 rx_udp_errinj; ++ uint32 rx_icmp_errinj; ++}; ++ ++/* ARP Offload feature flags for arp_ol iovar */ ++#define ARP_OL_AGENT 0x00000001 ++#define ARP_OL_SNOOP 0x00000002 ++#define ARP_OL_HOST_AUTO_REPLY 0x00000004 ++#define ARP_OL_PEER_AUTO_REPLY 0x00000008 ++ ++/* ARP Offload error injection */ ++#define ARP_ERRTEST_REPLY_PEER 0x1 ++#define ARP_ERRTEST_REPLY_HOST 0x2 ++ ++#define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++ ++/* Arp offload statistic counts */ ++struct arp_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ ++ uint32 arp_table_entries; /* ARP table entries */ ++ uint32 arp_table_overflow; /* ARP table additions skipped due to overflow */ ++ ++ uint32 host_request; /* ARP requests from host */ ++ uint32 host_reply; /* ARP replies from host */ ++ uint32 host_service; /* ARP requests from host serviced by ARP Agent */ ++ ++ uint32 peer_request; /* ARP requests received from network */ ++ uint32 peer_request_drop; /* ARP requests from network that were dropped */ ++ uint32 peer_reply; /* ARP replies received from network */ ++ uint32 peer_reply_drop; /* ARP replies from network that were dropped */ ++ uint32 peer_service; /* ARP request from host serviced by ARP Agent */ ++}; ++ ++/* NS offload statistic counts */ ++struct nd_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ uint32 peer_request; /* NS requests received from network */ ++ uint32 peer_request_drop; /* NS requests from network that were dropped */ ++ uint32 peer_reply_drop; /* NA replies from network that were dropped */ ++ uint32 peer_service; /* NS request from host serviced by firmware */ ++}; ++ ++/* ++ * Keep-alive packet offloading. ++ */ ++ ++/* NAT keep-alive packets format: specifies the re-transmission period, the packet ++ * length, and packet contents. ++ */ ++typedef struct wl_keep_alive_pkt { ++ uint32 period_msec; /* Retransmission period (0 to disable packet re-transmits) */ ++ uint16 len_bytes; /* Size of packet to transmit (0 to disable packet re-transmits) */ ++ uint8 data[1]; /* Variable length packet to transmit. Contents should include ++ * entire ethernet packet (enet header, IP header, UDP header, ++ * and UDP payload) in network byte order. ++ */ ++} wl_keep_alive_pkt_t; ++ ++#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data) ++ ++/* ++ * Dongle pattern matching filter. ++ */ ++ ++/* Packet filter types. Currently, only pattern matching is supported. */ ++typedef enum wl_pkt_filter_type { ++ WL_PKT_FILTER_TYPE_PATTERN_MATCH /* Pattern matching filter */ ++} wl_pkt_filter_type_t; ++ ++#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t ++ ++/* Pattern matching filter. Specifies an offset within received packets to ++ * start matching, the pattern to match, the size of the pattern, and a bitmask ++ * that indicates which bits within the pattern should be matched. ++ */ ++typedef struct wl_pkt_filter_pattern { ++ uint32 offset; /* Offset within received packet to start pattern matching. ++ * Offset '0' is the first byte of the ethernet header. ++ */ ++ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ ++ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts ++ * at offset 0. Pattern immediately follows mask. ++ */ ++} wl_pkt_filter_pattern_t; ++ ++/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ ++typedef struct wl_pkt_filter { ++ uint32 id; /* Unique filter id, specified by app. */ ++ uint32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ ++ uint32 negate_match; /* Negate the result of filter matches */ ++ union { /* Filter definitions */ ++ wl_pkt_filter_pattern_t pattern; /* Pattern matching filter */ ++ } u; ++} wl_pkt_filter_t; ++ ++#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u) ++#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern) ++ ++/* IOVAR "pkt_filter_enable" parameter. */ ++typedef struct wl_pkt_filter_enable { ++ uint32 id; /* Unique filter id */ ++ uint32 enable; /* Enable/disable bool */ ++} wl_pkt_filter_enable_t; ++ ++/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ ++typedef struct wl_pkt_filter_list { ++ uint32 num; /* Number of installed packet filters */ ++ wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */ ++} wl_pkt_filter_list_t; ++ ++#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) ++ ++/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */ ++typedef struct wl_pkt_filter_stats { ++ uint32 num_pkts_matched; /* # filter matches for specified filter id */ ++ uint32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */ ++ uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ ++} wl_pkt_filter_stats_t; ++ ++/* Sequential Commands ioctl */ ++typedef struct wl_seq_cmd_ioctl { ++ uint32 cmd; /* common ioctl definition */ ++ uint32 len; /* length of user buffer */ ++} wl_seq_cmd_ioctl_t; ++ ++#define WL_SEQ_CMD_ALIGN_BYTES 4 ++ ++/* These are the set of get IOCTLs that should be allowed when using ++ * IOCTL sequence commands. These are issued implicitly by wl.exe each time ++ * it is invoked. We never want to buffer these, or else wl.exe will stop working. ++ */ ++#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ ++ (((cmd) == WLC_GET_MAGIC) || \ ++ ((cmd) == WLC_GET_VERSION) || \ ++ ((cmd) == WLC_GET_AP) || \ ++ ((cmd) == WLC_GET_INSTANCE)) ++ ++/* ++ * Packet engine interface ++ */ ++ ++#define WL_PKTENG_PER_TX_START 0x01 ++#define WL_PKTENG_PER_TX_STOP 0x02 ++#define WL_PKTENG_PER_RX_START 0x04 ++#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 ++#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 ++#define WL_PKTENG_PER_RX_STOP 0x08 ++#define WL_PKTENG_PER_MASK 0xff ++ ++#define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ ++ ++typedef struct wl_pkteng { ++ uint32 flags; ++ uint32 delay; /* Inter-packet delay */ ++ uint32 nframes; /* Number of frames */ ++ uint32 length; /* Packet length */ ++ uint8 seqno; /* Enable/disable sequence no. */ ++ struct ether_addr dest; /* Destination address */ ++ struct ether_addr src; /* Source address */ ++} wl_pkteng_t; ++ ++#define NUM_80211b_RATES 4 ++#define NUM_80211ag_RATES 8 ++#define NUM_80211n_RATES 32 ++#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) ++typedef struct wl_pkteng_stats { ++ uint32 lostfrmcnt; /* RX PER test: no of frames lost (skip seqno) */ ++ int32 rssi; /* RSSI */ ++ int32 snr; /* signal to noise ratio */ ++ uint16 rxpktcnt[NUM_80211_RATES+1]; ++} wl_pkteng_stats_t; ++ ++typedef struct wl_sslpnphy_papd_debug_data { ++ uint8 psat_pwr; ++ uint8 psat_indx; ++ uint8 final_idx; ++ uint8 start_idx; ++ int32 min_phase; ++ int32 voltage; ++ int8 temperature; ++} wl_sslpnphy_papd_debug_data_t; ++typedef struct wl_sslpnphy_debug_data { ++ int16 papdcompRe [64]; ++ int16 papdcompIm [64]; ++} wl_sslpnphy_debug_data_t; ++typedef struct wl_sslpnphy_spbdump_data { ++ uint16 tbl_length; ++ int16 spbreal[256]; ++ int16 spbimg[256]; ++} wl_sslpnphy_spbdump_data_t; ++typedef struct wl_sslpnphy_percal_debug_data { ++ uint cur_idx; ++ uint tx_drift; ++ uint8 prev_cal_idx; ++ uint percal_ctr; ++ int nxt_cal_idx; ++ uint force_1idxcal; ++ uint onedxacl_req; ++ int32 last_cal_volt; ++ int8 last_cal_temp; ++ uint vbat_ripple; ++ uint exit_route; ++ int32 volt_winner; ++} wl_sslpnphy_percal_debug_data_t; ++ ++#define WL_WOWL_MAGIC (1 << 0) /* Wakeup on Magic packet */ ++#define WL_WOWL_NET (1 << 1) /* Wakeup on Netpattern */ ++#define WL_WOWL_DIS (1 << 2) /* Wakeup on loss-of-link due to Disassoc/Deauth */ ++#define WL_WOWL_RETR (1 << 3) /* Wakeup on retrograde TSF */ ++#define WL_WOWL_BCN (1 << 4) /* Wakeup on loss of beacon */ ++#define WL_WOWL_TST (1 << 5) /* Wakeup after test */ ++#define WL_WOWL_M1 (1 << 6) /* Wakeup after PTK refresh */ ++#define WL_WOWL_EAPID (1 << 7) /* Wakeup after receipt of EAP-Identity Req */ ++#define WL_WOWL_PME_GPIO (1 << 8) /* Wakeind via PME(0) or GPIO(1) */ ++#define WL_WOWL_NEEDTKIP1 (1 << 9) /* need tkip phase 1 key to be updated by the driver */ ++#define WL_WOWL_GTK_FAILURE (1 << 10) /* enable wakeup if GTK fails */ ++#define WL_WOWL_EXTMAGPAT (1 << 11) /* support extended magic packets */ ++#define WL_WOWL_ARPOFFLOAD (1 << 12) /* support ARP/NS/keepalive offloading */ ++#define WL_WOWL_WPA2 (1 << 13) /* read protocol version for EAPOL frames */ ++#define WL_WOWL_KEYROT (1 << 14) /* If the bit is set, use key rotaton */ ++#define WL_WOWL_BCAST (1 << 15) /* If the bit is set, frm received was bcast frame */ ++ ++#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ ++ ++#define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ ++#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ ++ ++typedef struct { ++ uint32 masksize; /* Size of the mask in #of bytes */ ++ uint32 offset; /* Offset to start looking for the packet in # of bytes */ ++ uint32 patternoffset; /* Offset of start of pattern in the structure */ ++ uint32 patternsize; /* Size of the pattern itself in #of bytes */ ++ uint32 id; /* id */ ++ uint32 reasonsize; /* Size of the wakeup reason code */ ++ uint32 flags; /* Flags to tell the pattern type and other properties */ ++ /* Mask follows the structure above */ ++ /* Pattern follows the mask is at 'patternoffset' from the start */ ++} wl_wowl_pattern_t; ++ ++typedef struct { ++ uint count; ++ wl_wowl_pattern_t pattern[1]; ++} wl_wowl_pattern_list_t; ++ ++typedef struct { ++ uint8 pci_wakeind; /* Whether PCI PMECSR PMEStatus bit was set */ ++ uint16 ucode_wakeind; /* What wakeup-event indication was set by ucode */ ++} wl_wowl_wakeind_t; ++ ++ ++/* per AC rate control related data structure */ ++typedef struct wl_txrate_class { ++ uint8 init_rate; ++ uint8 min_rate; ++ uint8 max_rate; ++} wl_txrate_class_t; ++ ++ ++#if defined(DSLCPE_DELAY) ++#define WL_DELAYMODE_DEFER 0 /* defer by scheduler's choice, make this driver default */ ++#define WL_DELAYMODE_FORCE 1 /* force, this is driver default */ ++#define WL_DELAYMODE_AUTO 2 /* defer if no sta associated, force if sta associated */ ++#endif ++ ++/* Overlap BSS Scan parameters default, minimum, maximum */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 /* unit Sec */ ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 /* unit percent */ ++ ++/* structure for Overlap BSS scan arguments */ ++typedef struct wl_obss_scan_arg { ++ int16 passive_dwell; ++ int16 active_dwell; ++ int16 bss_widthscan_interval; ++ int16 passive_total; ++ int16 active_total; ++ int16 chanwidth_transition_delay; ++ int16 activity_threshold; ++} wl_obss_scan_arg_t; ++ ++#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) ++#define WL_MIN_NUM_OBSS_SCAN_ARG 7 /* minimum number of arguments required for OBSS Scan */ ++ ++#define WL_COEX_INFO_MASK 0x07 ++#define WL_COEX_INFO_REQ 0x01 ++#define WL_COEX_40MHZ_INTOLERANT 0x02 ++#define WL_COEX_WIDTH20 0x04 ++ ++#define WLC_RSSI_INVALID 0 /* invalid RSSI value */ ++ ++#define MAX_RSSI_LEVELS 8 ++ ++/* RSSI event notification configuration. */ ++typedef struct wl_rssi_event { ++ uint32 rate_limit_msec; /* # of events posted to application will be limited to ++ * one per specified period (0 to disable rate limit). ++ */ ++ uint8 num_rssi_levels; /* Number of entries in rssi_levels[] below */ ++ int8 rssi_levels[MAX_RSSI_LEVELS]; /* Variable number of RSSI levels. An event ++ * will be posted each time the RSSI of received ++ * beacons/packets crosses a level. ++ */ ++} wl_rssi_event_t; ++ ++typedef struct wl_action_obss_coex_req { ++ uint8 info; ++ uint8 num; ++ uint8 ch_list[1]; ++} wl_action_obss_coex_req_t; ++ ++ ++/* IOVar parameter block for small MAC address array with type indicator */ ++#define WL_IOV_MAC_PARAM_LEN 4 ++ ++#define WL_IOV_PKTQ_LOG_PRECS 16 ++ ++typedef struct { ++ uint32 num_addrs; ++ char addr_type[WL_IOV_MAC_PARAM_LEN]; ++ struct ether_addr ea[WL_IOV_MAC_PARAM_LEN]; ++} wl_iov_mac_params_t; ++ ++ ++/* Parameter block for PKTQ_LOG statistics */ ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_log_counters_v01_t; ++ ++#define sacrified sacrificed ++ ++typedef struct { ++ uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; ++ pktq_log_counters_v01_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; ++ char headings[1]; ++} pktq_log_format_v01_t; ++ ++ ++typedef struct { ++ uint32 version; ++ wl_iov_mac_params_t params; ++ union { ++ pktq_log_format_v01_t v01; ++ } pktq_log; ++} wl_iov_pktq_log_t; ++ ++ ++/* **** EXTLOG **** */ ++#define EXTLOG_CUR_VER 0x0100 ++ ++#define MAX_ARGSTR_LEN 18 /* At least big enough for storing ETHER_ADDR_STR_LEN */ ++ ++/* log modules (bitmap) */ ++#define LOG_MODULE_COMMON 0x0001 ++#define LOG_MODULE_ASSOC 0x0002 ++#define LOG_MODULE_EVENT 0x0004 ++#define LOG_MODULE_MAX 3 /* Update when adding module */ ++ ++/* log levels */ ++#define WL_LOG_LEVEL_DISABLE 0 ++#define WL_LOG_LEVEL_ERR 1 ++#define WL_LOG_LEVEL_WARN 2 ++#define WL_LOG_LEVEL_INFO 3 ++#define WL_LOG_LEVEL_MAX WL_LOG_LEVEL_INFO /* Update when adding level */ ++ ++/* flag */ ++#define LOG_FLAG_EVENT 1 ++ ++/* log arg_type */ ++#define LOG_ARGTYPE_NULL 0 ++#define LOG_ARGTYPE_STR 1 /* %s */ ++#define LOG_ARGTYPE_INT 2 /* %d */ ++#define LOG_ARGTYPE_INT_STR 3 /* %d...%s */ ++#define LOG_ARGTYPE_STR_INT 4 /* %s...%d */ ++ ++typedef struct wlc_extlog_cfg { ++ int max_number; ++ uint16 module; /* bitmap */ ++ uint8 level; ++ uint8 flag; ++ uint16 version; ++} wlc_extlog_cfg_t; ++ ++typedef struct log_record { ++ uint32 time; ++ uint16 module; ++ uint16 id; ++ uint8 level; ++ uint8 sub_unit; ++ uint8 seq_num; ++ int32 arg; ++ char str[MAX_ARGSTR_LEN]; ++} log_record_t; ++ ++typedef struct wlc_extlog_req { ++ uint32 from_last; ++ uint32 num; ++} wlc_extlog_req_t; ++ ++typedef struct wlc_extlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ log_record_t logs[1]; ++} wlc_extlog_results_t; ++ ++typedef struct log_idstr { ++ uint16 id; ++ uint16 flag; ++ uint8 arg_type; ++ const char *fmt_str; ++} log_idstr_t; ++ ++#define FMTSTRF_USER 1 ++ ++/* flat ID definitions ++ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will ++ * affect backward compatibility with pre-existing apps ++ */ ++typedef enum { ++ FMTSTR_DRIVER_UP_ID = 0, ++ FMTSTR_DRIVER_DOWN_ID = 1, ++ FMTSTR_SUSPEND_MAC_FAIL_ID = 2, ++ FMTSTR_NO_PROGRESS_ID = 3, ++ FMTSTR_RFDISABLE_ID = 4, ++ FMTSTR_REG_PRINT_ID = 5, ++ FMTSTR_EXPTIME_ID = 6, ++ FMTSTR_JOIN_START_ID = 7, ++ FMTSTR_JOIN_COMPLETE_ID = 8, ++ FMTSTR_NO_NETWORKS_ID = 9, ++ FMTSTR_SECURITY_MISMATCH_ID = 10, ++ FMTSTR_RATE_MISMATCH_ID = 11, ++ FMTSTR_AP_PRUNED_ID = 12, ++ FMTSTR_KEY_INSERTED_ID = 13, ++ FMTSTR_DEAUTH_ID = 14, ++ FMTSTR_DISASSOC_ID = 15, ++ FMTSTR_LINK_UP_ID = 16, ++ FMTSTR_LINK_DOWN_ID = 17, ++ FMTSTR_RADIO_HW_OFF_ID = 18, ++ FMTSTR_RADIO_HW_ON_ID = 19, ++ FMTSTR_EVENT_DESC_ID = 20, ++ FMTSTR_PNP_SET_POWER_ID = 21, ++ FMTSTR_RADIO_SW_OFF_ID = 22, ++ FMTSTR_RADIO_SW_ON_ID = 23, ++ FMTSTR_PWD_MISMATCH_ID = 24, ++ FMTSTR_FATAL_ERROR_ID = 25, ++ FMTSTR_AUTH_FAIL_ID = 26, ++ FMTSTR_ASSOC_FAIL_ID = 27, ++ FMTSTR_IBSS_FAIL_ID = 28, ++ FMTSTR_EXTAP_FAIL_ID = 29, ++ FMTSTR_MAX_ID ++} log_fmtstr_id_t; ++ ++#ifdef DONGLEOVERLAYS ++typedef struct { ++ uint32 flags_idx; /* lower 8 bits: overlay index; upper 24 bits: flags */ ++ uint32 offset; /* offset into overlay region to write code */ ++ uint32 len; /* overlay code len */ ++ /* overlay code follows this struct */ ++} wl_ioctl_overlay_t; ++ ++#define OVERLAY_IDX_MASK 0x000000ff ++#define OVERLAY_IDX_SHIFT 0 ++#define OVERLAY_FLAGS_MASK 0xffffff00 ++#define OVERLAY_FLAGS_SHIFT 8 ++/* overlay written to device memory immediately after loading the base image */ ++#define OVERLAY_FLAG_POSTLOAD 0x100 ++/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */ ++#define OVERLAY_FLAG_DEFER_DL 0x200 ++/* overlay downloaded prior to the host going to sleep */ ++#define OVERLAY_FLAG_PRESLEEP 0x400 ++ ++#define OVERLAY_DOWNLOAD_CHUNKSIZE 1024 ++#endif /* DONGLEOVERLAYS */ ++ ++/* no default structure packing */ ++#include ++ ++/* require strict packing */ ++#include ++/* Structures and constants used for "vndr_ie" IOVar interface */ ++#define VNDR_IE_CMD_LEN 4 /* length of the set command string: ++ * "add", "del" (+ NUL) ++ */ ++ ++/* 802.11 Mgmt Packet flags */ ++#define VNDR_IE_BEACON_FLAG 0x1 ++#define VNDR_IE_PRBRSP_FLAG 0x2 ++#define VNDR_IE_ASSOCRSP_FLAG 0x4 ++#define VNDR_IE_AUTHRSP_FLAG 0x8 ++#define VNDR_IE_PRBREQ_FLAG 0x10 ++#define VNDR_IE_ASSOCREQ_FLAG 0x20 ++#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ ++#define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ ++ ++#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ vndr_ie_t vndr_ie_data; /* vendor IE data */ ++} BWL_POST_PACKED_STRUCT vndr_ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the vndr_ie_list[] array */ ++ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT vndr_ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NUL */ ++ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ ++} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT tlv_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ tlv_t ie_data; /* IE data */ ++} BWL_POST_PACKED_STRUCT ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the ie_list[] array */ ++ ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */ ++ ie_buf_t ie_buffer; /* buffer containing IE list information */ ++} BWL_POST_PACKED_STRUCT ie_setbuf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ uint8 id; /* IE type */ ++} BWL_POST_PACKED_STRUCT ie_getbuf_t; ++ ++/* structures used to define format of wps ie data from probe requests */ ++/* passed up to applications via iovar "prbreq_wpsie" */ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { ++ struct ether_addr staAddr; ++ uint16 ieLen; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data { ++ sta_prbreq_wps_ie_hdr_t hdr; ++ uint8 ieData[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list { ++ uint32 totLen; ++ uint8 ieDataList[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t; ++ ++ ++#ifdef WLMEDIA_TXFAILEVENT ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char dest[ETHER_ADDR_LEN]; /* destination MAC */ ++ uint8 prio; /* Packet Priority */ ++ uint8 flags; /* Flags */ ++ uint32 tsf_l; /* TSF timer low */ ++ uint32 tsf_h; /* TSF timer high */ ++ uint16 rates; /* Main Rates */ ++ uint16 txstatus; /* TX Status */ ++} BWL_POST_PACKED_STRUCT txfailinfo_t; ++#endif /* WLMEDIA_TXFAILEVENT */ ++ ++/* no strict structure packing */ ++#include ++ ++/* Global ASSERT Logging */ ++#define ASSERTLOG_CUR_VER 0x0100 ++#define MAX_ASSRTSTR_LEN 64 ++ ++typedef struct assert_record { ++ uint32 time; ++ uint8 seq_num; ++ char str[MAX_ASSRTSTR_LEN]; ++} assert_record_t; ++ ++typedef struct assertlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ assert_record_t logs[1]; ++} assertlog_results_t; ++ ++#define LOGRRC_FIX_LEN 8 ++#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) ++ ++ ++/* channel interference measurement (chanim) related defines */ ++ ++/* chanim mode */ ++#define CHANIM_DISABLE 0 /* disabled */ ++#define CHANIM_DETECT 1 /* detection only */ ++#define CHANIM_EXT 2 /* external state machine */ ++#define CHANIM_ACT 3 /* full internal state machine, detect + act */ ++#define CHANIM_MODE_MAX 4 ++ ++/* define for apcs reason code */ ++#define APCS_INIT 0 ++#define APCS_IOCTL 1 ++#define APCS_CHANIM 2 ++#define APCS_CSTIMER 3 ++#define APCS_BTA 4 ++ ++/* number of ACS record entries */ ++#define CHANIM_ACS_RECORD 10 ++ ++/* CHANIM */ ++#define CCASTATS_TXDUR 0 ++#define CCASTATS_INBSS 1 ++#define CCASTATS_OBSS 2 ++#define CCASTATS_NOCTG 3 ++#define CCASTATS_NOPKT 4 ++#define CCASTATS_DOZE 5 ++#define CCASTATS_TXOP 6 ++#define CCASTATS_GDTXDUR 7 ++#define CCASTATS_BDTXDUR 8 ++#define CCASTATS_MAX 9 ++ ++/* chanim acs record */ ++typedef struct { ++ bool valid; ++ uint8 trigger; ++ chanspec_t selected_chspc; ++ int8 bgnoise; ++ uint32 glitch_cnt; ++ uint8 ccastats; ++ uint timestamp; ++} chanim_acs_record_t; ++ ++typedef struct { ++ chanim_acs_record_t acs_record[CHANIM_ACS_RECORD]; ++ uint8 count; ++ uint timestamp; ++} wl_acs_record_t; ++ ++typedef struct chanim_stats { ++ uint32 glitchcnt; /* normalized as per second count */ ++ uint32 badplcp; /* normalized as per second count */ ++ uint8 ccastats[CCASTATS_MAX]; /* normalized as 0-255 */ ++ int8 bgnoise; /* background noise level (in dBm) */ ++ chanspec_t chanspec; ++ uint32 timestamp; ++} chanim_stats_t; ++ ++#define WL_CHANIM_STATS_VERSION 1 ++#define WL_CHANIM_COUNT_ALL 0xff ++#define WL_CHANIM_COUNT_ONE 0x1 ++ ++typedef struct { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ chanim_stats_t stats[1]; ++} wl_chanim_stats_t; ++ ++#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats) ++ ++/* Noise measurement metrics. */ ++#define NOISE_MEASURE_KNOISE 0x1 ++ ++/* scb probe parameter */ ++typedef struct { ++ uint32 scb_timeout; ++ uint32 scb_activity_time; ++ uint32 scb_max_probe; ++} wl_scb_probe_t; ++ ++/* ap tpc modes */ ++#define AP_TPC_OFF 0 ++#define AP_TPC_BSS_PWR 1 /* BSS power control */ ++#define AP_TPC_AP_PWR 2 /* AP power control */ ++#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */ ++#define AP_TPC_MAX_LINK_MARGIN 127 ++ ++/* structure/defines for selective mgmt frame (smf) stats support */ ++ ++#define SMFS_VERSION 1 ++/* selected mgmt frame (smf) stats element */ ++typedef struct wl_smfs_elem { ++ uint32 count; ++ uint16 code; /* SC or RC code */ ++} wl_smfs_elem_t; ++ ++typedef struct wl_smf_stats { ++ uint32 version; ++ uint16 length; /* reserved for future usage */ ++ uint8 type; ++ uint8 codetype; ++ uint32 ignored_cnt; ++ uint32 malformed_cnt; ++ uint32 count_total; /* count included the interested group */ ++ wl_smfs_elem_t elem[1]; ++} wl_smf_stats_t; ++ ++#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem); ++ ++enum { ++ SMFS_CODETYPE_SC, ++ SMFS_CODETYPE_RC ++}; ++ ++/* reuse two number in the sc/rc space */ ++#define SMFS_CODE_MALFORMED 0xFFFE ++#define SMFS_CODE_IGNORED 0xFFFD ++ ++typedef enum smfs_type { ++ SMFS_TYPE_AUTH, ++ SMFS_TYPE_ASSOC, ++ SMFS_TYPE_REASSOC, ++ SMFS_TYPE_DISASSOC_TX, ++ SMFS_TYPE_DISASSOC_RX, ++ SMFS_TYPE_DEAUTH_TX, ++ SMFS_TYPE_DEAUTH_RX, ++ SMFS_TYPE_MAX ++} smfs_type_t; ++ ++#ifdef PHYMON ++ ++#define PHYMON_VERSION 1 ++ ++typedef struct wl_phycal_core_state { ++ /* Tx IQ/LO calibration coeffs */ ++ int16 tx_iqlocal_a; ++ int16 tx_iqlocal_b; ++ int8 tx_iqlocal_ci; ++ int8 tx_iqlocal_cq; ++ int8 tx_iqlocal_di; ++ int8 tx_iqlocal_dq; ++ int8 tx_iqlocal_ei; ++ int8 tx_iqlocal_eq; ++ int8 tx_iqlocal_fi; ++ int8 tx_iqlocal_fq; ++ ++ /* Rx IQ calibration coeffs */ ++ int16 rx_iqcal_a; ++ int16 rx_iqcal_b; ++ ++ uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */ ++ uint32 papd_epsilon_table[64]; /* PAPD epsilon table */ ++ int16 papd_epsilon_offset; /* PAPD epsilon offset */ ++ uint8 curr_tx_pwrindex; /* Tx power index */ ++ int8 idle_tssi; /* Idle TSSI */ ++ int8 est_tx_pwr; /* Estimated Tx Power (dB) */ ++ int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */ ++ uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */ ++ uint16 init_gaincode; /* initgain required for ACI */ ++ int8 estirr_tx; ++ int8 estirr_rx; ++ ++} wl_phycal_core_state_t; ++ ++typedef struct wl_phycal_state { ++ int version; ++ int8 num_phy_cores; /* number of cores */ ++ int8 curr_temperature; /* on-chip temperature sensor reading */ ++ chanspec_t chspec; /* channspec for this state */ ++ bool aci_state; /* ACI state: ON/OFF */ ++ uint16 crsminpower; /* crsminpower required for ACI */ ++ uint16 crsminpowerl; /* crsminpowerl required for ACI */ ++ uint16 crsminpoweru; /* crsminpoweru required for ACI */ ++ wl_phycal_core_state_t phycal_core[1]; ++} wl_phycal_state_t; ++ ++#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) ++#endif /* PHYMON */ ++ ++/* discovery state */ ++typedef struct wl_p2p_disc_st { ++ uint8 state; /* see state */ ++ chanspec_t chspec; /* valid in listen state */ ++ uint16 dwell; /* valid in listen state, in ms */ ++} wl_p2p_disc_st_t; ++ ++/* state */ ++#define WL_P2P_DISC_ST_SCAN 0 ++#define WL_P2P_DISC_ST_LISTEN 1 ++#define WL_P2P_DISC_ST_SEARCH 2 ++ ++/* scan request */ ++typedef struct wl_p2p_scan { ++ uint8 type; /* 'S' for WLC_SCAN, 'E' for "escan" */ ++ uint8 reserved[3]; ++ /* scan or escan parms... */ ++} wl_p2p_scan_t; ++ ++/* i/f request */ ++typedef struct wl_p2p_if { ++ struct ether_addr addr; ++ uint8 type; /* see i/f type */ ++ chanspec_t chspec; /* for p2p_ifadd GO */ ++} wl_p2p_if_t; ++ ++/* i/f type */ ++#define WL_P2P_IF_CLIENT 0 ++#define WL_P2P_IF_GO 1 ++#define WL_P2P_IF_DYNBCN_GO 2 ++#define WL_P2P_IF_DEV 3 ++ ++/* i/f query */ ++typedef struct wl_p2p_ifq { ++ uint bsscfgidx; ++ char ifname[BCM_MSG_IFNAME_MAX]; ++} wl_p2p_ifq_t; ++ ++/* OppPS & CTWindow */ ++typedef struct wl_p2p_ops { ++ uint8 ops; /* 0: disable 1: enable */ ++ uint8 ctw; /* >= 10 */ ++} wl_p2p_ops_t; ++ ++/* absence and presence request */ ++typedef struct wl_p2p_sched_desc { ++ uint32 start; ++ uint32 interval; ++ uint32 duration; ++ uint32 count; /* see count */ ++} wl_p2p_sched_desc_t; ++ ++/* count */ ++#define WL_P2P_SCHED_RSVD 0 ++#define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */ ++ ++typedef struct wl_p2p_sched { ++ uint8 type; /* see schedule type */ ++ uint8 action; /* see schedule action */ ++ uint8 option; /* see schedule option */ ++ wl_p2p_sched_desc_t desc[1]; ++} wl_p2p_sched_t; ++#define WL_P2P_SCHED_FIXED_LEN 3 ++ ++/* schedule type */ ++#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */ ++#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */ ++ ++/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */ ++#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */ ++#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_ACTION_GOOFF 2 /* turn off GO beacon/prbrsp functions */ ++/* schedule option - WL_P2P_SCHED_TYPE_XXX */ ++#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */ ++ ++/* schedule option - WL_P2P_SCHED_TYPE_ABS */ ++#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count */ ++#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_OPTION_TSFOFS 2 /* normal start/internal/duration/count with ++ * start being an offset of the 'current' TSF ++ */ ++ ++/* feature flags */ ++#define WL_P2P_FEAT_GO_CSA (1 << 0) /* GO moves with the STA using CSA method */ ++#define WL_P2P_FEAT_GO_NOLEGACY (1 << 1) /* GO does not probe respond to non-p2p probe ++ * requests ++ */ ++#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2) /* Restrict p2p dev interface from responding */ ++ ++/* RFAWARE def */ ++#define BCM_ACTION_RFAWARE 0x77 ++#define BCM_ACTION_RFAWARE_DCS 0x01 ++ ++/* DCS reason code define */ ++#define BCM_DCS_IOVAR 0x1 ++#define BCM_DCS_UNKNOWN 0xFF ++ ++typedef struct wl_bcmdcs_data { ++ uint reason; ++ chanspec_t chspec; ++} wl_bcmdcs_data_t; ++ ++/* n-mode support capability */ ++/* 2x2 includes both 1x1 & 2x2 devices ++ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and ++ * control it independently ++ */ ++#define WL_11N_2x2 1 ++#define WL_11N_3x3 3 ++#define WL_11N_4x4 4 ++ ++/* define 11n feature disable flags */ ++#define WLFEATURE_DISABLE_11N 0x00000001 ++#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 ++#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 ++#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 ++#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 ++#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 ++#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 ++#define WLFEATURE_DISABLE_11N_GF 0x00000080 ++ ++/* Proxy STA modes */ ++#define PSTA_MODE_DISABLED 0 ++#define PSTA_MODE_PROXY 1 ++#define PSTA_MODE_REPEATER 2 ++ ++ ++/* NAT configuration */ ++typedef struct { ++ uint32 ipaddr; /* interface ip address */ ++ uint32 ipaddr_mask; /* interface ip address mask */ ++ uint32 ipaddr_gateway; /* gateway ip address */ ++ uint8 mac_gateway[6]; /* gateway mac address */ ++ uint32 ipaddr_dns; /* DNS server ip address, valid only for public if */ ++ uint8 mac_dns[6]; /* DNS server mac address, valid only for public if */ ++ uint8 GUID[38]; /* interface GUID */ ++} nat_if_info_t; ++ ++typedef struct { ++ uint op; /* operation code */ ++ bool pub_if; /* set for public if, clear for private if */ ++ nat_if_info_t if_info; /* interface info */ ++} nat_cfg_t; ++ ++/* op code in nat_cfg */ ++#define NAT_OP_ENABLE 1 /* enable NAT on given interface */ ++#define NAT_OP_DISABLE 2 /* disable NAT on given interface */ ++#define NAT_OP_DISABLE_ALL 3 /* disable NAT on all interfaces */ ++ ++/* NAT state */ ++#define NAT_STATE_ENABLED 1 /* NAT is enabled */ ++#define NAT_STATE_DISABLED 2 /* NAT is disabled */ ++ ++typedef struct { ++ int state; /* NAT state returned */ ++} nat_state_t; ++ ++#ifdef PROP_TXSTATUS ++/* Bit definitions for tlv iovar */ ++/* ++ * enable RSSI signals: ++ * WLFC_CTL_TYPE_RSSI ++ */ ++#define WLFC_FLAGS_RSSI_SIGNALS 1 ++ ++/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals: ++ * ++ * WLFC_CTL_TYPE_MAC_OPEN ++ * WLFC_CTL_TYPE_MAC_CLOSE ++ * ++ * WLFC_CTL_TYPE_INTERFACE_OPEN ++ * WLFC_CTL_TYPE_INTERFACE_CLOSE ++ * ++ * WLFC_CTL_TYPE_MACDESC_ADD ++ * WLFC_CTL_TYPE_MACDESC_DEL ++ * ++ */ ++#define WLFC_FLAGS_XONXOFF_SIGNALS 2 ++ ++/* enable (status, fifo_credit, mac_credit) signals ++ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT ++ * WLFC_CTL_TYPE_TXSTATUS ++ * WLFC_CTL_TYPE_FIFO_CREDITBACK ++ */ ++#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS 4 ++ ++#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE 8 ++#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE 16 ++#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE 32 ++#endif /* PROP_TXSTATUS */ ++ ++#define BTA_STATE_LOG_SZ 64 ++ ++/* BTAMP Statemachine states */ ++enum { ++ HCIReset = 1, ++ HCIReadLocalAMPInfo, ++ HCIReadLocalAMPASSOC, ++ HCIWriteRemoteAMPASSOC, ++ HCICreatePhysicalLink, ++ HCIAcceptPhysicalLinkRequest, ++ HCIDisconnectPhysicalLink, ++ HCICreateLogicalLink, ++ HCIAcceptLogicalLink, ++ HCIDisconnectLogicalLink, ++ HCILogicalLinkCancel, ++ HCIAmpStateChange, ++ HCIWriteLogicalLinkAcceptTimeout ++}; ++ ++typedef struct flush_txfifo { ++ uint32 txfifobmp; ++ uint32 hwtxfifoflush; ++ struct ether_addr ea; ++} flush_txfifo_t; ++ ++#define CHANNEL_5G_LOW_START 36 /* 5G low (36..48) CDD enable/disable bit mask */ ++#define CHANNEL_5G_MID_START 52 /* 5G mid (52..64) CDD enable/disable bit mask */ ++#define CHANNEL_5G_HIGH_START 100 /* 5G high (100..140) CDD enable/disable bit mask */ ++#define CHANNEL_5G_UPPER_START 149 /* 5G upper (149..161) CDD enable/disable bit mask */ ++ ++enum { ++ SPATIAL_MODE_2G_IDX = 0, ++ SPATIAL_MODE_5G_LOW_IDX, ++ SPATIAL_MODE_5G_MID_IDX, ++ SPATIAL_MODE_5G_HIGH_IDX, ++ SPATIAL_MODE_5G_UPPER_IDX, ++ SPATIAL_MODE_MAX_IDX ++}; ++ ++/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ ++typedef struct wl_mempool_stats { ++ int num; /* Number of memory pools */ ++ bcm_mp_stats_t s[1]; /* Variable array of memory pool stats. */ ++} wl_mempool_stats_t; ++ ++/* Network Offload Engine */ ++#define NWOE_OL_ENABLE 0x00000001 ++ ++typedef struct { ++ uint32 ipaddr; ++ uint32 ipaddr_netmask; ++ uint32 ipaddr_gateway; ++} nwoe_ifconfig_t; ++ ++/* ++ * Traffic management structures/defines. ++ */ ++ ++/* Traffic management bandwidth parameters */ ++#define TRF_MGMT_MAX_PRIORITIES 3 ++ ++#define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ ++#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ ++ ++ ++/* Traffic management priority classes */ ++typedef enum trf_mgmt_priority_class { ++ trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */ ++ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ ++ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ ++ trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) ++} trf_mgmt_priority_class_t; ++ ++/* Traffic management configuration parameters */ ++typedef struct trf_mgmt_config { ++ uint32 trf_mgmt_enabled; /* 0 - disabled, 1 - enabled */ ++ uint32 flags; /* See TRF_MGMT_FLAG_xxx defines */ ++ uint32 host_ip_addr; ++ uint32 host_subnet_mask; ++ uint32 downlink_bandwidth; /* In units of kbps */ ++ uint32 uplink_bandwidth; /* In units of kbps */ ++ uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; ++ uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_config_t; ++ ++/* Traffic management filter */ ++typedef struct trf_mgmt_filter { ++ uint32 dst_ip_addr; /* His IP address */ ++ uint16 dst_port; /* His L4 port */ ++ uint16 src_port; /* My L4 port */ ++ uint16 prot; /* L4 protocol (only TCP or UDP protocols) */ ++ uint16 flags; /* TBD. For now, this must be zero. */ ++ trf_mgmt_priority_class_t priority; /* 802.1p priority for filtered packets */ ++} trf_mgmt_filter_t; ++ ++/* Traffic management filter list (variable length) */ ++typedef struct trf_mgmt_filter_list { ++ uint32 num_filters; ++ trf_mgmt_filter_t filter[1]; ++} trf_mgmt_filter_list_t; ++ ++/* Traffic management shaping info */ ++typedef struct trf_mgmt_shaping_info { ++ uint32 max_bps; /* Max bytes consumed or produced per second */ ++ uint32 max_bytes_per_sampling_period; /* Max bytes consumed or produced per sample */ ++ uint32 shaping_delay_threshold; /* Theshold for starting traffic delays */ ++ uint32 num_bytes_produced_per_sec; /* Bytes produced over the sampling period */ ++ uint32 num_bytes_consumed_per_sec; /* Bytes consumed over the sampling period */ ++} trf_mgmt_shaping_info_t; ++ ++/* Traffic management shaping info array */ ++typedef struct trf_mgmt_shaping_info_array { ++ trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_shaping_info_array_t; ++ ++ ++/* Traffic management statistical counters */ ++typedef struct trf_mgmt_stats { ++ uint32 num_processed_packets; /* Number of packets processed */ ++ uint32 num_processed_bytes; /* Number of bytes processed */ ++ uint32 num_queued_packets; /* Number of packets in queue */ ++ uint32 num_queued_bytes; /* Number of bytes in queue */ ++ uint32 num_discarded_packets; /* Number of packets discarded from queue */ ++} trf_mgmt_stats_t; ++ ++/* Traffic management statisics array */ ++typedef struct trf_mgmt_stats_array { ++ trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_stats_array_t; ++ ++#endif /* _wlioctl_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/aiutils.c b/drivers/bcmdrivers/gmac/src/shared/aiutils.c +new file mode 100755 +index 0000000..eed6a11 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/aiutils.c +@@ -0,0 +1,1263 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * $Id: aiutils.c 327582 2012-04-14 05:02:37Z $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "siutils_priv.h" ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#include "hx4_erom.h" ++#elif defined(CONFIG_MACH_HR2) ++#include "hr2_erom.h" ++#elif defined(CONFIG_MACH_NSP) ++#include "nsp_erom.h" ++#elif defined(CONFIG_MACH_KT2) ++#include "kt2_erom.h" ++#endif ++ ++#include ++ ++#define BCM47162_DMP() ((CHIPID(sih->chip) == BCM47162_CHIP_ID) && \ ++ (CHIPREV(sih->chiprev) == 0) && \ ++ (sii->coreid[sii->curidx] == MIPS74K_CORE_ID)) ++ ++#define BCM5357_DMP() (((CHIPID(sih->chip) == BCM5357_CHIP_ID) || \ ++ (CHIPID(sih->chip) == BCM4749_CHIP_ID)) && \ ++ (sih->chippkg == BCM5357_PKG_ID) && \ ++ (sii->coreid[sii->curidx] == USB20H_CORE_ID)) ++ ++/* EROM parsing */ ++ ++static uint32 ++get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match) ++{ ++ uint32 ent; ++ uint inv = 0, nom = 0; ++ ++ while (TRUE) { ++#if defined(CONFIG_MACH_NS) ++ ent = R_REG(si_osh(sih), *eromptr); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_HR2) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_NSP) ++ ent = **eromptr; ++#elif defined(CONFIG_MACH_KT2) ++ ent = **eromptr; ++#endif ++ ++ (*eromptr)++; ++ ++ if (mask == 0) ++ break; ++ ++ if ((ent & ER_VALID) == 0) { ++ inv++; ++ continue; ++ } ++ ++ if (ent == (ER_END | ER_VALID)) ++ break; ++ ++ if ((ent & mask) == match) ++ break; ++ ++ nom++; ++ } ++ ++ SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent)); ++ if (inv + nom) { ++ SI_VMSG((" after %d invalid and %d non-matching entries\n", inv, nom)); ++ } ++ return ent; ++} ++ ++static uint32 ++get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh, ++ uint32 *sizel, uint32 *sizeh) ++{ ++ uint32 asd, sz, szd; ++ ++ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); ++ if (((asd & ER_TAG1) != ER_ADD) || ++ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || ++ ((asd & AD_ST_MASK) != st)) { ++ /* This is not what we want, "push" it back */ ++ (*eromptr)--; ++ return 0; ++ } ++ *addrl = asd & AD_ADDR_MASK; ++ if (asd & AD_AG32) ++ *addrh = get_erom_ent(sih, eromptr, 0, 0); ++ else ++ *addrh = 0; ++ *sizeh = 0; ++ sz = asd & AD_SZ_MASK; ++ if (sz == AD_SZ_SZD) { ++ szd = get_erom_ent(sih, eromptr, 0, 0); ++ *sizel = szd & SD_SZ_MASK; ++ if (szd & SD_SG32) ++ *sizeh = get_erom_ent(sih, eromptr, 0, 0); ++ } else ++ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); ++ ++ SI_VMSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n", ++ sp, ad, st, *sizeh, *sizel, *addrh, *addrl)); ++ ++ return asd; ++} ++ ++static void ++ai_hwfixup(si_info_t *sii) ++{ ++#ifdef _CFE_ ++ /* Fixup the interrupts in 4716 for i2s core so that ai_flag ++ * works without having to look at the core sinking the ++ * interrupt. We should have done this as the hardware default. ++ * ++ * Future chips should allocate interrupt lines in order (meaning ++ * no line should be skipped), without regard for core index. ++ */ ++ if (BUSTYPE(sii->pub.bustype) == SI_BUS && ++ ((CHIPID(sii->pub.chip) == BCM4716_CHIP_ID) || ++ (CHIPID(sii->pub.chip) == BCM4748_CHIP_ID))) { ++ aidmp_t *i2s, *pcie, *cpu; ++ ++ ASSERT(sii->coreid[3] == MIPS74K_CORE_ID); ++ cpu = REG_MAP(sii->wrapba[3], SI_CORE_SIZE); ++ ASSERT(sii->coreid[5] == PCIE_CORE_ID); ++ pcie = REG_MAP(sii->wrapba[5], SI_CORE_SIZE); ++ ASSERT(sii->coreid[8] == I2S_CORE_ID); ++ i2s = REG_MAP(sii->wrapba[8], SI_CORE_SIZE); ++ if ((R_REG(sii->osh, &cpu->oobselina74) != 0x08060504) || ++ (R_REG(sii->osh, &pcie->oobselina74) != 0x08060504) || ++ (R_REG(sii->osh, &i2s->oobselouta30) != 0x88)) { ++ SI_VMSG(("Unexpected oob values, not fixing i2s interrupt\n")); ++ } else { ++ /* Move i2s interrupt to oob line 7 instead of 8 */ ++ W_REG(sii->osh, &cpu->oobselina74, 0x07060504); ++ W_REG(sii->osh, &pcie->oobselina74, 0x07060504); ++ W_REG(sii->osh, &i2s->oobselouta30, 0x87); ++ SI_VMSG(("Changed i2s interrupt to use oob line 7 instead of 8\n")); ++ } ++ } ++#endif /* _CFE_ */ ++} ++ ++struct _corerev_entry { ++ uint corerev; ++ uint corerev_alias; ++}; ++static struct _corerev_entry bcm4706_corerev_cc[] = { ++ { 0x1f, CC_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++static struct _corerev_entry bcm4706_corerev_socsram[] = { ++ { 0x05, SOCRAM_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++static struct _corerev_entry bcm4706_corerev_gmac[] = { ++ { 0x00, GMAC_4706B0_CORE_REV }, ++ { 0, 0 } ++}; ++ ++struct _coreid_entry { ++ uint coreid; ++ uint coreid_alias; ++}; ++static struct _coreid_entry bcm4706_coreid_table[] = { ++ { CC_4706_CORE_ID, CC_CORE_ID }, ++ { SOCRAM_4706_CORE_ID, SOCRAM_CORE_ID }, ++ { GMAC_4706_CORE_ID, GMAC_CORE_ID }, ++ { 0, 0 } ++}; ++ ++static uint ++remap_coreid(si_t *sih, uint coreid) ++{ ++ struct _coreid_entry *coreid_table = NULL; ++ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) ++ coreid_table = &bcm4706_coreid_table[0]; ++ ++ if (coreid_table != NULL) { ++ uint i; ++ ++ for (i = 0; coreid_table[i].coreid; i++) { ++ if (coreid_table[i].coreid == coreid) ++ return coreid_table[i].coreid_alias; ++ } ++ } ++ ++ return coreid; ++} ++ ++static uint ++remap_corerev(si_t *sih, uint corerev) ++{ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) { ++ si_info_t *sii = SI_INFO(sih); ++ uint i, coreid = sii->coreid[sii->curidx]; ++ struct _corerev_entry *corerev_table = NULL; ++ ++ if (coreid == CC_CORE_ID) ++ corerev_table = bcm4706_corerev_cc; ++ else if (coreid == GMAC_CORE_ID) ++ corerev_table = bcm4706_corerev_gmac; ++ else if (coreid == SOCRAM_CORE_ID) ++ corerev_table = bcm4706_corerev_socsram; ++ if (corerev_table != NULL) { ++ for (i = 0; corerev_table[i].corerev_alias; i++) ++ if (corerev_table[i].corerev == corerev) ++ return corerev_table[i].corerev_alias; ++ } ++ } ++ ++ return corerev; ++} ++ ++/* parse the enumeration rom to identify all cores */ ++void ++BCMATTACHFN(ai_scan)(si_t *sih, void *regs, uint devid) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = (chipcregs_t *)regs; ++ uint32 erombase, *eromptr, *eromlim; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++#if defined(CONFIG_MACH_NS) ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ eromptr = hx4_erom; ++#elif defined(CONFIG_MACH_HR2) ++ eromptr = hr2_erom; ++#elif defined(CONFIG_MACH_NSP) ++ eromptr = nsp_erom; ++#elif defined(CONFIG_MACH_KT2) ++ eromptr = kt2_erom; ++#endif ++ break; ++ ++ case PCI_BUS: ++ /* Set wrappers address */ ++ sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE); ++ ++ /* Now point the window at the erom */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase); ++ eromptr = regs; ++ break; ++ ++ ++ case PCMCIA_BUS: ++ default: ++ SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype)); ++ ASSERT(0); ++ return; ++ } ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", ++ regs, erombase, eromptr, eromlim)); ++ while (eromptr < eromlim) { ++ uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; ++ uint32 mpd, asd, addrl, addrh, sizel, sizeh; ++ uint i, j, idx; ++ bool br; ++ ++ br = FALSE; ++ ++ /* Grok a component */ ++ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); ++ if (cia == (ER_END | ER_VALID)) { ++ SI_VMSG(("Found END of erom after %d cores\n", sii->numcores)); ++ ai_hwfixup(sii); ++ return; ++ } ++ ++ cib = get_erom_ent(sih, &eromptr, 0, 0); ++ ++ if ((cib & ER_TAG) != ER_CI) { ++ SI_ERROR(("CIA not followed by CIB\n")); ++ goto error; ++ } ++ ++ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; ++ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; ++ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++#ifdef BCMDBG_SI ++ SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " ++ "nsw = %d, nmp = %d & nsp = %d\n", ++ mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp)); ++#else ++ BCM_REFERENCE(crev); ++#endif ++ ++ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) ++ continue; ++ if ((nmw + nsw == 0)) { ++ /* A component which is not a core */ ++ if (cid == OOB_ROUTER_CORE_ID) { ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd != 0) { ++ sii->oob_router = addrl; ++ } ++ } ++ if (cid != GMAC_COMMON_4706_CORE_ID) ++ continue; ++ } ++ ++ idx = sii->numcores; ++ ++ sii->cia[idx] = cia; ++ sii->cib[idx] = cib; ++ sii->coreid[idx] = remap_coreid(sih, cid); ++ ++ for (i = 0; i < nmp; i++) { ++ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ if ((mpd & ER_TAG) != ER_MP) { ++ SI_ERROR(("Not enough MP entries for component 0x%x\n", cid)); ++ goto error; ++ } ++ SI_VMSG((" Master port %d, mp: %d id: %d\n", i, ++ (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT, ++ (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT)); ++ } ++ ++ /* First Slave Address Descriptor should be port 0: ++ * the main register space for the core ++ */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ do { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd != 0) ++ br = TRUE; ++ else { ++ if (br == TRUE) { ++ break; ++ } ++ else if ((addrh != 0) || (sizeh != 0) || ++ (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 =" ++ "0x%x\n", addrh, sizeh, sizel)); ++ SI_ERROR(("First Slave ASD for" ++ "core 0x%04x malformed " ++ "(0x%08x)\n", cid, asd)); ++ goto error; ++ } ++ } ++ } while (1); ++ } ++ sii->coresba[idx] = addrl; ++ sii->coresba_size[idx] = sizel; ++ /* Get any more ASDs in port 0 */ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { ++ sii->coresba2[idx] = addrl; ++ sii->coresba2_size[idx] = sizel; ++ } ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ ++ if (asd == 0) ++ break; ++ j++; ++ } while (1); ++ if (j == 0) { ++ SI_ERROR((" SP %d has no address descriptors\n", i)); ++ goto error; ++ } ++ } ++ ++ /* Now get master wrappers */ ++ for (i = 0; i < nmw; i++) { ++ asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ SI_ERROR(("Missing descriptor for MW %d\n", i)); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("Master wrapper %d is not 4KB\n", i)); ++ goto error; ++ } ++ if (i == 0) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* And finally slave wrappers */ ++ for (i = 0; i < nsw; i++) { ++ uint fwp = (nsp == 1) ? 0 : 1; ++ asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ SI_ERROR(("Missing descriptor for SW %d\n", i)); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ SI_ERROR(("Slave wrapper %d is not 4KB\n", i)); ++ goto error; ++ } ++ if ((nmw == 0) && (i == 0)) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ if (CHIPID(sih->chip) == BCM4706_CHIP_ID) { ++ /* Check if it's a low cost package */ ++ i = (R_REG(sii->osh, &cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ if (i == BCM4706L_PKG_ID) { ++ /* bcm4706L: only one GMAC */ ++ if (cid == GMAC_4706_CORE_ID) { ++ for (j = 0; j < sii->numcores; j++) { ++ if (sii->coreid[j] == GMAC_CORE_ID) ++ break; ++ } ++ if (j != sii->numcores) { ++ /* Found one GMAC already, ignore this one */ ++ continue; ++ } ++ } ++ } ++ } ++ ++ /* Don't record bridges */ ++ if (br) ++ continue; ++ ++ /* Done with core */ ++ sii->numcores++; ++ } ++ ++ SI_ERROR(("Reached end of erom without finding END")); ++ ++error: ++ sii->numcores = 0; ++ return; ++} ++ ++/* This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. ++ */ ++void * ++ai_setcoreidx(si_t *sih, uint coreidx) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 addr, wrap; ++ void *regs; ++ ++ if (coreidx >= MIN(sii->numcores, SI_MAXCORES)) ++ return (NULL); ++ ++ addr = sii->coresba[coreidx]; ++ wrap = sii->wrapba[coreidx]; ++ ++ /* ++ * If the user has provided an interrupt mask enabled function, ++ * then assert interrupts are disabled before switching the core. ++ */ ++ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ /* map new one */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ sii->curmap = regs = sii->regs[coreidx]; ++ if (!sii->wrappers[coreidx]) { ++ sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->wrappers[coreidx])); ++ } ++ sii->curwrap = sii->wrappers[coreidx]; ++ break; ++ ++ case PCI_BUS: ++ /* point bar0 window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, addr); ++ regs = sii->curmap; ++ /* point bar0 2nd 4KB window to the primary wrapper */ ++ if (PCIE_GEN2(sii)) ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap); ++ else ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, wrap); ++ break; ++ ++ ++ case PCMCIA_BUS: ++ default: ++ ASSERT(0); ++ regs = NULL; ++ break; ++ } ++ ++ sii->curmap = regs; ++ sii->curidx = coreidx; ++ ++ return regs; ++} ++ ++void ++ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = NULL; ++ uint32 erombase, *eromptr, *eromlim; ++ uint i, j, cidx; ++ uint32 cia, cib, nmp, nsp; ++ uint32 asd, addrl, addrh, sizel, sizeh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ if (sii->coreid[i] == CC_CORE_ID) { ++ cc = (chipcregs_t *)sii->regs[i]; ++ break; ++ } ++ } ++ if (cc == NULL) ++ goto error; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ cidx = sii->curidx; ++ cia = sii->cia[cidx]; ++ cib = sii->cib[cidx]; ++ ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++ /* scan for cores */ ++ while (eromptr < eromlim) { ++ if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) && ++ (get_erom_ent(sih, &eromptr, 0, 0) == cib)) { ++ break; ++ } ++ } ++ ++ /* skip master ports */ ++ for (i = 0; i < nmp; i++) ++ get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ ++ /* Skip ASDs in port 0 */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ } ++ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) ++ break; ++ ++ if (!asidx--) { ++ *addr = addrl; ++ *size = sizel; ++ return; ++ } ++ j++; ++ } while (1); ++ ++ if (j == 0) { ++ SI_ERROR((" SP %d has no address descriptors\n", i)); ++ break; ++ } ++ } ++ ++error: ++ *size = 0; ++ return; ++} ++ ++/* Return the number of address spaces in current core */ ++int ++ai_numaddrspaces(si_t *sih) ++{ ++ return 2; ++} ++ ++/* Return the address of the nth address space in the current core */ ++uint32 ++ai_addrspace(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2[cidx]; ++ else { ++ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx)); ++ return 0; ++ } ++} ++ ++/* Return the size of the nth address space in the current core */ ++uint32 ++ai_addrspacesize(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba_size[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2_size[cidx]; ++ else { ++ SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx)); ++ return 0; ++ } ++} ++ ++uint ++ai_flag(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__)); ++ return sii->curidx; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__)); ++ return sii->curidx; ++ } ++ ai = sii->curwrap; ++//printf("ai=%p, oobselouta30=0x%x\n", ai, R_REG(sii->osh, &ai->oobselouta30)); ++ return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); ++} ++ ++void ++ai_setint(si_t *sih, int siflag) ++{ ++} ++ ++uint ++ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 *map = (uint32 *) sii->curwrap; ++ ++ if (mask || val) { ++ uint32 w = R_REG(sii->osh, map+(offset/4)); ++ w &= ~mask; ++ w |= val; ++ W_REG(sii->osh, map+(offset/4), val); ++ } ++ ++ return (R_REG(sii->osh, map+(offset/4))); ++} ++ ++uint ++ai_corevendor(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cia; ++ ++ sii = SI_INFO(sih); ++ cia = sii->cia[sii->curidx]; ++ return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT); ++} ++ ++uint ++ai_corerev(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cib; ++ ++ sii = SI_INFO(sih); ++ cib = sii->cib[sii->curidx]; ++ return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT); ++} ++ ++bool ++ai_iscoreup(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ ++ return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) && ++ ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0)); ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, ++ * switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fiddling with interrupts or core switches is needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers ++ * and (on newer pci cores) chipcommon registers. ++ */ ++uint ++ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ uint origidx = 0; ++ uint32 *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = FALSE; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODIDX(coreidx)); ++ ASSERT(regoff < SI_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) { ++ /* If internal bus, we can always get at everything */ ++ fast = TRUE; ++ /* map if does not exist */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], ++ SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff); ++ } else if (BUSTYPE(sih->bustype) == PCI_BUS) { ++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ ++ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ ++ fast = TRUE; ++ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* pci registers are at either in the last 2KB of an 8KB window ++ * or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = TRUE; ++ if (SI_FAST(sii)) ++ r = (uint32 *)((char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (uint32 *)((char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + ++ regoff); ++ } ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = si_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ASSERT(r != NULL); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_REG(sii->osh, r) & ~mask) | val; ++ W_REG(sii->osh, r, w); ++ } ++ ++ /* readback */ ++ w = R_REG(sii->osh, r); ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return (w); ++} ++ ++void ++ai_core_disable(si_t *sih, uint32 bits) ++{ ++ si_info_t *sii; ++ volatile uint32 dummy; ++ uint32 status; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ /* if core is already in reset, just return */ ++ if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) ++ return; ++ ++ /* ensure there are no pending backplane operations */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); ++ ++ /* if pending backplane ops still, try waiting longer */ ++ if (status != 0) { ++ /* 300usecs was sufficient to allow backplane ops to clear for big hammer */ ++ /* during driver load we may need more time */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000); ++ /* if still pending ops, continue on and try disable anyway */ ++ /* this is in big hammer path, so don't call wl_reinit in this case... */ ++#ifdef BCMDBG ++ if (status != 0) { ++ printf("%s: WARN: resetstatus=%0x on core disable\n", __FUNCTION__, status); ++ } ++#endif ++ } ++ ++ W_REG(sii->osh, &ai->ioctrl, bits); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(10); ++ ++ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ++ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ volatile uint32 dummy; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ bits = resetbits = R_REG(sii->osh, &ai->ioctrl) & 0xFFFFFFFC; ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ ai_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ ++ W_REG(sii->osh, &ai->resetctrl, 0); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++void ++ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__)); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__)); ++ return; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++} ++ ++uint32 ++ai_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__)); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__)); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++ ++ return R_REG(sii->osh, &ai->ioctrl); ++} ++ ++uint32 ++ai_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", ++ __FUNCTION__)); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n", ++ __FUNCTION__)); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SISF_CORE_BITS) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); ++ W_REG(sii->osh, &ai->iostatus, w); ++ } ++ ++ return R_REG(sii->osh, &ai->iostatus); ++} ++ ++#if defined(BCMDBG) ++/* print interesting aidmp registers */ ++void ++ai_dumpregs(si_t *sih, struct bcmstrbuf *b) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ osh = sii->osh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(&sii->pub, i); ++ ai = sii->curwrap; ++ ++ bcm_bprintf(b, "core 0x%x: \n", sii->coreid[i]); ++ if (BCM47162_DMP()) { ++ bcm_bprintf(b, "Skipping mips74k in 47162a0\n"); ++ continue; ++ } ++ if (BCM5357_DMP()) { ++ bcm_bprintf(b, "Skipping usb20h in 5357\n"); ++ continue; ++ } ++ ++ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" ++ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" ++ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x resetwriteid 0x%x\n" ++ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" ++ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" ++ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" ++ "intstatus 0x%x config 0x%x itcr 0x%x\n", ++ R_REG(osh, &ai->ioctrlset), ++ R_REG(osh, &ai->ioctrlclear), ++ R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->ioctrlwidth), ++ R_REG(osh, &ai->iostatuswidth), ++ R_REG(osh, &ai->resetctrl), ++ R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), ++ R_REG(osh, &ai->resetwriteid), ++ R_REG(osh, &ai->errlogctrl), ++ R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), ++ R_REG(osh, &ai->errlogaddrlo), ++ R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogid), ++ R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), ++ R_REG(osh, &ai->intstatus), ++ R_REG(osh, &ai->config), ++ R_REG(osh, &ai->itcr)); ++ if ((sih->chip == BCM4331_CHIP_ID) && (sii->coreid[i] == PCIE_CORE_ID)) { ++ /* point bar0 2nd 4KB window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18103000); ++ bcm_bprintf(b, "ioctrlset 0x%x ioctrlclear 0x%x ioctrl 0x%x iostatus 0x%x" ++ "ioctrlwidth 0x%x iostatuswidth 0x%x\n" ++ "resetctrl 0x%x resetstatus 0x%x resetreadid 0x%x" ++ " resetwriteid 0x%x\n" ++ "errlogctrl 0x%x errlogdone 0x%x errlogstatus 0x%x" ++ "errlogaddrlo 0x%x errlogaddrhi 0x%x\n" ++ "errlogid 0x%x errloguser 0x%x errlogflags 0x%x\n" ++ "intstatus 0x%x config 0x%x itcr 0x%x\n", ++ R_REG(osh, &ai->ioctrlset), ++ R_REG(osh, &ai->ioctrlclear), ++ R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->ioctrlwidth), ++ R_REG(osh, &ai->iostatuswidth), ++ R_REG(osh, &ai->resetctrl), ++ R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), ++ R_REG(osh, &ai->resetwriteid), ++ R_REG(osh, &ai->errlogctrl), ++ R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), ++ R_REG(osh, &ai->errlogaddrlo), ++ R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogid), ++ R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), ++ R_REG(osh, &ai->intstatus), ++ R_REG(osh, &ai->config), ++ R_REG(osh, &ai->itcr)); ++ /* bar0 2nd 4KB window will be fixed in the next setcore */ ++ } ++ } ++} ++#endif ++ ++#ifdef BCMDBG ++static void ++_ai_view(osl_t *osh, aidmp_t *ai, uint32 cid, uint32 addr, bool verbose) ++{ ++ uint32 config; ++ ++ config = R_REG(osh, &ai->config); ++ SI_ERROR(("\nCore ID: 0x%x, addr 0x%x, config 0x%x\n", cid, addr, config)); ++ ++ if (config & AICFG_RST) ++ SI_ERROR(("resetctrl 0x%x, resetstatus 0x%x, resetreadid 0x%x, resetwriteid 0x%x\n", ++ R_REG(osh, &ai->resetctrl), R_REG(osh, &ai->resetstatus), ++ R_REG(osh, &ai->resetreadid), R_REG(osh, &ai->resetwriteid))); ++ ++ if (config & AICFG_IOC) ++ SI_ERROR(("ioctrl 0x%x, width %d\n", R_REG(osh, &ai->ioctrl), ++ R_REG(osh, &ai->ioctrlwidth))); ++ ++ if (config & AICFG_IOS) ++ SI_ERROR(("iostatus 0x%x, width %d\n", R_REG(osh, &ai->iostatus), ++ R_REG(osh, &ai->iostatuswidth))); ++ ++ if (config & AICFG_ERRL) { ++ SI_ERROR(("errlogctrl 0x%x, errlogdone 0x%x, errlogstatus 0x%x, intstatus 0x%x\n", ++ R_REG(osh, &ai->errlogctrl), R_REG(osh, &ai->errlogdone), ++ R_REG(osh, &ai->errlogstatus), R_REG(osh, &ai->intstatus))); ++ SI_ERROR(("errlogid 0x%x, errloguser 0x%x, errlogflags 0x%x, errlogaddr " ++ "0x%x/0x%x\n", ++ R_REG(osh, &ai->errlogid), R_REG(osh, &ai->errloguser), ++ R_REG(osh, &ai->errlogflags), R_REG(osh, &ai->errlogaddrhi), ++ R_REG(osh, &ai->errlogaddrlo))); ++ } ++ ++ if (verbose && (config & AICFG_OOB)) { ++ SI_ERROR(("oobselina30 0x%x, oobselina74 0x%x\n", ++ R_REG(osh, &ai->oobselina30), R_REG(osh, &ai->oobselina74))); ++ SI_ERROR(("oobselinb30 0x%x, oobselinb74 0x%x\n", ++ R_REG(osh, &ai->oobselinb30), R_REG(osh, &ai->oobselinb74))); ++ SI_ERROR(("oobselinc30 0x%x, oobselinc74 0x%x\n", ++ R_REG(osh, &ai->oobselinc30), R_REG(osh, &ai->oobselinc74))); ++ SI_ERROR(("oobselind30 0x%x, oobselind74 0x%x\n", ++ R_REG(osh, &ai->oobselind30), R_REG(osh, &ai->oobselind74))); ++ SI_ERROR(("oobselouta30 0x%x, oobselouta74 0x%x\n", ++ R_REG(osh, &ai->oobselouta30), R_REG(osh, &ai->oobselouta74))); ++ SI_ERROR(("oobseloutb30 0x%x, oobseloutb74 0x%x\n", ++ R_REG(osh, &ai->oobseloutb30), R_REG(osh, &ai->oobseloutb74))); ++ SI_ERROR(("oobseloutc30 0x%x, oobseloutc74 0x%x\n", ++ R_REG(osh, &ai->oobseloutc30), R_REG(osh, &ai->oobseloutc74))); ++ SI_ERROR(("oobseloutd30 0x%x, oobseloutd74 0x%x\n", ++ R_REG(osh, &ai->oobseloutd30), R_REG(osh, &ai->oobseloutd74))); ++ SI_ERROR(("oobsynca 0x%x, oobseloutaen 0x%x\n", ++ R_REG(osh, &ai->oobsynca), R_REG(osh, &ai->oobseloutaen))); ++ SI_ERROR(("oobsyncb 0x%x, oobseloutben 0x%x\n", ++ R_REG(osh, &ai->oobsyncb), R_REG(osh, &ai->oobseloutben))); ++ SI_ERROR(("oobsyncc 0x%x, oobseloutcen 0x%x\n", ++ R_REG(osh, &ai->oobsyncc), R_REG(osh, &ai->oobseloutcen))); ++ SI_ERROR(("oobsyncd 0x%x, oobseloutden 0x%x\n", ++ R_REG(osh, &ai->oobsyncd), R_REG(osh, &ai->oobseloutden))); ++ SI_ERROR(("oobaextwidth 0x%x, oobainwidth 0x%x, oobaoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobaextwidth), R_REG(osh, &ai->oobainwidth), ++ R_REG(osh, &ai->oobaoutwidth))); ++ SI_ERROR(("oobbextwidth 0x%x, oobbinwidth 0x%x, oobboutwidth 0x%x\n", ++ R_REG(osh, &ai->oobbextwidth), R_REG(osh, &ai->oobbinwidth), ++ R_REG(osh, &ai->oobboutwidth))); ++ SI_ERROR(("oobcextwidth 0x%x, oobcinwidth 0x%x, oobcoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobcextwidth), R_REG(osh, &ai->oobcinwidth), ++ R_REG(osh, &ai->oobcoutwidth))); ++ SI_ERROR(("oobdextwidth 0x%x, oobdinwidth 0x%x, oobdoutwidth 0x%x\n", ++ R_REG(osh, &ai->oobdextwidth), R_REG(osh, &ai->oobdinwidth), ++ R_REG(osh, &ai->oobdoutwidth))); ++ } ++} ++ ++void ++ai_view(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint32 cid, addr; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ osh = sii->osh; ++ if (BCM47162_DMP()) { ++ SI_ERROR(("Cannot access mips74k DMP in 47162a0\n")); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("Cannot access usb20h DMP in 5357\n")); ++ return; ++ } ++ cid = sii->coreid[sii->curidx]; ++ addr = sii->wrapba[sii->curidx]; ++ _ai_view(osh, ai, cid, addr, verbose); ++} ++ ++void ++ai_viewall(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ osl_t *osh; ++ aidmp_t *ai; ++ uint32 cid, addr; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ osh = sii->osh; ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(sih, i); ++ if (BCM47162_DMP()) { ++ SI_ERROR(("Skipping mips74k DMP in 47162a0\n")); ++ continue; ++ } ++ if (BCM5357_DMP()) { ++ SI_ERROR(("Skipping usb20h DMP in 5357\n")); ++ continue; ++ } ++ ai = sii->curwrap; ++ cid = sii->coreid[sii->curidx]; ++ addr = sii->wrapba[sii->curidx]; ++ _ai_view(osh, ai, cid, addr, verbose); ++ if ((sih->chip == BCM4331_CHIP_ID) && (sii->coreid[i] == PCIE_CORE_ID)) { ++ /* point bar0 2nd 4KB window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18103000); ++ _ai_view(osh, ai, cid, 0x18103000, verbose); ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18104000); ++ _ai_view(osh, ai, 0x135, 0x18104000, verbose); ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 4, 0x18105000); ++ _ai_view(osh, ai, 0x135, 0x18105000, verbose); ++ /* bar0 2nd 4KB window will be fixed in the next setcore */ ++ } ++ } ++} ++#endif /* BCMDBG */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c +new file mode 100755 +index 0000000..58e66fc +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5221.c +@@ -0,0 +1,509 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "../../../mdio/iproc_mdio.h" ++#include "bcmiproc_phy.h" ++#include "bcmiproc_phy5221.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++ ++/* ==== Public Functions ================================================= */ ++ ++int ++phy5221_wr_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ uint16 wr_data=*data; ++ uint16 test_reg; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data)); ++ //printf("%s going to write phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, wr_data); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } ++ return SOC_E_NONE; ++} ++ ++ ++int ++phy5221_rd_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ uint16 test_reg; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to read phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr)); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ } ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, *data)); ++ //printf("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); ++ return SOC_E_NONE; ++} ++ ++ ++int ++phy5221_mod_reg(uint eth_num, uint phyaddr, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask) ++{ ++ uint16 test_reg; ++ uint16 org_data, rd_data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, data, mask)); ++ ++ if (reg_bank) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1f, &test_reg); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, (test_reg | 0x0080)); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1f, test_reg); ++ } else { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ } ++ //printf("%s modified(0x%x to 0x%x) at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); ++ ++ return SOC_E_NONE; ++} ++ ++ ++void ++phy5221_fe_reset(uint eth_num, uint phyaddr) ++{ ++ uint16 ctrl; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ctrl |= MII_CTRL_RESET; ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ++ SPINWAIT( (!phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) ++ && (ctrl & MII_CTRL_RESET)), 100000); ++ /* check if out of reset */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ if (ctrl & MII_CTRL_RESET) { ++ /* timeout */ ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } else { ++ NET_ERROR(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); ++ } ++ ++ return; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_fe_init ++ * Purpose: ++ * Initialize the PHY (MII mode) to a known good state. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * Returns: ++ * SOC_E_XXX ++ ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5221_fe_init(uint eth_num, uint phyaddr) ++{ ++ uint16 mii_ana, mii_ctrl; ++ ++ /* Reset PHY */ ++ phy5221_fe_reset(eth_num, phyaddr); ++ ++ mii_ana = MII_ANA_HD_10 | MII_ANA_FD_10 | MII_ANA_HD_100 | ++ MII_ANA_FD_100 | MII_ANA_ASF_802_3; ++ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_100 | MII_CTRL_AE | MII_CTRL_RAN; ++ ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5221_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5221_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_init(uint eth_num, uint phyaddr) ++{ ++ uint16 phyid0, phyid1; ++ uint16 tmp = 0; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); ++ ++ //printf("%s phyaddr(0x%x) Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyaddr, phyid1, phyid0); ++ ++ phy5221_fe_init(eth_num, phyaddr); ++ ++ phy5221_rd_reg(eth_num, phyaddr, 0, 0x16, &tmp); ++ tmp = 2; ++ phy5221_wr_reg(eth_num, phyaddr, 0, 0x16, &tmp); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_link_get ++ * Purpose: ++ * Determine the current link up/down status ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5221_link_get(uint eth_num, uint phyaddr, int *link) ++{ ++ uint16 mii_ctrl, mii_stat; ++ uint32 wait; ++ ++ *link = FALSE; /* Default */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ /* the first read of status register will not show link up, second read will show link up */ ++ if (!(mii_stat & MII_STAT_LA) ) { ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ } ++ ++ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { ++ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ ++ return SOC_E_NONE; ++ } ++ ++ /* Link appears to be up; we are done if autoneg is off. */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ if (!(mii_ctrl & MII_CTRL_AE)) { ++ *link = TRUE; ++ return SOC_E_NONE; ++ } ++ ++ /* ++ * If link appears to be up but autonegotiation is still in ++ * progress, wait for it to complete. For BCM5228, autoneg can ++ * still be busy up to about 200 usec after link is indicated. Also ++ * continue to check link state in case it goes back down. ++ * wait 500ms (500000us/10us = 50000 ) ++ */ ++ for (wait=0; wait<50000; wait++) { ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (!(mii_stat & MII_STAT_LA)) { ++ /* link is down */ ++ return SOC_E_NONE; ++ } ++ ++ if (mii_stat & MII_STAT_AN_DONE) { ++ /* AutoNegotiation done */ ++ break; ++ } ++ ++ OSL_DELAY(10); ++ } ++ if (wait>=50000) { ++ /* timeout */ ++ return SOC_E_BUSY; ++ } ++ ++ /* Return link state at end of polling */ ++ *link = ((mii_stat & MII_STAT_LA) != 0); ++ ++ return SOC_E_NONE; ++} ++ ++ ++/* ++ * Function: ++ * phy5221_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_enable_set(uint eth_num, uint phyaddr, int enable) ++{ ++ uint16 data; /* New value to write to PHY register */ ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ data = enable ? 0 : MII_ECR_TD; /* Transmitt enable/disable */ ++ phy5221_mod_reg(eth_num, phyaddr, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, data, MII_ECR_TD); ++ ++ data = enable ? 0 : PHY522X_SUPER_ISOLATE_MODE; ++ /* Device needs to be put in super-isolate mode in order to disable ++ * the link in 10BaseT mode ++ */ ++ phy5221_mod_reg(eth_num, phyaddr, PHY_AUX_MULTIPLE_PHYr_BANK, PHY_AUX_MULTIPLE_PHYr_ADDR, ++ data, PHY522X_SUPER_ISOLATE_MODE); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5221_auto_negotiate_gcd (greatest common denominator). ++ * Purpose: ++ * Determine the current greatest common denominator between ++ * two ends of a link ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * speed - (OUT) greatest common speed. ++ * duplex - (OUT) greatest common duplex. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++static int ++phy5221_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int t_speed, t_duplex; ++ uint16 mii_ana, mii_anp, mii_stat; ++ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; ++ ++ mii_gb_stat = 0; /* Start off 0 */ ++ mii_gb_ctrl = 0; /* Start off 0 */ ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ ++ /* ++ * If the PHY supports extended status, check if it is 1000MB ++ * capable. If it is, check the 1000Base status register to see ++ * if 1000MB negotiated. ++ */ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); ++ ++ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | ++ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ } ++ } ++ ++ /* ++ * At this point, if we did not see Gig status, one of mii_gb_stat or ++ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to ++ * fail and fall into the default 10/100 cases. ++ */ ++ ++ mii_ana &= mii_anp; ++ ++ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { ++ t_speed = 1000; ++ t_duplex = 1; ++ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { ++ t_speed = 1000; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ ++ t_speed = 100; ++ t_duplex = 1; ++ } else if (mii_ana & MII_ANA_T4) { /* [b] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ ++ t_speed = 10; ++ t_duplex = 1 ; ++ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ ++ t_speed = 10; ++ t_duplex = 0; ++ } else { ++ return(SOC_E_FAIL); ++ } ++ ++ if (speed) *speed = t_speed; ++ if (duplex) *duplex = t_duplex; ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5221_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++phy5221_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int rv; ++ uint16 mii_ctrl, mii_stat; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5221_rd_reg(eth_num, phyaddr, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ *speed = 0; ++ *duplex = 0; ++ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ ++ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ ++ rv = SOC_E_NONE; ++ } else { ++ rv = phy5221_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); ++ } ++ } else { /* Auto-negotiation disabled */ ++ /* ++ * Simply pick up the values we force in CTRL register. ++ */ ++ if (mii_ctrl & MII_CTRL_FD) ++ *duplex = 1; ++ ++ switch(MII_CTRL_SS(mii_ctrl)) { ++ case MII_CTRL_SS_10: ++ *speed = 10; ++ break; ++ case MII_CTRL_SS_100: ++ *speed = 100; ++ break; ++ case MII_CTRL_SS_1000: ++ *speed = 1000; ++ break; ++ default: /* Just pass error back */ ++ return(SOC_E_UNAVAIL); ++ } ++ rv = SOC_E_NONE; ++ } ++ ++ return(rv); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c +new file mode 100755 +index 0000000..6b2391d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_phy5461s.c +@@ -0,0 +1,734 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the external phy ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "../../../mdio/iproc_mdio.h" ++#include "bcmiproc_phy.h" ++#include "bcmiproc_phy5461s.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++ ++/* ==== Public Functions ================================================= */ ++ ++int ++phy5461_wr_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ int rv = SOC_E_NONE; ++ uint16 wr_data=*data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to write phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data)); ++ //printf("%s phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, wr_data); ++ ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* write 1000X IEEE register */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else if (flags & _SOC_PHY_REG_DIRECT) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ if (reg_bank == 0x0007) { ++ wr_data |= 0x8000; ++ } ++ wr_data = (wr_data & ~(0x0007)) | reg_bank; ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ wr_data = 0x8000 | (reg_bank << 10) | (wr_data & 0x03FF); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not write to reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, wr_data); ++ } ++ } ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } ++ return rv; ++} ++ ++ ++int ++phy5461_rd_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 *data) ++{ ++ int rv = SOC_E_NONE; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to read phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr)); ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* Read 1000X IEEE register */ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not read from reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, *data)); ++ } ++ } ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } else { ++ //printf("%s phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg_bank, reg_addr, *data); ++ } ++ ++ return rv; ++} ++ ++ ++int ++phy5461_mod_reg(uint eth_num, uint phyaddr, uint32 flags, uint16 reg_bank, ++ uint8 reg_addr, uint16 data, uint16 mask) ++{ ++ int rv = SOC_E_NONE; ++ uint16 org_data, rd_data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s going to modify phyaddr(0x%x) flags(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x) mask(0x%x)\n", ++ __FUNCTION__, phyaddr, flags, reg_bank, reg_addr, data, mask)); ++ ++ if (flags & SOC_PHY_REG_1000X) { ++ if (reg_addr <= 0x000f) { ++ uint16 blk_sel; ++ ++ /* Map 1000X page */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, 0x7c00); ++ ccb_mii_read(MII_DEV_EXT, phyaddr, 0x1c, &blk_sel); ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, blk_sel | 0x8001); ++ ++ /* Modify 1000X IEEE register */ ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ ++ /* Restore IEEE mapping */ ++ ccb_mii_write(MII_DEV_EXT, phyaddr, 0x1c, (blk_sel & 0xfffe) | 0x8000); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ } else { ++ switch(reg_addr) { ++ /* Map shadow registers */ ++ case 0x18: ++ if (reg_bank <= 0x0007) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 12) | 0x7); ++ ++ if (reg_bank == 0x0007) { ++ data |= 0x8000; ++ mask |= 0x8000; ++ } ++ mask &= ~(0x0007); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ case 0x1C: ++ if (reg_bank <= 0x001F) { ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, (reg_bank << 10)); ++ data |= 0x8000; ++ mask |= 0x8000; ++ mask &= ~(0x1F << 10); ++ } else { ++ rv = SOC_E_PARAM; ++ } ++ break; ++ default: ++ if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { ++ /* Must not write to reserved registers */ ++ if (reg_addr > 0x001e) { ++ rv = SOC_E_PARAM; ++ } ++ } ++ break; ++ } ++ if (SOC_SUCCESS(rv)) { ++ ccb_mii_read(MII_DEV_EXT, phyaddr, reg_addr, &rd_data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ org_data = rd_data; ++ rd_data &= ~(mask); ++ rd_data |= data; ++ ccb_mii_write(MII_DEV_EXT, phyaddr, reg_addr, rd_data); ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rd_data)); ++ } ++ } ++ ++ if (SOC_FAILURE(rv)) { ++ NET_ERROR(("%s ERROR phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x) rv(%d)\n", ++ __FUNCTION__, phyaddr, reg_bank, reg_addr, rv)); ++ } else { ++ //printf("%s modified(0x%x to 0x%x at phyaddr(0x%x) reg_bank(0x%x) reg_addr(0x%x)\n", ++ // __FUNCTION__, org_data, rd_data, phyaddr, reg_bank, reg_addr); ++ } ++ ++ return rv; ++} ++ ++ ++void ++phy5461_ge_reset(uint eth_num, uint phyaddr) ++{ ++ uint16 ctrl; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ctrl |= MII_CTRL_RESET; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ ++ SPINWAIT( (!phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl) ++ && (ctrl & MII_CTRL_RESET)), 100000); ++ /* check if out of reset */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &ctrl); ++ if (ctrl & MII_CTRL_RESET) { ++ /* timeout */ ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } else { ++ NET_TRACE(("et%d: %s reset complete\n", eth_num, __FUNCTION__)); ++ } ++} ++ ++ ++/* ++ * Function: ++ * phy5461_ge_interface_set ++ * Purpose: ++ * Set the current operating mode of the PHY. ++ * (Pertaining to the MAC/PHY interface, not the line interface). ++ * For example: TBI or MII/GMII. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * pif - one of SOC_PORT_IF_* ++ * Returns: ++ * SOC_E_XXX ++ */ ++int ++phy5461_ge_interface_set(uint eth_num, uint phyaddr, soc_port_if_t pif) ++{ ++ uint16 mii_ecr; ++ int mii; /* MII if true, TBI otherwise */ ++ ++ switch (pif) { ++ case SOC_PORT_IF_MII: ++ case SOC_PORT_IF_GMII: ++ case SOC_PORT_IF_SGMII: ++ mii = TRUE; ++ break; ++ case SOC_PORT_IF_NOCXN: ++ return (SOC_E_NONE); ++ case SOC_PORT_IF_TBI: ++ mii = FALSE; ++ break; ++ default: ++ return SOC_E_UNAVAIL; ++ } ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); ++ ++ if (mii) { ++ mii_ecr &= ~MII_ECR_10B; ++ } else { ++ mii_ecr |= MII_ECR_10B; ++ } ++ ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ECRr_FLAGS, PHY_MII_ECRr_BANK, PHY_MII_ECRr_ADDR, &mii_ecr); ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5461_ge_init ++ * Purpose: ++ * Initialize the PHY (MII mode) to a known good state. ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * Returns: ++ * SOC_E_XXX ++ ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5461_ge_init(uint eth_num, uint phyaddr) ++{ ++ uint16 mii_ctrl, mii_gb_ctrl; ++ uint16 mii_ana; ++ soc_port_if_t pif; ++ ++ /* Reset PHY */ ++ phy5461_ge_reset(eth_num, phyaddr); ++ ++ /* set advertized bits */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ mii_ana |= MII_ANA_FD_100 | MII_ANA_FD_10; ++ mii_ana |= MII_ANA_HD_100 | MII_ANA_HD_10; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ ++ mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE | MII_CTRL_RAN; ++ mii_gb_ctrl = MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT; ++ ++ pif = SOC_PORT_IF_GMII; ++ ++ phy5461_ge_interface_set(eth_num, phyaddr, pif); ++ ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ phy5461_wr_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ return(SOC_E_NONE); ++} ++ ++ ++ ++ ++void ++phy5461_reset_setup(uint eth_num, uint phyaddr) ++{ ++ uint16 tmp; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ phy5461_ge_init(eth_num, phyaddr); ++ ++ /* copper regs */ ++ /* remove power down */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, 0, MII_CTRL_PD); ++ /* Disable super-isolate */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_POWER_CTRLr_FLAGS, PHY_MII_POWER_CTRLr_BANK, PHY_MII_POWER_CTRLr_ADDR, 0, 1U<<5); ++ /* Enable extended packet length */ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_AUX_CTRLr_FLAGS, PHY_MII_AUX_CTRLr_BANK, PHY_MII_AUX_CTRLr_ADDR, 0x4000, 0x4000); ++ ++ /* Configure interface to MAC */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); ++ /* phy5461_ge_init has reset the phy, powering down the unstrapped interface */ ++ /* make sure enabled interfaces are powered up */ ++ /* SGMII (passthrough fiber) or GMII fiber regs */ ++ tmp &= ~MII_CTRL_PD; /* remove power down */ ++ /* ++ * Enable SGMII autonegotiation on the switch side so that the ++ * link status changes are reflected in the switch. ++ * On Bradley devices, LAG failover feature depends on the SerDes ++ * link staus to activate failover recovery. ++ */ ++ tmp |= MII_CTRL_AE; ++ phy5461_wr_reg(eth_num, phyaddr, PHY_1000X_MII_CTRLr_FLAGS, PHY_1000X_MII_CTRLr_BANK, PHY_1000X_MII_CTRLr_ADDR, &tmp); ++ ++ return; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_init(uint eth_num, uint phyaddr) ++{ ++ uint16 phyid0, phyid1; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID0r_FLAGS, PHY_MII_PHY_ID0r_BANK, PHY_MII_PHY_ID0r_ADDR, &phyid0); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_PHY_ID1r_FLAGS, PHY_MII_PHY_ID1r_BANK, PHY_MII_PHY_ID1r_ADDR, &phyid1); ++ ++ printf("%s Phy ChipID: 0x%04x:0x%04x\n", __FUNCTION__, phyid1, phyid0); ++ ++ phy5461_reset_setup(eth_num, phyaddr); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_link_get ++ * Purpose: ++ * Determine the current link up/down status ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++int ++phy5461_link_get(uint eth_num, uint phyaddr, int *link) ++{ ++ uint16 mii_ctrl, mii_stat; ++ uint32 wait; ++ ++ *link = FALSE; /* Default */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ /* the first read of status register will not show link up, second read will show link up */ ++ if (!(mii_stat & MII_STAT_LA) ) { ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ } ++ ++ if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { ++ /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ ++ return SOC_E_NONE; ++ } ++ ++ /* Link appears to be up; we are done if autoneg is off. */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ ++ if (!(mii_ctrl & MII_CTRL_AE)) { ++ *link = TRUE; ++ return SOC_E_NONE; ++ } ++ ++ /* ++ * If link appears to be up but autonegotiation is still in ++ * progress, wait for it to complete. For BCM5228, autoneg can ++ * still be busy up to about 200 usec after link is indicated. Also ++ * continue to check link state in case it goes back down. ++ */ ++ for (wait=0; wait<50000; wait++) { ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (!(mii_stat & MII_STAT_LA)) { ++ /* link is down */ ++ return SOC_E_NONE; ++ } ++ ++ if (mii_stat & MII_STAT_AN_DONE) { ++ /* AutoNegotiation done */ ++ break; ++ } ++ ++ OSL_DELAY(10); ++ } ++ if (wait>=50000) { ++ /* timeout */ ++ return SOC_E_BUSY; ++ } ++ ++ /* Return link state at end of polling */ ++ *link = ((mii_stat & MII_STAT_LA) != 0); ++ ++ return SOC_E_NONE; ++} ++ ++ ++/* ++ * Function: ++ * phy5461_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_enable_set(uint eth_num, uint phyaddr, int enable) ++{ ++ uint16 power_down; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ power_down = (enable) ? 0 : MII_CTRL_PD; ++ ++ phy5461_mod_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, power_down, MII_CTRL_PD); ++ ++ return SOC_E_NONE; ++} ++ ++ ++ ++ ++/* ++ * Function: ++ * phy5461_auto_negotiate_gcd (greatest common denominator). ++ * Purpose: ++ * Determine the current greatest common denominator between ++ * two ends of a link ++ * Parameters: ++ * unit - StrataSwitch unit #. ++ * port - StrataSwitch port #. ++ * speed - (OUT) greatest common speed. ++ * duplex - (OUT) greatest common duplex. ++ * link - (OUT) Boolean, true indicates link established. ++ * Returns: ++ * SOC_E_XXX ++ * Notes: ++ * No synchronization performed at this level. ++ */ ++static int ++phy5461_auto_negotiate_gcd(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int t_speed, t_duplex; ++ uint16 mii_ana, mii_anp, mii_stat; ++ uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; ++ ++ mii_gb_stat = 0; /* Start off 0 */ ++ mii_gb_ctrl = 0; /* Start off 0 */ ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANAr_FLAGS, PHY_MII_ANAr_BANK, PHY_MII_ANAr_ADDR, &mii_ana); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ANPr_FLAGS, PHY_MII_ANPr_BANK, PHY_MII_ANPr_ADDR, &mii_anp); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ if (mii_stat & MII_STAT_ES) { /* Supports extended status */ ++ /* ++ * If the PHY supports extended status, check if it is 1000MB ++ * capable. If it is, check the 1000Base status register to see ++ * if 1000MB negotiated. ++ */ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_ESRr_FLAGS, PHY_MII_ESRr_BANK, PHY_MII_ESRr_ADDR, &mii_esr); ++ ++ if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | ++ MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_STATr_FLAGS, PHY_MII_GB_STATr_BANK, PHY_MII_GB_STATr_ADDR, &mii_gb_stat); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_GB_CTRLr_FLAGS, PHY_MII_GB_CTRLr_BANK, PHY_MII_GB_CTRLr_ADDR, &mii_gb_ctrl); ++ } ++ } ++ ++ /* ++ * At this point, if we did not see Gig status, one of mii_gb_stat or ++ * mii_gb_ctrl will be 0. This will cause the first 2 cases below to ++ * fail and fall into the default 10/100 cases. ++ */ ++ ++ mii_ana &= mii_anp; ++ ++ if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { ++ t_speed = 1000; ++ t_duplex = 1; ++ } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && ++ (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { ++ t_speed = 1000; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ ++ t_speed = 100; ++ t_duplex = 1; ++ } else if (mii_ana & MII_ANA_T4) { /* [b] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ ++ t_speed = 100; ++ t_duplex = 0; ++ } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ ++ t_speed = 10; ++ t_duplex = 1 ; ++ } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ ++ t_speed = 10; ++ t_duplex = 0; ++ } else { ++ return(SOC_E_FAIL); ++ } ++ ++ if (speed) *speed = t_speed; ++ if (duplex) *duplex = t_duplex; ++ ++ return(SOC_E_NONE); ++} ++ ++ ++/* ++ * Function: ++ * phy5461_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++phy5461_speed_get(uint eth_num, uint phyaddr, int *speed, int *duplex) ++{ ++ int rv; ++ uint16 mii_ctrl, mii_stat; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_CTRLr_FLAGS, PHY_MII_CTRLr_BANK, PHY_MII_CTRLr_ADDR, &mii_ctrl); ++ phy5461_rd_reg(eth_num, phyaddr, PHY_MII_STATr_FLAGS, PHY_MII_STATr_BANK, PHY_MII_STATr_ADDR, &mii_stat); ++ ++ *speed = 0; ++ *duplex = 0; ++ if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ ++ if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ ++ rv = SOC_E_NONE; ++ } else { ++ rv = phy5461_auto_negotiate_gcd(eth_num, phyaddr, speed, duplex); ++ } ++ } else { /* Auto-negotiation disabled */ ++ /* ++ * Simply pick up the values we force in CTRL register. ++ */ ++ if (mii_ctrl & MII_CTRL_FD) ++ *duplex = 1; ++ ++ switch(MII_CTRL_SS(mii_ctrl)) { ++ case MII_CTRL_SS_10: ++ *speed = 10; ++ break; ++ case MII_CTRL_SS_100: ++ *speed = 100; ++ break; ++ case MII_CTRL_SS_1000: ++ *speed = 1000; ++ break; ++ default: /* Just pass error back */ ++ return(SOC_E_UNAVAIL); ++ } ++ rv = SOC_E_NONE; ++ } ++ ++ return(rv); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c +new file mode 100755 +index 0000000..add347f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_robo_serdes.c +@@ -0,0 +1,428 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include ++#include ++#include "bcmiproc_robo_serdes.h" ++#include "bcmiproc_serdes_def.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++/* ==== Public Functions ================================================= */ ++ ++uint16 ++robo_serdes_get_id(robo_info_t *robo, uint page, uint off) ++{ ++ uint16 data; ++ ++ /* read the id high */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESID_SERDESID0r+off, &data); ++ return data; ++} ++ ++ ++void ++robo_serdes_reset(robo_info_t *robo, uint page) ++{ ++ uint16 ctrl; ++ ++ /* set reset flag */ ++ srab_sgmii_rreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ udelay(100); ++ /* check if out of reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_IEEE0BLK_IEEECONTROL0r, &ctrl); ++ if (ctrl & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { ++ NET_ERROR(("%s page (0x%x) reset not complete\n", __FUNCTION__, page)); ++ } ++} ++ ++ ++int ++robo_serdes_reset_core(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ uint16 serdes_id2; ++ ++ /* get serdes id */ ++ serdes_id2 = robo_serdes_get_id(robo, page, 2); ++ printf("%s page(0x%x) id2(0x%x)\n", __FUNCTION__, page, serdes_id2); ++ ++ /* unlock lane */ ++ srab_sgmii_rreg(robo, page, 0x833c, &data16); ++ data16 &= ~(0x0040); ++ srab_sgmii_wreg(robo, page, 0x833c, &data16); ++ ++ if ( page == PAGE_P5_SGMII ) { ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ ++ /* Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in ++ * IEEE address space. ++ */ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_MISCCONTROL1r, &data16); ++ if (XGXS16G_2p5G_ID(serdes_id2)) { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ } else { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++ } ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_MISCCONTROL1r, &data16); ++ ++ } ++ return 0; ++} ++ ++ ++int ++robo_serdes_start_pll(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ ++ if ( page == PAGE_P5_SGMII ) { ++ uint32 count=250; ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK0_XGXSCONTROLr, &data16); ++ ++ /* wait for PLL to lock */ ++ while (count!=0) { ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK0_XGXSSTATUSr, &data16); ++ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { ++ break; ++ } ++ /* wait 1 usec then dec counter */ ++ udelay(10); ++ count--; ++ } ++ if (count == 0) { ++ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_init(robo_info_t *robo, uint page) ++{ ++ uint16 data16; ++ uint16 serdes_id0, serdes_id1, serdes_id2; ++ uint locpage=page; ++ ++ if ( page == PAGE_P4_SGMII ) { ++ printf("%s access page4 via page5 lane1\n", __FUNCTION__); ++ locpage = PAGE_P5_SGMII; ++ // try to access p4 registers via lane1 ++ data16 = 1; ++ srab_sgmii_wreg(robo, locpage, 0xffde, &data16); ++ } ++ ++ /* get serdes id */ ++ serdes_id0 = robo_serdes_get_id(robo, locpage, 0); ++ serdes_id1 = robo_serdes_get_id(robo, locpage, 1); ++ serdes_id2 = robo_serdes_get_id(robo, locpage, 2); ++ printf("%s page(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, locpage, serdes_id0, serdes_id1, serdes_id2); ++ ++ /* get more ids */ ++ srab_sgmii_rreg(robo, locpage, 2, &serdes_id0); ++ srab_sgmii_rreg(robo, locpage, 3, &serdes_id1); ++ //printf("%s locpage(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, locpage, serdes_id0, serdes_id1); ++ ++ /* unlock lane */ ++ srab_sgmii_rreg(robo, locpage, 0x833c, &data16); ++ data16 &= ~(0x0040); ++ srab_sgmii_wreg(robo, locpage, 0x833c, &data16); ++ ++ /* Must Enable TX polarity flip */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_TX0_TX_ACONTROL0r, &data16); ++ data16 |= TX0_TX_ACONTROL0_TXPOL_FLIP_MASK; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_TX0_TX_ACONTROL0r, &data16); ++ ++ /* disable CL73 BAM */ ++ srab_sgmii_rreg(robo, locpage, 0x8372, &data16); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ srab_sgmii_wreg(robo, locpage, 0x8372, &data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_COMBO_IEEE0_AUTONEGADVr, &data16); ++ ++ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, &data16); ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, &data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK | ++ SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; ++ ++// data16 |= SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK; ++ /* ++ * Put the Serdes in SGMII mode ++ * bit0 = 0; in SGMII mode ++ */ ++ srab_sgmii_wreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, &data16); ++ ++ /* set autoneg */ ++ data16 = MII_CTRL_AE | MII_CTRL_RAN; ++// data16 = MII_CTRL_SS_MSB | MII_CTRL_FD; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_AN73_PDET_PARDET10GCONTROLr, &data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ srab_sgmii_wreg(robo, locpage, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, &data16); ++ ++ /* Enable lanes */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_XGXSBLK1_LANECTRL0r, &data16); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_XGXSBLK1_LANECTRL0r, &data16); ++ ++ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ srab_sgmii_wreg(robo, locpage, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ /* Enabble LPI passthru' for native mode EEE */ ++ srab_sgmii_rreg(robo, locpage, XGXS16G_REMOTEPHY_MISC5r, &data16); ++ data16 |= 0xc000; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_REMOTEPHY_MISC5r, &data16); ++ srab_sgmii_rreg(robo, locpage, XGXS16G_XGXSBLK7_EEECONTROLr, &data16); ++ data16 |= 0x0007; ++ srab_sgmii_wreg(robo, locpage, XGXS16G_XGXSBLK7_EEECONTROLr, &data16); ++ ++ if ( page == PAGE_P4_SGMII ) { ++ printf("%s set back to lane0\n", __FUNCTION__); ++ // set back to lane 0 ++ data16 = 0; ++ srab_sgmii_wreg(robo, locpage, 0xffde, &data16); ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_enable_set ++ * Purpose: ++ * Enable/Disable phy ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * enable - on/off state to set ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_enable_set(robo_info_t *robo, uint page, int enable) ++{ ++ uint16 data16, mask16; ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_XGXSBLK1_LANECTRL3r, &data16); ++ if (page == PAGE_P5_SGMII) ++ /* lane 0 */ ++ mask16 = 1; /* rx lane */ ++ else ++ /* lane 1 */ ++ mask16 = 2; /* rx lane */ ++ mask16 |= (mask16 << 4); /* add tx lane */ ++ mask16 |= 0x800; ++ if (enable) { ++ data16 &= ~(mask16); ++ } else { ++ data16 &= ~(mask16); ++ data16 |= mask16; ++ } ++ srab_sgmii_wreg(robo, page, XGXS16G_XGXSBLK1_LANECTRL3r, &data16); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_speed_set ++ * Purpose: ++ * Set PHY speed ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_speed_set(robo_info_t *robo, uint page, int speed) ++{ ++ uint16 speed_val, mask; ++ uint16 data16; ++ uint16 speed_mii; ++ ++ if (speed > 1000) { ++ return -1; ++ } ++ ++ speed_val = 0; ++ speed_mii = 0; ++ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | ++ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; ++ ++ switch (speed) { ++ case 0: ++ /* Do not change speed */ ++ return 0; ++ case 10: ++ speed_mii = MII_CTRL_SS_10; ++ break; ++ case 100: ++ speed_mii = MII_CTRL_SS_100; ++ break; ++ case 1000: ++ speed_mii = MII_CTRL_SS_1000; ++ break; ++ default: ++ return -1; ++ } ++ ++ /* Hold rxSeqStart */ ++ srab_sgmii_rreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ ++ /* hold TX FIFO in reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_MISC1r, &data16); ++ data16 &= ~(mask); ++ data16 |= speed_val; ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_MISC1r, &data16); ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ data16 &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); ++ data16 |= speed_mii; ++ srab_sgmii_wreg(robo, page, XGXS16G_COMBO_IEEE0_MIICNTLr, &data16); ++ ++ /* release rxSeqStart */ ++ srab_sgmii_rreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); ++ srab_sgmii_wreg(robo, page, XGXS16G_RX0_RX_CONTROLr, &data16); ++ ++ /* release TX FIFO reset */ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); ++ srab_sgmii_wreg(robo, page, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, &data16); ++ ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * robo_serdes_speed_get ++ * Purpose: ++ * Get PHY speed ++ * Parameters: ++ * robo - robo handle ++ * page - port page ++ * speed - current link speed in Mbps ++ * Returns: ++ * 0 ++ */ ++int ++robo_serdes_speed_get(robo_info_t *robo, uint page, int *speed) ++{ ++ uint16 data16; ++ ++ srab_sgmii_rreg(robo, page, XGXS16G_SERDESDIGITAL_STATUS1000X1r, &data16); ++ ++ data16 &= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK; ++ data16 >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT; ++ ++ if (data16 == 3) { ++ *speed= 2500; ++ } else if (data16 == 2) { ++ *speed= 1000; ++ } else if (data16 == 1) { ++ *speed= 100; ++ } else { ++ *speed= 10; ++ } ++ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c +new file mode 100755 +index 0000000..0dda6c6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmiproc_serdes.c +@@ -0,0 +1,481 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * These routines provide access to the serdes ++ * ++ */ ++ ++/* ---- Include Files ---------------------------------------------------- */ ++#include ++#include ++#include "bcmiproc_serdes.h" ++#include "bcmiproc_serdes_def.h" ++#include "../../../mdio/iproc_mdio.h" ++ ++/* ---- External Variable Declarations ----------------------------------- */ ++/* ---- External Function Prototypes ------------------------------------- */ ++/* ---- Public Variables ------------------------------------------------- */ ++/* ---- Private Constants and Types -------------------------------------- */ ++/* ---- Private Variables ------------------------------------------------ */ ++ ++/* debug/trace */ ++//#define BCMDBG ++//#define BCMDBG_ERR ++#ifdef BCMDBG ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) printf args ++#elif defined(BCMDBG_ERR) ++#define NET_ERROR(args) printf args ++#define NET_TRACE(args) ++#else ++#define NET_ERROR(args) ++#define NET_TRACE(args) ++#endif /* BCMDBG */ ++#define NET_REG_TRACE(args) ++ ++ ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++ ++/* ==== Public Functions ================================================= */ ++ ++void ++serdes_set_blk(uint eth_num, uint phyaddr, uint blk) ++{ ++ uint16 blkaddr; ++ uint16 destblk = (uint16)blk; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ NET_REG_TRACE(("%s phyaddr(0x%x) blk(0x%x)\n", ++ __FUNCTION__, phyaddr, blk)); ++ ++ /* check if need to update blk addr */ ++ ccb_mii_read(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, &blkaddr); ++ if (blkaddr!=destblk) { ++ /* write block address */ ++ ccb_mii_write(MII_DEV_LOCAL, phyaddr, PHY_REG_BLK_ADDR, destblk); ++ } ++} ++ ++ ++void ++serdes_wr_reg(uint eth_num, uint phyaddr, uint reg, uint data) ++{ ++ uint blk = reg&0x7ff0; ++ uint off = reg&0x000f; ++ uint16 tmpdata=(uint16)data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* set block address */ ++ serdes_set_blk(eth_num, phyaddr, blk); ++ ++ NET_REG_TRACE(("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg, tmpdata)); ++ //printf("%s wrt phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg, tmpdata); ++ /* write register */ ++ ccb_mii_write(MII_DEV_LOCAL, phyaddr, off, tmpdata); ++} ++ ++ ++uint16 ++serdes_rd_reg(uint eth_num, uint phyaddr, uint reg) ++{ ++ uint blk = reg&0x7ff0; ++ uint off = reg&0x000f; ++ uint16 data; ++ ++ NET_TRACE(("%s enter\n", __FUNCTION__)); ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* set block address */ ++ serdes_set_blk(eth_num, phyaddr, blk); ++ ++ /* read register */ ++ ccb_mii_read(MII_DEV_LOCAL, phyaddr, off, &data); ++ NET_REG_TRACE(("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ __FUNCTION__, phyaddr, reg, data)); ++ //printf("%s rd phyaddr(0x%x) reg(0x%x) data(0x%x)\n", ++ // __FUNCTION__, phyaddr, reg, data); ++ ++ return data; ++} ++ ++ ++uint16 ++serdes_get_id(uint eth_num, uint phyaddr, uint off) ++{ ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return 0; ++ ++ /* read the id high */ ++ return serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESID_SERDESID0r+off); ++} ++ ++ ++void ++serdes_reset(uint eth_num, uint phyaddr) ++{ ++ uint ctrl; ++ ++ ASSERT(phyaddr < MAXEPHY); ++ ++ if (phyaddr == EPHY_NOREG) ++ return; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* set reset flag */ ++ ctrl = serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r); ++ ctrl |= IEEE0BLK_IEEECONTROL0_RST_HW_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r, ctrl); ++ udelay(100); ++ /* check if out of reset */ ++ if (serdes_rd_reg(eth_num, phyaddr, XGXS16G_IEEE0BLK_IEEECONTROL0r) & IEEE0BLK_IEEECONTROL0_RST_HW_MASK) { ++ NET_ERROR(("et%d: %s reset not complete\n", eth_num, __FUNCTION__)); ++ } ++} ++ ++ ++int ++serdes_reset_core(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint16 serdes_id2; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* get serdes id */ ++ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); ++ printf("et%d %s pbyaddr(0x%x) id2(0x%x)\n", eth_num, __FUNCTION__, phyaddr, serdes_id2); ++ ++ /* unlock lane */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x833c); ++ data16 &= ~(0x0040); ++ serdes_wr_reg(eth_num, phyaddr, 0x833c, data16); ++ ++ if ( phyaddr == 1 ) { ++ /* Reset the core */ ++ /* Stop PLL Sequencer and configure the core into correct mode */ ++ data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << ++ XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | ++ XGXSBLK0_XGXSCONTROL_HSTL_MASK | ++ XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_EDEN_MASK | ++ XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | ++ XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* Disable IEEE block select auto-detect. ++ * The driver will select desired block as necessary. ++ * By default, the driver keeps the XAUI block in ++ * IEEE address space. ++ */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r); ++ if (XGXS16G_2p5G_ID(serdes_id2)) { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++ } else { ++ data16 &= ~( XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | ++ XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK); ++#if !defined(CONFIG_MACH_KT2) ++ data16 |= XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; ++#endif /* (!defined(CONFIG_MACH_KT2)) */ ++ } ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_MISCCONTROL1r, data16); ++ ++ /* disable in-band MDIO. PHY-443 */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8111); ++ /* rx_inBandMdio_rst */ ++ data16 |= 1 << 3; ++ serdes_wr_reg(eth_num, phyaddr, 0x8111, data16); ++ } ++ return 0; ++} ++ ++ ++int ++serdes_start_pll(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ ++ if ( phyaddr == 1 ) { ++ uint32 count=250; ++ /* Start PLL Sequencer and wait for PLL to lock */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr); ++ data16 |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSCONTROLr, data16); ++ ++ /* wait for PLL to lock */ ++ while (count!=0) { ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK0_XGXSSTATUSr); ++ if ( data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK ) { ++ break; ++ } ++ /* wait 1 usec then dec counter */ ++ udelay(10); ++ count--; ++ } ++ if (count == 0) { ++ NET_ERROR(("%s TXPLL did not lock\n", __FUNCTION__)); ++ } ++ } ++ return 0; ++} ++ ++ ++/* ++ * Function: ++ * serdes_init ++ * Purpose: ++ * Initialize xgxs6 phys ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * Returns: ++ * 0 ++ */ ++int ++serdes_init(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint16 serdes_id0, serdes_id1, serdes_id2; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ /* get serdes id */ ++ serdes_id0 = serdes_get_id(eth_num, phyaddr, 0); ++ serdes_id1 = serdes_get_id(eth_num, phyaddr, 1); ++ serdes_id2 = serdes_get_id(eth_num, phyaddr, 2); ++ printf("%s pbyaddr(0x%x) id0(0x%x) id1(0x%x) id2(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1, serdes_id2); ++ ++ /* get more ids */ ++ serdes_id0 = serdes_rd_reg(eth_num, phyaddr, 2); ++ serdes_id1 = serdes_rd_reg(eth_num, phyaddr, 3); ++ //printf("%s pbyaddr(0x%x) SERDES PhyID_MS(0x%x) PhyID_LS(0x%x)\n", __FUNCTION__, phyaddr, serdes_id0, serdes_id1); ++ ++ /* unlock lane */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x833c); ++ data16 &= ~(0x0040); ++ serdes_wr_reg(eth_num, phyaddr, 0x833c, data16); ++ ++ /* disable CL73 BAM */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, 0x8372); ++ data16 &= ~(CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK); ++ serdes_wr_reg(eth_num, phyaddr, 0x8372, data16); ++ ++ /* Set Local Advertising Configuration */ ++ data16 = MII_ANA_C37_FD | MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_AUTONEGADVr, data16); ++ ++ /* Disable BAM in Independent Lane mode. Over1G AN not supported */ ++ data16 = 0; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_UD_FIELDr, data16); ++ ++ data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | ++ SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK; ++ /* ++ * Put the Serdes in SGMII mode ++ * bit0 = 0; in SGMII mode ++ */ ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X1r, data16); ++ ++ /* set autoneg */ ++ data16 = MII_CTRL_AE | MII_CTRL_RAN; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* Disable 10G parallel detect */ ++ data16 = 0; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_AN73_PDET_PARDET10GCONTROLr, data16); ++ ++ /* Disable BAM mode and Teton mode */ ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr, data16); ++ ++ /* Enable lanes */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r); ++ data16 |= XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | ++ XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL0r, data16); ++ ++ /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK; ++ data16 |= (1 << 2); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ /* Enabble LPI passthru' for native mode EEE */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r); ++ data16 |= 0xc000; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_REMOTEPHY_MISC5r, data16); ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr); ++ data16 |= 0x0007; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK7_EEECONTROLr, data16); ++ ++ return 0; ++} ++ ++ ++ ++ ++#if defined(CONFIG_SERDES_ASYMMETRIC_MODE) ++/* ++ * Function: ++ * serdes_speeddpx_set ++ * Purpose: ++ * Set serdes speed dpx ++ * Parameters: ++ * eth_num - ethernet data ++ * phyaddr - physical address ++ * speed - link speed in Mbps ++ * fulldpx - link dpx ++ * Returns: ++ * 0 ++ */ ++int ++serdes_speeddpx_set(uint eth_num, uint phyaddr, int speed, int fulldpx) ++{ ++ uint16 speed_val, mask; ++ uint16 data16; ++ uint16 speed_mii; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ if (speed > 1000) { ++ return -1; ++ } ++ ++ speed_val = 0; ++ speed_mii = 0; ++ mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | ++ SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; ++ ++ switch (speed) { ++ case 0: ++ /* Do not change speed */ ++ return 0; ++ case 10: ++ speed_mii = MII_CTRL_SS_10; ++ break; ++ case 100: ++ speed_mii = MII_CTRL_SS_100; ++ break; ++ case 1000: ++ speed_mii = MII_CTRL_SS_1000; ++ break; ++ default: ++ return -1; ++ } ++ ++ if (fulldpx) ++ speed_mii |= MII_CTRL_FD; ++ ++ /* Hold rxSeqStart */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); ++ data16 |= DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); ++ ++ /* hold TX FIFO in reset */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 |= SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); ++ data16 &= ~(mask); ++ data16 |= speed_val; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); ++ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr); ++ data16 &= ~(MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_SS_LSB | MII_CTRL_SS_MSB | MII_CTRL_FD); ++ data16 |= speed_mii; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_COMBO_IEEE0_MIICNTLr, data16); ++ ++ /* release rxSeqStart */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr); ++ data16 &= ~(DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_RX0_RX_CONTROLr, data16); ++ ++ /* release TX FIFO reset */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r); ++ data16 &= ~(SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK); ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_CONTROL1000X3r, data16); ++ ++ return 0; ++} ++ ++int ++serdes_set_asym_mode(uint eth_num, uint phyaddr) ++{ ++ uint16 data16; ++ uint32 txclkctrlreg[] = {0x0000, 0x8065, 0x8075, 0x8085}; ++ uint32 rxclkctrlreg[] = {0x0000, 0x80bc, 0x80cc, 0x80dc}; ++ uint32 spd[] = {0x0000, 0x7120, 0x7120, 0x7110}; ++ uint32 clkctrlmsk[] = {0x0000, 0x0040, 0x0040, 0x0040}; ++ uint32 clkctrlval[] = {0x0000, 0x0040, 0x0040, 0x0000}; ++ ++ NET_TRACE(("et%d: %s: phyaddr %d\n", eth_num, __FUNCTION__, phyaddr)); ++ ++ printk("et%d: %s: setting serdes asymmetrice mode\n", eth_num, __FUNCTION__); ++ ++ /* set speed */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); ++ data16 &= 0x0f00; ++ data16 |= spd[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_SERDESDIGITAL_MISC1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_SERDESDIGITAL_MISC1r); ++ ++ /* Enable asymmetric mode */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); ++ data16 |= 0x0100; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_TX_LN_SWAP1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_TX_LN_SWAP1r); ++ ++ /* set tx clock control bit */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, txclkctrlreg[phyaddr]); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); ++ data16 &= ~(clkctrlmsk[phyaddr]); ++ data16 |= clkctrlval[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, txclkctrlreg[phyaddr], data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, txclkctrlreg[phyaddr]); ++ ++ /* set rx clock control bit */ ++ data16 = serdes_rd_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr]); ++ //printk("et%d: %s: read 0x%x from 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); ++ data16 &= ~(clkctrlmsk[phyaddr]); ++ data16 |= clkctrlval[phyaddr]; ++ serdes_wr_reg(eth_num, phyaddr, rxclkctrlreg[phyaddr], data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, rxclkctrlreg[phyaddr]); ++ ++ data16 = 0xffff; ++ serdes_wr_reg(eth_num, phyaddr, XGXS16G_XGXSBLK1_LANECTRL1r, data16); ++ //printk("et%d: %s: write 0x%x to 0x%x\n", eth_num, __FUNCTION__, data16, XGXS16G_XGXSBLK1_LANECTRL1r); ++ ++ return 0; ++} ++ ++#endif /* (defined(CONFIG_SERDES_ASYMMETRIC_MODE)) */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmotp.c b/drivers/bcmdrivers/gmac/src/shared/bcmotp.c +new file mode 100755 +index 0000000..a6c41d4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmotp.c +@@ -0,0 +1,3791 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * OTP support. ++ * ++ * $Id: bcmotp.c 322632 2012-03-21 05:17:48Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * There are two different OTP controllers so far: ++ * 1. new IPX OTP controller: chipc 21, >=23 ++ * 2. older HND OTP controller: chipc 12, 17, 22 ++ * ++ * Define BCMHNDOTP to include support for the HND OTP controller. ++ * Define BCMIPXOTP to include support for the IPX OTP controller. ++ * ++ * NOTE 1: More than one may be defined ++ * NOTE 2: If none are defined, the default is to include them all. ++ */ ++ ++#if !defined(BCMHNDOTP) && !defined(BCMIPXOTP) ++#define BCMHNDOTP 1 ++#define BCMIPXOTP 1 ++#endif ++ ++#define OTPTYPE_HND(ccrev) ((ccrev) < 21 || (ccrev) == 22) ++#define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) ++ ++#define OTP_ERR_VAL 0x0001 ++#define OTP_MSG_VAL 0x0002 ++#define OTP_DBG_VAL 0x0004 ++uint32 otp_msg_level = OTP_ERR_VAL; ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) ++#define OTP_ERR(args) do {if (otp_msg_level & OTP_ERR_VAL) printf args;} while (0) ++#else ++#define OTP_ERR(args) ++#endif ++ ++#ifdef BCMDBG ++#define OTP_MSG(args) do {if (otp_msg_level & OTP_MSG_VAL) printf args;} while (0) ++#define OTP_DBG(args) do {if (otp_msg_level & OTP_DBG_VAL) printf args;} while (0) ++#else ++#define OTP_MSG(args) ++#define OTP_DBG(args) ++#endif ++ ++#define OTPP_TRIES 10000000 /* # of tries for OTPP */ ++#define OTP_FUSES_PER_BIT 2 ++#define OTP_WRITE_RETRY 16 ++ ++#ifdef BCMIPXOTP ++#define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ ++#endif ++ ++/* OTP common function type */ ++typedef int (*otp_status_t)(void *oh); ++typedef int (*otp_size_t)(void *oh); ++typedef void* (*otp_init_t)(si_t *sih); ++typedef uint16 (*otp_read_bit_t)(void *oh, chipcregs_t *cc, uint off); ++typedef int (*otp_read_region_t)(si_t *sih, int region, uint16 *data, uint *wlen); ++typedef int (*otp_nvread_t)(void *oh, char *data, uint *len); ++typedef int (*otp_write_region_t)(void *oh, int region, uint16 *data, uint wlen); ++typedef int (*otp_cis_append_region_t)(si_t *sih, int region, char *vars, int count); ++typedef int (*otp_lock_t)(si_t *sih); ++typedef int (*otp_nvwrite_t)(void *oh, uint16 *data, uint wlen); ++typedef int (*otp_dump_t)(void *oh, int arg, char *buf, uint size); ++typedef int (*otp_write_word_t)(void *oh, uint wn, uint16 data); ++typedef int (*otp_read_word_t)(void *oh, uint wn, uint16 *data); ++typedef int (*otp_write_bits_t)(void *oh, int bn, int bits, uint8* data); ++ ++/* OTP function struct */ ++typedef struct otp_fn_s { ++ otp_size_t size; ++ otp_read_bit_t read_bit; ++ otp_dump_t dump; ++ otp_status_t status; ++ ++ otp_init_t init; ++ otp_read_region_t read_region; ++ otp_nvread_t nvread; ++ otp_write_region_t write_region; ++ otp_cis_append_region_t cis_append_region; ++ otp_lock_t lock; ++ otp_nvwrite_t nvwrite; ++ otp_write_word_t write_word; ++ otp_read_word_t read_word; ++ ++#if defined(BCMNVRAMW) ++ otp_write_bits_t write_bits; ++#endif ++} otp_fn_t; ++ ++typedef struct { ++ uint ccrev; /* chipc revision */ ++ otp_fn_t *fn; /* OTP functions */ ++ si_t *sih; /* Saved sb handle */ ++ osl_t *osh; ++ ++#ifdef BCMIPXOTP ++ /* IPX OTP section */ ++ uint16 wsize; /* Size of otp in words */ ++ uint16 rows; /* Geometry */ ++ uint16 cols; /* Geometry */ ++ uint32 status; /* Flag bits (lock/prog/rv). ++ * (Reflected only when OTP is power cycled) ++ */ ++ uint16 hwbase; /* hardware subregion offset */ ++ uint16 hwlim; /* hardware subregion boundary */ ++ uint16 swbase; /* software subregion offset */ ++ uint16 swlim; /* software subregion boundary */ ++ uint16 fbase; /* fuse subregion offset */ ++ uint16 flim; /* fuse subregion boundary */ ++ int otpgu_base; /* offset to General Use Region */ ++ uint16 fusebits; /* num of fusebits */ ++ bool buotp; /* Uinified OTP flag */ ++ uint usbmanfid_offset; /* Offset of the usb manfid inside the sdio CIS */ ++ struct { ++ uint8 width; /* entry width in bits */ ++ uint8 val_shift; /* value bit offset in the entry */ ++ uint8 offsets; /* # entries */ ++ uint8 stat_shift; /* valid bit in otpstatus */ ++ uint16 offset[MAXNUMRDES]; /* entry offset in OTP */ ++ } rde_cb; /* OTP redundancy control blocks */ ++ uint16 rde_idx; ++#endif /* BCMIPXOTP */ ++ ++#ifdef BCMHNDOTP ++ /* HND OTP section */ ++ uint size; /* Size of otp in bytes */ ++ uint hwprot; /* Hardware protection bits */ ++ uint signvalid; /* Signature valid bits */ ++ int boundary; /* hw/sw boundary */ ++#endif /* BCMHNDOTP */ ++} otpinfo_t; ++ ++static otpinfo_t otpinfo; ++ ++/* ++ * ROM accessor to avoid struct in shdat ++ */ ++static otpinfo_t * ++get_otpinfo(void) ++{ ++ return (otpinfo_t *)&otpinfo; ++} ++ ++/* ++ * IPX OTP Code ++ * ++ * Exported functions: ++ * ipxotp_status() ++ * ipxotp_size() ++ * ipxotp_init() ++ * ipxotp_read_bit() ++ * ipxotp_read_region() ++ * ipxotp_read_word() ++ * ipxotp_nvread() ++ * ipxotp_write_region() ++ * ipxotp_write_word() ++ * ipxotp_cis_append_region() ++ * ipxotp_lock() ++ * ipxotp_nvwrite() ++ * ipxotp_dump() ++ * ++ * IPX internal functions: ++ * ipxotp_otpr() ++ * _ipxotp_init() ++ * ipxotp_write_bit() ++ * ipxotp_otpwb16() ++ * ipxotp_check_otp_pmu_res() ++ * ipxotp_write_rde() ++ * ipxotp_fix_word16() ++ * ipxotp_check_word16() ++ * ipxotp_max_rgnsz() ++ * ipxotp_otprb16() ++ * ipxotp_uotp_usbmanfid_offset() ++ * ++ */ ++ ++#ifdef BCMIPXOTP ++ ++#define OTPWSIZE 16 /* word size */ ++#define HWSW_RGN(rgn) (((rgn) == OTP_HW_RGN) ? "h/w" : "s/w") ++ ++/* OTP layout */ ++/* CC revs 21, 24 and 27 OTP General Use Region word offset */ ++#define REVA4_OTPGU_BASE 12 ++ ++/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ ++#define REVB8_OTPGU_BASE 20 ++ ++/* CC rev 36 OTP General Use Region word offset */ ++#define REV36_OTPGU_BASE 12 ++ ++/* Subregion word offsets in General Use region */ ++#define OTPGU_HSB_OFF 0 ++#define OTPGU_SFB_OFF 1 ++#define OTPGU_CI_OFF 2 ++#define OTPGU_P_OFF 3 ++#define OTPGU_SROM_OFF 4 ++ ++/* Flag bit offsets in General Use region */ ++#define OTPGU_NEWCISFORMAT_OFF 59 ++#define OTPGU_HWP_OFF 60 ++#define OTPGU_SWP_OFF 61 ++#define OTPGU_CIP_OFF 62 ++#define OTPGU_FUSEP_OFF 63 ++#define OTPGU_CIP_MSK 0x4000 ++#define OTPGU_P_MSK 0xf000 ++#define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) ++ ++/* LOCK but offset */ ++#define OTP_LOCK_ROW1_LOC_OFF 63 /* 1st ROW lock bit */ ++#define OTP_LOCK_ROW2_LOC_OFF 127 /* 2nd ROW lock bit */ ++#define OTP_LOCK_RD_LOC_OFF 128 /* Redundnancy Region lock bit */ ++#define OTP_LOCK_GU_LOC_OFF 129 /* General User Region lock bit */ ++ ++ ++/* OTP Size */ ++#define OTP_SZ_FU_324 ((ROUNDUP(324,8))/8) /* 324 bits */ ++#define OTP_SZ_FU_288 (288/8) /* 288 bits */ ++#define OTP_SZ_FU_216 (216/8) /* 216 bits */ ++#define OTP_SZ_FU_72 (72/8) /* 72 bits */ ++#define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ ++#define OTP4315_SWREG_SZ 178 /* 178 bytes */ ++#define OTP_SZ_FU_144 (144/8) /* 144 bits */ ++#define OTP_SZ_FU_180 ((ROUNDUP(180,8))/8) /* 180 bits */ ++ ++/* OTP BT shared region (pre-allocated) */ ++#define OTP_BT_BASE_4330 (1760/OTPWSIZE) ++#define OTP_BT_END_4330 (1888/OTPWSIZE) ++#define OTP_BT_BASE_4324 (2384/OTPWSIZE) ++#define OTP_BT_END_4324 (2640/OTPWSIZE) ++#define OTP_BT_BASE_4334 (2512/OTPWSIZE) ++#define OTP_BT_END_4334 (2768/OTPWSIZE) ++#define OTP_BT_BASE_4314 (4192/OTPWSIZE) ++#define OTP_BT_END_4314 (4960/OTPWSIZE) ++#define OTP_BT_BASE_4335 (4528/OTPWSIZE) ++#define OTP_BT_END_4335 (5552/OTPWSIZE) ++ ++/* OTP unification */ ++#if defined(USBSDIOUNIFIEDOTP) ++/* USB MANIFID tuple offset in the SDIO CIS in (16-bit) words */ ++#define USB_MANIFID_OFFSET_4319 42 ++#endif /* USBSDIOUNIFIEDOTP */ ++ ++#if defined(BCMNVRAMW) ++/* Local */ ++static int ipxotp_check_otp_pmu_res(chipcregs_t *cc); ++static int ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off); ++static int ipxotp40n_read2x(void *oh, chipcregs_t *cc, uint off); ++static int ipxotp_write_rde_nopc(void *oh, chipcregs_t *cc, int rde, uint bit, uint val); ++#endif ++ ++static int ++ipxotp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return (int)(oi->status); ++} ++ ++/* Return size in bytes */ ++static int ++ipxotp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return (int)oi->wsize * 2; ++} ++ ++static uint16 ++ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ ASSERT(wn < oi->wsize); ++ ASSERT(cc != NULL); ++ ++ return R_REG(oi->osh, &cc->sromotp[wn]); ++} ++ ++static uint16 ++ipxotp_read_bit_common(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_READ_40NM : ++ OTPPOC_READ) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x", ++ __FUNCTION__, off, row, col, otpp)); ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return 0xffff; ++ } ++ if (st & OTPP_READERR) { ++ OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, off)); ++ return 0xffff; ++ } ++ st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; ++ ++ OTP_DBG((" => %d\n", st)); ++ return (int)st; ++} ++ ++static uint16 ++ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++/* ++ * OTP BT region size ++ */ ++static void ++ipxotp_bt_region_get(otpinfo_t *oi, uint16 *start, uint16 *end) ++{ ++ *start = *end = 0; ++ switch (CHIPID(oi->sih->chip)) { ++ case BCM4330_CHIP_ID: ++ *start = OTP_BT_BASE_4330; ++ *end = OTP_BT_END_4330; ++ break; ++ case BCM4324_CHIP_ID: ++ *start = OTP_BT_BASE_4324; ++ *end = OTP_BT_END_4324; ++ break; ++ case BCM4334_CHIP_ID: ++ *start = OTP_BT_BASE_4334; ++ *end = OTP_BT_END_4334; ++ break; ++ case BCM4314_CHIP_ID: ++ case BCM43142_CHIP_ID: ++ *start = OTP_BT_BASE_4314; ++ *end = OTP_BT_END_4314; ++ break; ++ case BCM4335_CHIP_ID: ++ *start = OTP_BT_BASE_4335; ++ *end = OTP_BT_END_4335; ++ break; ++ } ++} ++ ++/* Calculate max HW/SW region byte size by substracting fuse region and checksum size, ++ * osizew is oi->wsize (OTP size - GU size) in words ++ */ ++static int ++ipxotp_max_rgnsz(otpinfo_t *oi) ++{ ++ int osizew = oi->wsize; ++ int ret = 0; ++ uint16 checksum; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ checksum = OTP_SZ_CHECKSUM; ++ ++ /* for new chips, fusebit is available from cc register */ ++ if (oi->sih->ccrev >= 35) { ++ oi->fusebits = R_REG(oi->osh, &cc->otplayoutextension) & OTPLAYOUTEXT_FUSE_MASK; ++ oi->fusebits = ROUNDUP(oi->fusebits, 8); ++ oi->fusebits >>= 3; /* bytes */ ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ switch (CHIPID(oi->sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43239_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_288; ++ break; ++ case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: ++ case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID: ++ case BCM43226_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43237_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_324; ++ break; ++ case BCM4325_CHIP_ID: ++ case BCM5356_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_216; ++ break; ++ case BCM4336_CHIP_ID: ++ case BCM43362_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_144; ++ break; ++ case BCM4313_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM4330_CHIP_ID: ++ case BCM4334_CHIP_ID: ++ case BCM4314_CHIP_ID: ++ case BCM43142_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_144; ++ break; ++ case BCM4319_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_180; ++ break; ++ case BCM4331_CHIP_ID: ++ case BCM43431_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ case BCM43428_CHIP_ID: ++ oi->fusebits = OTP_SZ_FU_72; ++ break; ++ default: ++ if (oi->fusebits == 0) ++ ASSERT(0); /* Don't konw about this chip */ ++ } ++ ++ ret = osizew*2 - oi->fusebits - checksum; ++ ++ if (CHIPID(oi->sih->chip) == BCM4315_CHIP_ID) { ++ ret = OTP4315_SWREG_SZ; ++ } ++ ++ OTP_MSG(("max region size %d bytes\n", ret)); ++ return ret; ++} ++ ++/* ++ * OTP sizes for 65nm and 130nm ++ */ ++static int ++ipxotp_otpsize_set_65nm(otpinfo_t *oi, uint otpsz) ++{ ++ /* Check for otp size */ ++ switch (otpsz) { ++ case 1: /* 32x64 */ ++ oi->rows = 32; ++ oi->cols = 64; ++ oi->wsize = 128; ++ break; ++ case 2: /* 64x64 */ ++ oi->rows = 64; ++ oi->cols = 64; ++ oi->wsize = 256; ++ break; ++ case 5: /* 96x64 */ ++ oi->rows = 96; ++ oi->cols = 64; ++ oi->wsize = 384; ++ break; ++ case 7: /* 16x64 */ /* 1024 bits */ ++ oi->rows = 16; ++ oi->cols = 64; ++ oi->wsize = 64; ++ break; ++ default: ++ /* Don't know the geometry */ ++ OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__)); ++ } ++ ++ return 0; ++} ++ ++/* ++ * OTP sizes for 40nm ++ */ ++static int ++ipxotp_otpsize_set_40nm(otpinfo_t *oi, uint otpsz) ++{ ++ /* Check for otp size */ ++ switch (otpsz) { ++ case 1: /* 64x32: 2048 bits */ ++ oi->rows = 64; ++ oi->cols = 32; ++ break; ++ case 2: /* 96x32: 3072 bits */ ++ oi->rows = 96; ++ oi->cols = 32; ++ break; ++ case 3: /* 128x32: 4096 bits */ ++ oi->rows = 128; ++ oi->cols = 32; ++ break; ++ case 4: /* 160x32: 5120 bits */ ++ oi->rows = 160; ++ oi->cols = 32; ++ break; ++ case 5: /* 192x32: 6144 bits */ ++ oi->rows = 192; ++ oi->cols = 32; ++ break; ++ case 7: /* 256x32: 8192 bits */ ++ oi->rows = 256; ++ oi->cols = 32; ++ break; ++ default: ++ /* Don't know the geometry */ ++ OTP_ERR(("%s: unknown OTP geometry\n", __FUNCTION__)); ++ } ++ ++ oi->wsize = (oi->cols * oi->rows)/OTPWSIZE; ++ return 0; ++} ++ ++/* OTP unification */ ++#if defined(USBSDIOUNIFIEDOTP) && defined(BCMNVRAMW) ++static void ++ipxotp_uotp_usbmanfid_offset(otpinfo_t *oi) ++{ ++ OTP_DBG(("%s: chip=0x%x\n", __FUNCTION__, CHIPID(oi->sih->chip))); ++ switch (CHIPID(oi->sih->chip)) { ++ /* Add cases for supporting chips */ ++ case BCM4319_CHIP_ID: ++ oi->usbmanfid_offset = USB_MANIFID_OFFSET_4319; ++ oi->buotp = TRUE; ++ break; ++ default: ++ OTP_ERR(("chip=0x%x does not support Unified OTP.\n", ++ CHIPID(oi->sih->chip))); ++ break; ++ } ++} ++#endif /* USBSDIOUNIFIEDOTP && BCMNVRAMW */ ++ ++static void ++BCMNMIATTACHFN(_ipxotp_init)(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint k; ++ uint32 otpp, st; ++ uint16 btsz, btbase = 0, btend = 0; ++ uint otpwt; ++ ++ /* record word offset of General Use Region for various chipcommon revs */ ++ if (oi->sih->ccrev >= 40) { ++ /* FIX: Available in rev >= 23; Verify before applying to others */ ++ oi->otpgu_base = (R_REG(oi->osh, &cc->otplayout) & OTPL_HWRGN_OFF_MASK) ++ >> OTPL_HWRGN_OFF_SHIFT; ++ ASSERT((oi->otpgu_base - (OTPGU_SROM_OFF * OTPWSIZE)) > 0); ++ oi->otpgu_base >>= 4; /* words */ ++ oi->otpgu_base -= OTPGU_SROM_OFF; ++ } else if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24 || oi->sih->ccrev == 27) { ++ oi->otpgu_base = REVA4_OTPGU_BASE; ++ } else if ((oi->sih->ccrev == 36) || (oi->sih->ccrev == 39)) { ++ /* OTP size greater than equal to 2KB (128 words), otpgu_base is similar to rev23 */ ++ if (oi->wsize >= 128) ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ else ++ oi->otpgu_base = REV36_OTPGU_BASE; ++ } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) { ++ oi->otpgu_base = REVB8_OTPGU_BASE; ++ } else { ++ OTP_ERR(("%s: chipc rev %d not supported\n", __FUNCTION__, oi->sih->ccrev)); ++ } ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt != OTPL_WRAP_TYPE_40NM) { ++ /* First issue an init command so the status is up to date */ ++ otpp = OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); ++ ++ OTP_DBG(("%s: otpp = 0x%x", __FUNCTION__, otpp)); ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return; ++ } ++ } ++ ++ /* Read OTP lock bits and subregion programmed indication bits */ ++ oi->status = R_REG(oi->osh, &cc->otpstatus); ++ ++ if ((CHIPID(oi->sih->chip) == BCM43222_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43111_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43112_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43224_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43225_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43421_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43226_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43236_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43235_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43234_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43238_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43237_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43239_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4324_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4335_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(oi->sih->chip) == BCM43526_CHIP_ID) || ++ 0) { ++ uint32 p_bits; ++ p_bits = (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) & OTPGU_P_MSK) ++ >> OTPGU_P_SHIFT; ++ oi->status |= (p_bits << OTPS_GUP_SHIFT); ++ } ++ OTP_DBG(("%s: status 0x%x\n", __FUNCTION__, oi->status)); ++ ++ /* OTP unification */ ++ oi->buotp = FALSE; /* Initialize it to false, until its explicitely set true. */ ++ oi->usbmanfid_offset = 0; ++#if defined(USBSDIOUNIFIEDOTP) && defined(BCMNVRAMW) ++ ipxotp_uotp_usbmanfid_offset(oi); ++#endif /* USBSDIOUNIFIEDOTP && BCMNVRAMW */ ++ if ((oi->status & (OTPS_GUP_HW | OTPS_GUP_SW)) == (OTPS_GUP_HW | OTPS_GUP_SW)) { ++ switch (CHIPID(oi->sih->chip)) { ++ /* Add cases for supporting chips */ ++ case BCM4319_CHIP_ID: ++ oi->buotp = TRUE; ++ break; ++ default: ++ OTP_ERR(("chip=0x%x does not support Unified OTP.\n", ++ CHIPID(oi->sih->chip))); ++ break; ++ } ++ } ++ ++ /* ++ * h/w region base and fuse region limit are fixed to the top and ++ * the bottom of the general use region. Everything else can be flexible. ++ */ ++ oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; ++ oi->hwlim = oi->wsize; ++ oi->flim = oi->wsize; ++ ++ ipxotp_bt_region_get(oi, &btbase, &btend); ++ btsz = btend - btbase; ++ if (btsz > 0) { ++ /* default to not exceed BT base */ ++ oi->hwlim = btbase; ++ ++ /* With BT shared region, swlim and fbase are fixed */ ++ oi->swlim = btbase; ++ oi->fbase = btend; ++ } ++ ++ /* Update hwlim and swbase */ ++ if (oi->status & OTPS_GUP_HW) { ++ OTP_DBG(("%s: hw region programmed\n", __FUNCTION__)); ++ oi->hwlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16; ++ oi->swbase = oi->hwlim; ++ } else ++ oi->swbase = oi->hwbase; ++ ++ /* Update swlim and fbase only if no BT region */ ++ if (btsz == 0) { ++ /* subtract fuse and checksum from beginning */ ++ oi->swlim = ipxotp_max_rgnsz(oi) / 2; ++ ++ if (oi->status & OTPS_GUP_SW) { ++ OTP_DBG(("%s: sw region programmed\n", __FUNCTION__)); ++ oi->swlim = ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16; ++ oi->fbase = oi->swlim; ++ } ++ else ++ oi->fbase = oi->swbase; ++ } ++ ++ OTP_DBG(("%s: OTP limits---\n" ++ "hwbase %d/%d hwlim %d/%d\n" ++ "swbase %d/%d swlim %d/%d\n" ++ "fbase %d/%d flim %d/%d\n", __FUNCTION__, ++ oi->hwbase, oi->hwbase * 16, oi->hwlim, oi->hwlim * 16, ++ oi->swbase, oi->swbase * 16, oi->swlim, oi->swlim * 16, ++ oi->fbase, oi->fbase * 16, oi->flim, oi->flim * 16)); ++} ++ ++static void * ++BCMNMIATTACHFN(ipxotp_init)(si_t *sih) ++{ ++ uint idx, otpsz, otpwt; ++ chipcregs_t *cc; ++ otpinfo_t *oi = NULL; ++ ++ OTP_MSG(("%s: Use IPX OTP controller\n", __FUNCTION__)); ++ ++ /* Make sure we're running IPX OTP */ ++ ASSERT(OTPTYPE_IPX(sih->ccrev)); ++ if (!OTPTYPE_IPX(sih->ccrev)) ++ return NULL; ++ ++ /* Make sure OTP is not disabled */ ++ if (si_is_otp_disabled(sih)) { ++ OTP_MSG(("%s: OTP is disabled\n", __FUNCTION__)); ++#if !defined(WLTEST) ++ return NULL; ++#endif ++ } ++ ++ /* Make sure OTP is powered up */ ++ if (!si_is_otp_powered(sih)) { ++ OTP_ERR(("%s: OTP is powered down\n", __FUNCTION__)); ++ return NULL; ++ } ++ ++ /* Retrieve OTP region info */ ++ idx = si_coreidx(sih); ++ cc = si_setcoreidx(sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpsz = (sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT; ++ if (otpsz == 0) { ++ OTP_ERR(("%s: No OTP\n", __FUNCTION__)); ++ goto exit; ++ } ++ ++ oi = get_otpinfo(); ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ ipxotp_otpsize_set_40nm(oi, otpsz); ++ } else if (otpwt == OTPL_WRAP_TYPE_65NM) { ++ ipxotp_otpsize_set_65nm(oi, otpsz); ++ } else { ++ OTP_ERR(("%s: Unknown wrap type: %d\n", __FUNCTION__, otpwt)); ++ ASSERT(0); ++ } ++ ++ OTP_MSG(("%s: rows %u cols %u wsize %u\n", __FUNCTION__, oi->rows, oi->cols, oi->wsize)); ++ ++#ifdef BCMNVRAMW ++ /* Initialize OTP redundancy control blocks */ ++ if (sih->ccrev >= 40) { ++ uint16 offset[] = {269, 286, 303, 333, 350, 367, 397, 414, 431}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 17; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } else if (sih->ccrev == 36) { ++ uint16 offset[] = {141, 158, 175}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } else if (sih->ccrev == 21 || sih->ccrev == 24) { ++ uint16 offset[] = {64, 79, 94, 109, 128, 143, 158, 173}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 11; ++ oi->rde_cb.stat_shift = 16; ++ } ++ else if (sih->ccrev == 27) { ++ uint16 offset[] = {128, 143, 158, 173}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 15; ++ oi->rde_cb.val_shift = 11; ++ oi->rde_cb.stat_shift = 20; ++ } ++ else { ++ uint16 offset[] = {141, 158, 175, 205, 222, 239, 269, 286, 303}; ++ bcopy(offset, &oi->rde_cb.offset, sizeof(offset)); ++ oi->rde_cb.offsets = ARRAYSIZE(offset); ++ oi->rde_cb.width = 17; ++ oi->rde_cb.val_shift = 13; ++ oi->rde_cb.stat_shift = 16; ++ } ++ ASSERT(oi->rde_cb.offsets <= MAXNUMRDES); ++ /* Initialize global rde index */ ++ oi->rde_idx = 0; ++#endif /* BCMNVRAMW */ ++ ++ _ipxotp_init(oi, cc); ++ ++exit: ++ si_setcoreidx(sih, idx); ++ ++ return (void *)oi; ++} ++ ++static int ++ipxotp_read_region(void *oh, int region, uint16 *data, uint *wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint base, i, sz; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ /* OTP unification: For unified OTP sz=flim-hwbase */ ++ if (oi->buotp) ++ sz = (uint)oi->flim - oi->hwbase; ++ else ++ sz = (uint)oi->hwlim - oi->hwbase; ++ if (!(oi->status & OTPS_GUP_HW)) { ++ OTP_ERR(("%s: h/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->hwlim - oi->hwbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ /* OTP unification: For unified OTP sz=flim-swbase */ ++ if (oi->buotp) ++ sz = ((uint)oi->flim - oi->swbase); ++ else ++ sz = ((uint)oi->swlim - oi->swbase); ++ if (!(oi->status & OTPS_GUP_SW)) { ++ OTP_ERR(("%s: s/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small should be at least %u\n", ++ __FUNCTION__, oi->swlim - oi->swbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ sz = OTPGU_CI_SZ; ++ if (!(oi->status & OTPS_GUP_CI)) { ++ OTP_ERR(("%s: chipid region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, OTPGU_CI_SZ)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ sz = (uint)oi->flim - oi->fbase; ++ if (!(oi->status & OTPS_GUP_FUSE)) { ++ OTP_ERR(("%s: fuse region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->flim - oi->fbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->fbase; ++ break; ++ case OTP_ALL_RGN: ++ sz = ((uint)oi->flim - oi->hwbase); ++ if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { ++ OTP_ERR(("%s: h/w & s/w region not programmed\n", __FUNCTION__)); ++ *wlen = sz; ++ return BCME_NOTFOUND; ++ } ++ if (*wlen < sz) { ++ OTP_ERR(("%s: buffer too small, should be at least %u\n", ++ __FUNCTION__, oi->hwlim - oi->hwbase)); ++ *wlen = sz; ++ return BCME_BUFTOOSHORT; ++ } ++ base = oi->hwbase; ++ break; ++ default: ++ OTP_ERR(("%s: reading region %d is not supported\n", __FUNCTION__, region)); ++ return BCME_BADARG; ++ } ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Read the data */ ++ for (i = 0; i < sz; i ++) ++ data[i] = ipxotp_otpr(oh, cc, base + i); ++ ++ si_setcoreidx(oi->sih, idx); ++ *wlen = sz; ++ return 0; ++} ++ ++static int ++ipxotp_read_word(void *oh, uint wn, uint16 *data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Read the data */ ++ *data = ipxotp_otpr(oh, cc, wn); ++ ++ si_setcoreidx(oi->sih, idx); ++ return 0; ++} ++ ++static int ++ipxotp_nvread(void *oh, char *data, uint *len) ++{ ++ return BCME_UNSUPPORTED; ++} ++ ++#ifdef BCMNVRAMW ++static int ++ipxotp_writable(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ uint i, k, row, col; ++ uint32 otpp, st; ++ uint cols[4] = {15, 4, 8, 13}; ++ ++ row = 0; ++ for (i = 0; i < 4; i++) { ++ col = cols[i]; ++ ++ otpp = OTPP_START_BUSY | ++ ((OTPPOC_PROG_ENABLE_40NM << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && ++ (k < OTPP_TRIES); k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", ++ __FUNCTION__, st, k)); ++ return -1; ++ } ++ } ++ ++ /* wait till OTP Program mode is unlocked */ ++ for (k = 0; ++ (!((st = R_REG(oi->osh, &cc->otpstatus)) & OTPS_PROGOK)) && ++ (k < OTPP_TRIES); k ++) ++ ; ++ OTP_MSG(("\n%s: OTP Program status: %x\n", __FUNCTION__, st)); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: OTP Program mode is still locked, OTP is unwritable\n", ++ __FUNCTION__)); ++ return -1; ++ } ++ } ++ ++ OR_REG(oi->osh, &cc->otpcontrol, OTPC_PROGEN); ++ return 0; ++} ++ ++static int ++ipxotp_unwritable(otpinfo_t *oi, chipcregs_t *cc) ++{ ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ uint k, row, col; ++ uint32 otpp, st; ++ ++ row = 0; ++ col = 0; ++ ++ otpp = OTPP_START_BUSY | ++ ((OTPPOC_PROG_DISABLE_40NM << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ /* wait till OTP Program mode is unlocked */ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpstatus)) & OTPS_PROGOK) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ OTP_MSG(("\n%s: OTP Program status: %x\n", __FUNCTION__, st)); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: OTP Program mode is still unlocked, OTP is writable\n", ++ __FUNCTION__)); ++ return -1; ++ } ++ } ++ ++ AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN); ++ return 0; ++} ++ ++static int ++ipxotp_write_bit_common(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((1 << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_BIT_PROG_40NM : ++ OTPPOC_BIT_PROG) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, off, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ipxotp40n_read2x(void *oh, chipcregs_t *cc, uint off) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (1 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_R1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_R1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_read1x(void *oh, chipcregs_t *cc, uint off, uint fuse) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_R1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_R1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_verify1x(void *oh, chipcregs_t *cc, uint off, uint fuse) ++{ ++ otpinfo_t *oi; ++ ++ oi = (otpinfo_t *)oh; ++ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_V1X << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (1 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_V1X << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT)); ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_V1X << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_read_bit_common(oh, cc, off); ++} ++ ++static int ++ipxotp40n_write_fuse(otpinfo_t *oi, chipcregs_t *cc, uint off, uint fuse) ++{ ++ W_REG(oi->osh, &cc->otpcontrol, ++ (fuse << OTPC_40NM_PROGSEL_SHIFT) | ++ (OTPC_40NM_PCOUNT_WR << OTPC_40NM_PCOUNT_SHIFT) | ++ (OTPC_40NM_REGCSEL_DEF << OTPC_40NM_REGCSEL_SHIFT) | ++ (1 << OTPC_40NM_PROGIN_SHIFT) | ++ (0 << OTPC_40NM_R2X_SHIFT) | ++ (1 << OTPC_40NM_ODM_SHIFT) | ++ (0 << OTPC_40NM_DF_SHIFT) | ++ (OTPC_40NM_VSEL_WR << OTPC_40NM_VSEL_SHIFT) | ++ (1 << OTPC_40NM_COFAIL_SHIFT) | ++ OTPC_PROGEN); ++ ++ W_REG(oi->osh, &cc->otpcontrol1, ++ (OTPC1_CPCSEL_DEF << OTPC1_CPCSEL_SHIFT) | ++ (OTPC1_TM_WR << OTPC1_TM_SHIFT)); ++ ++ return ipxotp_write_bit_common(oi, cc, off); ++} ++ ++static int ++ipxotp40n_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint32 oc_orig, oc1_orig; ++ uint8 i, j, err = 0; ++ int verr0, verr1, rerr0, rerr1, retry, val; ++ ++ oc_orig = R_REG(oi->osh, &cc->otpcontrol); ++ oc1_orig = R_REG(oi->osh, &cc->otpcontrol1); ++ ++ for (i = 0; i < OTP_FUSES_PER_BIT; i++) { ++ retry = 0; ++ for (j = 0; j < OTP_WRITE_RETRY; j++) { ++ /* program fuse */ ++ ipxotp40n_write_fuse(oi, cc, off, i); ++ ++ /* verify fuse */ ++ val = ipxotp40n_verify1x(oi, cc, off, i); ++ if (val == 1) ++ break; ++ ++ retry++; ++ } ++ ++ if ((val != 1) && (j == OTP_WRITE_RETRY)) { ++ OTP_ERR(("ERROR: New write failed max attempts fuse:%d @ off:%d\n", ++ i, off)); ++ } else if (retry > 0) ++ OTP_MSG(("Verify1x multi retries:%d fuse:%d @ off:%d\n", ++ retry, i, off)); ++ } ++ ++ /* Post screen */ ++ verr0 = (ipxotp40n_verify1x(oi, cc, off, 0) == 1) ? TRUE : FALSE; ++ verr1 = (ipxotp40n_verify1x(oi, cc, off, 1) == 1) ? TRUE : FALSE; ++ rerr0 = (ipxotp40n_read1x(oi, cc, off, 0) == 1) ? TRUE : FALSE; ++ rerr1 = (ipxotp40n_read1x(oi, cc, off, 1) == 1) ? TRUE : FALSE; ++ ++ if (verr0 && verr1) { ++ OTP_MSG(("V0:%d and V1:%d ok off:%d\n", verr0, verr1, off)); ++ } else if (verr0 && rerr1) { ++ OTP_MSG(("V0:%d and R1:%d ok off:%d\n", verr0, rerr1, off)); ++ } else if (rerr0 && verr1) { ++ OTP_MSG(("R0:%d and V1:%d ok off:%d\n", rerr0, verr1, off)); ++ } else { ++ OTP_ERR(("Bit failed post screen v0:%d v1:%d r0:%d r1:%d off:%d\n", ++ verr0, verr1, rerr0, rerr1, off)); ++ err = -1; ++ } ++ ++ W_REG(oi->osh, &cc->otpcontrol, oc_orig); ++ W_REG(oi->osh, &cc->otpcontrol1, oc1_orig); ++ ++ return err; ++} ++ ++#ifdef OTP_DEBUG ++int ++otp_read1x(void *oh, uint off, uint fuse) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, otpwt; ++ int val = 0; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ if ((otpwt != OTPL_WRAP_TYPE_40NM) || (oi->sih->ccrev < 40)) ++ goto exit; ++ ++ val = ipxotp40n_read1x(oi, cc, off, fuse); ++ ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return val; ++} ++ ++int ++otp_verify1x(void *oh, uint off, uint fuse) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0; ++ chipcregs_t *cc; ++ uint idx, otpwt; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ if ((otpwt != OTPL_WRAP_TYPE_40NM) || (oi->sih->ccrev < 40)) ++ goto exit; ++ ++ err = ipxotp40n_verify1x(oi, cc, off, fuse); ++ if (err != 1) ++ OTP_ERR(("v1x failed fuse:%d @ off:%d\n", fuse, off)); ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return err; ++} ++ ++/* ++ * Repair is to fix damaged bits; not intended to fix programming errors ++ * This is limited and for 4334 only nine repair entries available ++ */ ++int ++otp_repair_bit(void *oh, uint off, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return ipxotp_write_rde(oi, -1, off, val); ++} ++ ++int ++otp_write_ones_old(void *oh, uint off, uint bits) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint32 i; ++ ++ if (off < 0 || off + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; i++) { ++ ipxotp_write_bit_common(oi, cc, off++); ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++int ++otp_write_ones(void *oh, uint off, uint bits) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint32 i; ++ int err; ++ ++ if (off < 0 || off + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; i++) { ++ err = ipxotp_write_bit(oi, cc, off); ++ if (err != 0) { ++ OTP_ERR(("%s: write bit failed: %d\n", __FUNCTION__, off)); ++ ++ err = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), off, 1); ++ if (err != 0) ++ OTP_ERR(("%s: repair bit failed: %d\n", __FUNCTION__, off)); ++ else ++ OTP_ERR(("%s: repair bit ok: %d\n", __FUNCTION__, off)); ++ } ++ ++ off++; ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++#endif /* OTP_DEBUG */ ++ ++static int ++ipxotp_write_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint otpwt; ++ int status = 0; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ if (otpwt == OTPL_WRAP_TYPE_40NM) { ++ /* Can damage fuse in 40nm so safeguard against reprogramming */ ++ if (ipxotp40n_read2x(oi, cc, off) != 1) { ++ status = ipxotp40n_write_bit(oi, cc, off); ++ } else { ++ OTP_MSG(("Bit already programmed: %d\n", off)); ++ } ++ } else { ++ W_REG(oi->osh, &cc->otpcontrol, 0); ++ W_REG(oi->osh, &cc->otpcontrol1, 0); ++ ++ status = ipxotp_write_bit_common(oi, cc, off); ++ } ++ ++ return status; ++} ++ ++static int ++ipxotp_write_bits(void *oh, int bn, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int i, j; ++ uint8 temp; ++ int err; ++ ++ if (bn < 0 || bn + bits > oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ ipxotp_writable(oi, cc); ++ for (i = 0; i < bits; ) { ++ temp = *data++; ++ for (j = 0; j < 8; j++, i++) { ++ if (i >= bits) ++ break; ++ if (temp & 0x01) ++ { ++ if (ipxotp_write_bit(oi, cc, (uint)(i + bn)) != 0) { ++ OTP_ERR(("%s: write bit failed: %d\n", ++ __FUNCTION__, i + bn)); ++ ++ err = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), i + bn, 1); ++ if (err != 0) { ++ OTP_ERR(("%s: repair bit failed: %d\n", ++ __FUNCTION__, i + bn)); ++ AND_REG(oi->osh, &cc->otpcontrol, ~OTPC_PROGEN); ++ return -1; ++ } else ++ OTP_ERR(("%s: repair bit ok: %d\n", ++ __FUNCTION__, i + bn)); ++ } ++ } ++ temp >>= 1; ++ } ++ } ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++ ++static int ++ipxotp_write_lock_bit(otpinfo_t *oi, chipcregs_t *cc, uint off) ++{ ++ uint k, row, col; ++ uint32 otpp, st; ++ uint otpwt; ++ ++ otpwt = (R_REG(oi->osh, &cc->otplayout) & OTPL_WRAP_TYPE_MASK) >> OTPL_WRAP_TYPE_SHIFT; ++ ++ row = off / oi->cols; ++ col = off % oi->cols; ++ ++ otpp = OTPP_START_BUSY | ++ ((((otpwt == OTPL_WRAP_TYPE_40NM)? OTPPOC_ROW_LOCK_40NM : ++ OTPPOC_ROW_LOCK) << OTPP_OC_SHIFT) & OTPP_OC_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK); ++ OTP_DBG(("%s: off = %d, row = %d, col = %d, otpp = 0x%x\n", ++ __FUNCTION__, off, row, col, otpp)); ++ ++ W_REG(oi->osh, &cc->otpprog, otpp); ++ ++ for (k = 0; ++ ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY) && (k < OTPP_TRIES); ++ k ++) ++ ; ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++ipxotp_otpwb16(otpinfo_t *oi, chipcregs_t *cc, int wn, uint16 data) ++{ ++ uint base, i; ++ int rc = 0; ++ ++ base = wn * 16; ++ for (i = 0; i < 16; i++) { ++ if (data & (1 << i)) { ++ rc = ipxotp_write_bit(oi, cc, base + i); ++ if (rc != 0) { ++ OTP_ERR(("%s: write bit failed:%d\n", __FUNCTION__, base + i)); ++ ++ rc = ipxotp_write_rde_nopc(oi, cc, ++ ipxotp_check_otp_pmu_res(cc), base + i, 1); ++ if (rc != 0) { ++ OTP_ERR(("%s: repair bit failed:%d\n", ++ __FUNCTION__, base + i)); ++ break; ++ } else ++ OTP_ERR(("%s: repair bit ok:%d\n", __FUNCTION__, base + i)); ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++/* Write OTP redundancy entry: ++ * rde - redundancy entry index (-ve for "next") ++ * bit - bit offset ++ * val - bit value ++ */ ++ ++/* Check if for a particular chip OTP PMU resource is available */ ++static int ++ipxotp_check_otp_pmu_res(chipcregs_t *cc) ++{ ++ switch (cc->chipid & 0x0000ffff) { ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ /* OTP PMU resource not available, hence use global rde index */ ++ return OTP_GLOBAL_RDE_IDX; ++ default: ++ /* OTP PMU resource available, hence calculate rde index */ ++ return -1; ++ } ++ return -1; ++} ++ ++/* Assumes already writable and bypasses power-cycling */ ++static int ++ipxotp_write_rde_nopc(void *oh, chipcregs_t *cc, int rde, uint bit, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint i, temp; ++ int err = BCME_OK; ++ ++#ifdef BCMDBG ++ if ((rde >= (int)oi->rde_cb.offsets) || (bit >= (uint)(oi->rows * oi->cols)) || (val > 1)) ++ return BCME_RANGE; ++#endif ++ ++ if (rde < 0) { ++ for (rde = 0; rde < oi->rde_cb.offsets - 1; rde++) { ++ if ((oi->status & (1 << (oi->rde_cb.stat_shift + rde))) == 0) ++ break; ++ } ++ OTP_ERR(("%s: Auto rde index %d\n", __FUNCTION__, rde)); ++ } ++ else if (rde == OTP_GLOBAL_RDE_IDX) { ++ /* Chips which do not have a OTP PMU res, OTP can't be pwr cycled from the drv. */ ++ /* Hence we need to have a count of the global rde, and populate accordingly. */ ++ ++ /* Find the next available rde location */ ++ while (oi->status & (1 << (oi->rde_cb.stat_shift + oi->rde_idx))) { ++ OTP_MSG(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__, ++ rde, oi->status)); ++ oi->rde_idx++; ++ } ++ rde = oi->rde_idx++; ++ ++ if (rde >= MAXNUMRDES) { ++ OTP_MSG(("%s: No rde location available to fix.\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ } ++ ++ if (oi->status & (1 << (oi->rde_cb.stat_shift + rde))) { ++ OTP_ERR(("%s: rde %d already in use, status 0x%08x\n", __FUNCTION__, ++ rde, oi->status)); ++ return BCME_ERROR; ++ } ++ ++ temp = ~(~0 << oi->rde_cb.width) & ++ ((~0 << (oi->rde_cb.val_shift + 1)) | (val << oi->rde_cb.val_shift) | bit); ++ ++ OTP_MSG(("%s: rde %d bit %d val %d bmp 0x%08x\n", __FUNCTION__, rde, bit, val, temp)); ++ ++ for (i = 0; i < oi->rde_cb.width; i ++) { ++ if (!(temp & (1 << i))) ++ continue; ++ if (ipxotp_write_bit(oi, cc, oi->rde_cb.offset[rde] + i) != 0) ++ err = BCME_ERROR; ++ } ++ ++ /* no power-cyclying to just set status */ ++ oi->status |= (1 << (oi->rde_cb.stat_shift + rde)); ++ ++ return err; ++} ++ ++int ++ipxotp_write_rde(void *oh, int rde, uint bit, uint val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int err; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ err = ipxotp_write_rde_nopc(oh, cc, rde, bit, val); ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ return err; ++} ++ ++/* Set up redundancy entries for the specified bits */ ++static int ++ipxotp_fix_word16(void *oh, uint wn, uint16 mask, uint16 val, chipcregs_t *cc) ++{ ++ otpinfo_t *oi; ++ uint bit; ++ int rc = 0; ++ ++ oi = (otpinfo_t *)oh; ++ ++ ASSERT(oi != NULL); ++ ASSERT(wn < oi->wsize); ++ ++ for (bit = wn * 16; mask; bit++, mask >>= 1, val >>= 1) { ++ if (mask & 1) { ++ if ((rc = ipxotp_write_rde(oi, ipxotp_check_otp_pmu_res(cc), bit, val & 1))) ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++static int ++ipxotp_check_word16(void *oh, chipcregs_t *cc, uint wn, uint16 val) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint16 word = ipxotp_otpr(oi, cc, wn); ++ int rc = 0; ++ ++ if ((word ^= val)) { ++ OTP_MSG(("%s: word %d is 0x%04x, wanted 0x%04x, fixing...\n", ++ __FUNCTION__, wn, (word ^ val), val)); ++ ++ if ((rc = ipxotp_fix_word16(oi, wn, word, val, cc))) { ++ OTP_ERR(("FAILED, ipxotp_fix_word16 returns %d\n", rc)); ++ /* Fatal error, unfixable. MFGC will have to fail. Board ++ * needs to be discarded!! ++ */ ++ return BCME_NORESOURCE; ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++ipxotp_write_region(void *oh, int region, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ uint base, i; ++ int otpgu_bit_base; ++ bool rewrite = FALSE; ++ int rc = 0; ++#if defined(DONGLEBUILD) ++ uint16 *origdata = NULL; ++#endif /* DONGLEBUILD */ ++ ++ otpgu_bit_base = oi->otpgu_base * 16; ++ ++ /* Validate region selection */ ++ switch (region) { ++ case OTP_HW_RGN: ++ if (wlen > (uint)(oi->hwlim - oi->hwbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP h/w region limit %u\n", ++ __FUNCTION__, wlen, oi->hwlim - oi->hwbase)); ++ return BCME_BUFTOOLONG; ++ } ++ rewrite = !!(oi->status & OTPS_GUP_HW); ++ base = oi->hwbase; ++ break; ++ case OTP_SW_RGN: ++ if (wlen > (uint)(oi->swlim - oi->swbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP s/w region limit %u\n", ++ __FUNCTION__, wlen, oi->swlim - oi->swbase)); ++ return BCME_BUFTOOLONG; ++ } ++ rewrite = !!(oi->status & OTPS_GUP_SW); ++ base = oi->swbase; ++ break; ++ case OTP_CI_RGN: ++ if (oi->status & OTPS_GUP_CI) { ++ OTP_ERR(("%s: chipid region has been programmed\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (wlen > OTPGU_CI_SZ) { ++ OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n", ++ __FUNCTION__, wlen, OTPGU_CI_SZ)); ++ return BCME_BUFTOOLONG; ++ } ++ if ((wlen == OTPGU_CI_SZ) && (data[OTPGU_CI_SZ - 1] & OTPGU_P_MSK) != 0) { ++ OTP_ERR(("%s: subregion programmed bits not zero\n", __FUNCTION__)); ++ return BCME_BADARG; ++ } ++ base = oi->otpgu_base + OTPGU_CI_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ if (oi->status & OTPS_GUP_FUSE) { ++ OTP_ERR(("%s: fuse region has been programmed\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (wlen > (uint)(oi->flim - oi->fbase)) { ++ OTP_ERR(("%s: wlen %u exceeds OTP ci region limit %u\n", ++ __FUNCTION__, wlen, oi->flim - oi->fbase)); ++ return BCME_BUFTOOLONG; ++ } ++ base = oi->flim - wlen; ++ break; ++ default: ++ OTP_ERR(("%s: writing region %d is not supported\n", __FUNCTION__, region)); ++ return BCME_ERROR; ++ } ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++#if defined(DONGLEBUILD) ++ /* Check for conflict; Since some bits might be programmed at ATE time, we need to ++ * avoid redundancy by clearing already written bits, but copy original for verification. ++ */ ++ if ((origdata = (uint16*)MALLOC(oi->osh, wlen * 2)) == NULL) { ++ rc = BCME_NOMEM; ++ goto exit; ++ } ++ for (i = 0; i < wlen; i++) { ++ origdata[i] = data[i]; ++ data[i] = ipxotp_otpr(oi, cc, base + i); ++ if (data[i] & ~origdata[i]) { ++ OTP_ERR(("%s: %s region: word %d incompatible (0x%04x->0x%04x)\n", ++ __FUNCTION__, HWSW_RGN(region), i, data[i], origdata[i])); ++ rc = BCME_BADARG; ++ goto exit; ++ } ++ data[i] ^= origdata[i]; ++ } ++#endif /* DONGLEBUILD */ ++ ++ OTP_MSG(("%s: writing new bits in %s region\n", __FUNCTION__, HWSW_RGN(region))); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ /* Write the data */ ++ for (i = 0; i < wlen; i++) { ++ rc = ipxotp_otpwb16(oi, cc, base + i, data[i]); ++ if (rc != 0) { ++ OTP_ERR(("%s: otpwb16 failed: %d 0x%x\n", __FUNCTION__, base + i, data[i])); ++ ipxotp_unwritable(oi, cc); ++ goto exit; ++ } ++ } ++ ++ /* One time set region flag: Update boundary/flag in memory and in OTP */ ++ if (!rewrite) { ++ switch (region) { ++ case OTP_HW_RGN: ++ /* OTP unification */ ++ if (oi->buotp) { ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ ((base + oi->usbmanfid_offset) * 16)); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF); ++ } else ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ (base + i) * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_HWP_OFF); ++ if (CHIPID(oi->sih->chip) == BCM4336_CHIP_ID || ++ CHIPID(oi->sih->chip) == BCM43362_CHIP_ID || ++ CHIPID(oi->sih->chip) == BCM4324_CHIP_ID) ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_NEWCISFORMAT_OFF); ++ break; ++ case OTP_SW_RGN: ++ /* Write HW region limit as well */ ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, base * 16); ++ /* write max swlim(covert to bits) to the sw/fuse boundary */ ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, oi->swlim * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_SWP_OFF); ++ break; ++ case OTP_CI_RGN: ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_CIP_OFF); ++ /* Also set the OTPGU_CIP_MSK bit in the input so verification ++ * doesn't fail ++ */ ++ if (wlen >= OTPGU_CI_SZ) ++ data[OTPGU_CI_SZ - 1] |= OTPGU_CIP_MSK; ++ break; ++ case OTP_FUSE_RGN: ++ ipxotp_otpwb16(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF, base * 16); ++ ipxotp_write_bit(oi, cc, otpgu_bit_base + OTPGU_FUSEP_OFF); ++ break; ++ } ++ } ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ ++ /* Check and fix for region size and region programmed bits */ ++ if (!rewrite) { ++ uint16 boundary_off = 0, boundary_val = 0; ++ uint16 programmed_off = 0; ++ uint16 bit = 0; ++ ++ switch (region) { ++ case OTP_HW_RGN: ++ boundary_off = OTPGU_HSB_OFF; ++ /* OTP unification */ ++ if (oi->buotp) { ++ boundary_val = ((base + oi->usbmanfid_offset) * 16); ++ } else ++ boundary_val = (base + i) * 16; ++ programmed_off = OTPGU_HWP_OFF; ++ break; ++ case OTP_SW_RGN: ++ /* Also write 0 to HW region boundary */ ++ if ((rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF, ++ base * 16))) ++ goto exit; ++ boundary_off = OTPGU_SFB_OFF; ++ boundary_val = oi->swlim * 16; ++ programmed_off = OTPGU_SWP_OFF; ++ break; ++ case OTP_CI_RGN: ++ /* No CI region boundary */ ++ programmed_off = OTPGU_CIP_OFF; ++ break; ++ case OTP_FUSE_RGN: ++ boundary_off = OTPGU_SFB_OFF; ++ boundary_val = base * 16; ++ programmed_off = OTPGU_FUSEP_OFF; ++ break; ++ } ++ ++ /* Do the actual checking and return BCME_NORESOURCE if we cannot fix */ ++ if ((region != OTP_CI_RGN) && ++ (rc = ipxotp_check_word16(oi, cc, oi->otpgu_base + boundary_off, ++ boundary_val))) { ++ goto exit; ++ } ++ ++ if ((bit = ipxotp_read_bit(oh, cc, otpgu_bit_base + programmed_off)) == 0xffff) { ++ OTP_ERR(("\n%s: FAILED bit %d reads %d\n", __FUNCTION__, otpgu_bit_base + ++ programmed_off, bit)); ++ goto exit; ++ } else if (bit == 0) { /* error detected, fix it */ ++ OTP_ERR(("\n%s: FAILED bit %d reads %d, fixing\n", __FUNCTION__, ++ otpgu_bit_base + programmed_off, bit)); ++ if ((rc = ipxotp_write_rde(oi, ipxotp_check_otp_pmu_res(cc), ++ otpgu_bit_base + programmed_off, 1))) { ++ OTP_ERR(("\n%s: cannot fix, ipxotp_write_rde returns %d\n", ++ __FUNCTION__, rc)); ++ goto exit; ++ } ++ } ++ } ++ ++ /* Update status, apply WAR */ ++ _ipxotp_init(oi, cc); ++ ++#if defined(DONGLEBUILD) ++ /* Recover original data... */ ++ if (origdata) ++ bcopy(origdata, data, wlen * 2); ++#endif /* DONGLEBUILD */ ++ ++ /* ...Check again so we can verify and fix where possible */ ++ for (i = 0; i < wlen; i++) { ++ if ((rc = ipxotp_check_word16(oi, cc, base + i, data[i]))) ++ goto exit; ++ } ++ ++exit: ++#if defined(DONGLEBUILD) ++ if (origdata) ++ MFREE(oi->osh, origdata, wlen * 2); ++#endif /* DONGLEBUILD */ ++ si_setcoreidx(oi->sih, idx); ++ return rc; ++} ++ ++static int ++ipxotp_write_word(void *oh, uint wn, uint16 data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int rc = 0; ++ uint16 origdata; ++ uint idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Check for conflict */ ++ origdata = data; ++ data = ipxotp_otpr(oi, cc, wn); ++ if (data & ~origdata) { ++ OTP_ERR(("%s: word %d incompatible (0x%04x->0x%04x)\n", ++ __FUNCTION__, wn, data, origdata)); ++ rc = BCME_BADARG; ++ goto exit; ++ } ++ data ^= origdata; ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ rc = ipxotp_otpwb16(oi, cc, wn, data); ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ data = origdata; ++ if ((rc = ipxotp_check_word16(oi, cc, wn, data))) ++ goto exit; ++exit: ++ si_setcoreidx(oi->sih, idx); ++ return rc; ++} ++ ++static int ++ipxotp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ uint8 *cis; ++ osl_t *osh; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int rc = 0; ++ bool newchip = FALSE; ++ uint overwrite = 0; ++ ++ ASSERT(region == OTP_HW_RGN || region == OTP_SW_RGN); ++ ++ osh = si_osh(sih); ++ if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return BCME_ERROR; ++ } ++ ++ bzero(cis, OTP_SZ_MAX); ++ ++ rc = otp_read_region(sih, region, (uint16 *)cis, &sz); ++ newchip = (rc == BCME_NOTFOUND) ? TRUE : FALSE; ++ if ((rc != 0) && (rc != BCME_NOTFOUND)) { ++ return BCME_ERROR; ++ } ++ rc = 0; ++ ++ /* zero count for read, non-zero count for write */ ++ if (count) { ++ int i = 0, newlen = 0; ++ ++ if (newchip) { ++ int termw_len = 0; /* length of termination word */ ++ ++ /* convert halfwords to bytes offset */ ++ newlen = sz * 2; ++ ++ if ((CHIPID(sih->chip) == BCM4322_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43231_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4315_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4319_CHIP_ID)) { ++ /* bootloader WAR, refer to above twiki link */ ++ cis[newlen-1] = 0x00; ++ cis[newlen-2] = 0xff; ++ cis[newlen-3] = 0x00; ++ cis[newlen-4] = 0xff; ++ cis[newlen-5] = 0xff; ++ cis[newlen-6] = 0x1; ++ cis[newlen-7] = 0x2; ++ termw_len = 7; ++ } else { ++ cis[newlen-1] = 0xff; ++ cis[newlen-2] = 0xff; ++ termw_len = 2; ++ } ++ ++ if (count >= newlen - termw_len) { ++ OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", newlen, count)); ++ rc = BCME_BUFTOOLONG; ++ } ++ } else { ++ int end = 0; ++ if (region == OTP_SW_RGN) { ++ /* Walk through the leading zeros (could be 0 or 8 bytes for now) */ ++ for (i = 0; i < (int)sz*2; i++) ++ if (cis[i] != 0) ++ break; ++ } else { ++ /* move pass the hardware header */ ++ if (sih->ccrev >= 36) { ++ uint32 otp_layout; ++ otp_layout = si_corereg(sih, SI_CC_IDX, ++ OFFSETOF(chipcregs_t, otplayout), 0, 0); ++ if (otp_layout & OTP_CISFORMAT_NEW) { ++ i += 4; /* new sdio header format, 2 half words */ ++ } else { ++ i += 8; /* old sdio header format */ ++ } ++ } else { ++ return BCME_ERROR; /* old chip, not suppported */ ++ } ++ } ++ ++ /* Find the place to append */ ++ for (; i < (int)sz*2; i++) { ++ int j; ++ if (cis[i] == 0) ++ break; ++ /* If the tuple exist, check if it can be overwritten */ ++ if (cis[i + 2] == vars[2]) { ++ if (cis[i+1] == vars[1]) { ++ /* found, check if it is compiatable for fix */ ++ for (j = 0; j < cis[i+1] + 2; j++) { ++ if ((cis[i+j] ^ vars[j]) & cis[i+j]) { ++ break; ++ } ++ } ++ if (j == cis[i+1] + 2) { ++ overwrite = i; ++ } ++ } ++ } ++ i += ((int)cis[i+1] + 1); ++ } ++ for (end = i; end < (int)sz*2; end++) { ++ if (cis[end] != 0) ++ break; ++ } ++ if (overwrite) ++ i = overwrite; ++ ++ newlen = i + count; ++ if (newlen & 1) /* make it even-sized buffer */ ++ newlen++; ++ ++ if (newlen >= (end - 1)) { ++ OTP_MSG(("OTP left %x bytes; buffer %x bytes\n", end-i, count)); ++ rc = BCME_BUFTOOLONG; ++ } ++ } ++ ++ /* copy the buffer */ ++ memcpy(&cis[i], vars, count); ++#ifdef BCMNVRAMW ++ /* Write the buffer back */ ++ if (!rc) ++ rc = otp_write_region(sih, region, (uint16*)cis, newlen/2); ++ ++ /* Print the buffer */ ++ OTP_MSG(("Buffer of size %d bytes to write:\n", newlen)); ++ for (i = 0; i < newlen; i++) { ++ OTP_DBG(("%02x ", cis[i] & 0xff)); ++ if ((i % 16) == 15) { ++ OTP_DBG(("\n")); ++ } ++ } ++ OTP_MSG(("\n")); ++#endif /* BCMNVRAMW */ ++ } ++ if (cis) ++ MFREE(osh, cis, OTP_SZ_MAX); ++ ++ return (rc); ++} ++ ++/* No need to lock for IPXOTP */ ++static int ++ipxotp_lock(void *oh) ++{ ++ uint idx; ++ chipcregs_t *cc; ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0, rc = 0; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Enable Write */ ++ ipxotp_writable(oi, cc); ++ ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW1_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock ROW1\n")); ++ rc = -1; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_ROW2_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock ROW2\n")); ++ rc = -2; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_RD_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock RD\n")); ++ rc = -3; ++ } ++ err = ipxotp_write_lock_bit(oi, cc, OTP_LOCK_GU_LOC_OFF); ++ if (err) { ++ OTP_ERR(("fail to lock GU\n")); ++ rc = -4; ++ } ++ ++ /* Disable Write */ ++ ipxotp_unwritable(oi, cc); ++ ++ /* Sync region info by retrieving them again (use PMU bit to power cycle OTP) */ ++ si_otp_power(oi->sih, FALSE); ++ si_otp_power(oi->sih, TRUE); ++ ++ /* Update status, apply WAR */ ++ _ipxotp_init(oi, cc); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return rc; ++} ++ ++static int ++ipxotp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ return -1; ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++static uint16 ++ipxotp_otprb16(void *oh, chipcregs_t *cc, uint wn) ++{ ++ uint base, i; ++ uint16 val; ++ uint16 bit; ++ ++ base = wn * 16; ++ ++ val = 0; ++ for (i = 0; i < 16; i++) { ++ if ((bit = ipxotp_read_bit(oh, cc, base + i)) == 0xffff) ++ break; ++ val = val | (bit << i); ++ } ++ if (i < 16) ++ val = 0xffff; ++ ++ return val; ++} ++ ++static int ++ipxotp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, i, count; ++ uint16 val; ++ struct bcmstrbuf b; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ count = ipxotp_size(oh); ++ ++ bcm_binit(&b, buf, size); ++ for (i = 0; i < count / 2; i++) { ++ if (!(i % 4)) ++ bcm_bprintf(&b, "\n0x%04x:", 2 * i); ++ if (arg == 0) ++ val = ipxotp_otpr(oh, cc, i); ++ else ++ val = ipxotp_otprb16(oi, cc, i); ++ bcm_bprintf(&b, " 0x%04x", val); ++ } ++ bcm_bprintf(&b, "\n"); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ((int)(b.buf - b.origbuf)); ++} ++#endif ++ ++static otp_fn_t ipxotp_fn = { ++ (otp_size_t)ipxotp_size, ++ (otp_read_bit_t)ipxotp_read_bit, ++ (otp_dump_t)NULL, /* Assigned in otp_init */ ++ (otp_status_t)ipxotp_status, ++ ++ (otp_init_t)ipxotp_init, ++ (otp_read_region_t)ipxotp_read_region, ++ (otp_nvread_t)ipxotp_nvread, ++#ifdef BCMNVRAMW ++ (otp_write_region_t)ipxotp_write_region, ++ (otp_cis_append_region_t)ipxotp_cis_append_region, ++ (otp_lock_t)ipxotp_lock, ++ (otp_nvwrite_t)ipxotp_nvwrite, ++ (otp_write_word_t)ipxotp_write_word, ++#else /* BCMNVRAMW */ ++ (otp_write_region_t)NULL, ++ (otp_cis_append_region_t)NULL, ++ (otp_lock_t)NULL, ++ (otp_nvwrite_t)NULL, ++ (otp_write_word_t)NULL, ++#endif /* BCMNVRAMW */ ++ (otp_read_word_t)ipxotp_read_word, ++#if defined(BCMNVRAMW) ++ (otp_write_bits_t)ipxotp_write_bits ++#endif ++}; ++ ++#endif /* BCMIPXOTP */ ++ ++ ++/* ++ * HND OTP Code ++ * ++ * Exported functions: ++ * hndotp_status() ++ * hndotp_size() ++ * hndotp_init() ++ * hndotp_read_bit() ++ * hndotp_read_region() ++ * hndotp_read_word() ++ * hndotp_nvread() ++ * hndotp_write_region() ++ * hndotp_cis_append_region() ++ * hndotp_lock() ++ * hndotp_nvwrite() ++ * hndotp_dump() ++ * ++ * HND internal functions: ++ * hndotp_otpr() ++ * hndotp_otproff() ++ * hndotp_write_bit() ++ * hndotp_write_word() ++ * hndotp_valid_rce() ++ * hndotp_write_rce() ++ * hndotp_write_row() ++ * hndotp_otprb16() ++ * ++ */ ++ ++#ifdef BCMHNDOTP ++ ++/* Fields in otpstatus */ ++#define OTPS_PROGFAIL 0x80000000 ++#define OTPS_PROTECT 0x00000007 ++#define OTPS_HW_PROTECT 0x00000001 ++#define OTPS_SW_PROTECT 0x00000002 ++#define OTPS_CID_PROTECT 0x00000004 ++#define OTPS_RCEV_MSK 0x00003f00 ++#define OTPS_RCEV_SHIFT 8 ++ ++/* Fields in the otpcontrol register */ ++#define OTPC_RECWAIT 0xff000000 ++#define OTPC_PROGWAIT 0x00ffff00 ++#define OTPC_PRW_SHIFT 8 ++#define OTPC_MAXFAIL 0x00000038 ++#define OTPC_VSEL 0x00000006 ++#define OTPC_SELVL 0x00000001 ++ ++/* OTP regions (Word offsets from otp size) */ ++#define OTP_SWLIM_OFF (-4) ++#define OTP_CIDBASE_OFF 0 ++#define OTP_CIDLIM_OFF 4 ++ ++/* Predefined OTP words (Word offset from otp size) */ ++#define OTP_BOUNDARY_OFF (-4) ++#define OTP_HWSIGN_OFF (-3) ++#define OTP_SWSIGN_OFF (-2) ++#define OTP_CIDSIGN_OFF (-1) ++#define OTP_CID_OFF 0 ++#define OTP_PKG_OFF 1 ++#define OTP_FID_OFF 2 ++#define OTP_RSV_OFF 3 ++#define OTP_LIM_OFF 4 ++#define OTP_RD_OFF 4 /* Redundancy row starts here */ ++#define OTP_RC0_OFF 28 /* Redundancy control word 1 */ ++#define OTP_RC1_OFF 32 /* Redundancy control word 2 */ ++#define OTP_RC_LIM_OFF 36 /* Redundancy control word end */ ++ ++#define OTP_HW_REGION OTPS_HW_PROTECT ++#define OTP_SW_REGION OTPS_SW_PROTECT ++#define OTP_CID_REGION OTPS_CID_PROTECT ++ ++#if OTP_HW_REGION != OTP_HW_RGN ++#error "incompatible OTP_HW_RGN" ++#endif ++#if OTP_SW_REGION != OTP_SW_RGN ++#error "incompatible OTP_SW_RGN" ++#endif ++#if OTP_CID_REGION != OTP_CI_RGN ++#error "incompatible OTP_CI_RGN" ++#endif ++ ++/* Redundancy entry definitions */ ++#define OTP_RCE_ROW_SZ 6 ++#define OTP_RCE_SIGN_MASK 0x7fff ++#define OTP_RCE_ROW_MASK 0x3f ++#define OTP_RCE_BITS 21 ++#define OTP_RCE_SIGN_SZ 15 ++#define OTP_RCE_BIT0 1 ++ ++#define OTP_WPR 4 ++#define OTP_SIGNATURE 0x578a ++#define OTP_MAGIC 0x4e56 ++ ++static int ++hndotp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return ((int)(oi->hwprot | oi->signvalid)); ++} ++ ++static int ++hndotp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return ((int)(oi->size)); ++} ++ ++static uint16 ++hndotp_otpr(void *oh, chipcregs_t *cc, uint wn) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ volatile uint16 *ptr; ++ ++ ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF)); ++ ASSERT(cc != NULL); ++ ++ osh = si_osh(oi->sih); ++ ++ ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP); ++ return (R_REG(osh, &ptr[wn])); ++} ++ ++static uint16 ++hndotp_otproff(void *oh, chipcregs_t *cc, int woff) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ volatile uint16 *ptr; ++ ++ ASSERT(woff >= (-((int)oi->size / 2))); ++ ASSERT(woff < OTP_LIM_OFF); ++ ASSERT(cc != NULL); ++ ++ osh = si_osh(oi->sih); ++ ++ ptr = (volatile uint16 *)((volatile char *)cc + CC_SROM_OTP); ++ ++ return (R_REG(osh, &ptr[(oi->size / 2) + woff])); ++} ++ ++static uint16 ++hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint k, row, col; ++ uint32 otpp, st; ++ osl_t *osh; ++ ++ osh = si_osh(oi->sih); ++ row = idx / 65; ++ col = idx % 65; ++ ++ otpp = OTPP_START_BUSY | OTPP_READ | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ (col & OTPP_COL_MASK); ++ ++ OTP_DBG(("%s: idx = %d, row = %d, col = %d, otpp = 0x%x", __FUNCTION__, ++ idx, row, col, otpp)); ++ ++ W_REG(osh, &cc->otpprog, otpp); ++ st = R_REG(osh, &cc->otpprog); ++ for (k = 0; ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ++ st = R_REG(osh, &cc->otpprog); ++ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("\n%s: BUSY stuck: st=0x%x, count=%d\n", __FUNCTION__, st, k)); ++ return 0xffff; ++ } ++ if (st & OTPP_READERR) { ++ OTP_ERR(("\n%s: Could not read OTP bit %d\n", __FUNCTION__, idx)); ++ return 0xffff; ++ } ++ st = (st & OTPP_VALUE_MASK) >> OTPP_VALUE_SHIFT; ++ OTP_DBG((" => %d\n", st)); ++ return (uint16)st; ++} ++ ++static void * ++BCMNMIATTACHFN(hndotp_init)(si_t *sih) ++{ ++ uint idx; ++ chipcregs_t *cc; ++ otpinfo_t *oi; ++ uint32 cap = 0, clkdiv, otpdiv = 0; ++ void *ret = NULL; ++ osl_t *osh; ++ ++ OTP_MSG(("%s: Use HND OTP controller\n", __FUNCTION__)); ++ ++ oi = get_otpinfo(); ++ ++ idx = si_coreidx(sih); ++ osh = si_osh(oi->sih); ++ ++ /* Check for otp */ ++ if ((cc = si_setcoreidx(sih, SI_CC_IDX)) != NULL) { ++ cap = R_REG(osh, &cc->capabilities); ++ if ((cap & CC_CAP_OTPSIZE) == 0) { ++ /* Nothing there */ ++ goto out; ++ } ++ ++ /* As of right now, support only 4320a2, 4311a1 and 4312 */ ++ ASSERT((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22)); ++ if (!((oi->ccrev == 12) || (oi->ccrev == 17) || (oi->ccrev == 22))) ++ return NULL; ++ ++ /* Read the OTP byte size. chipcommon rev >= 18 has RCE so the size is ++ * 8 row (64 bytes) smaller ++ */ ++ oi->size = 1 << (((cap & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) ++ + CC_CAP_OTPSIZE_BASE); ++ if (oi->ccrev >= 18) { ++ oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2); ++ } else { ++ OTP_ERR(("Negative otp size, shouldn't happen for programmed chip.")); ++ oi->size = 0; ++ } ++ ++ oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT); ++ oi->boundary = -1; ++ ++ /* Check the region signature */ ++ if (hndotp_otproff(oi, cc, OTP_HWSIGN_OFF) == OTP_SIGNATURE) { ++ oi->signvalid |= OTP_HW_REGION; ++ oi->boundary = hndotp_otproff(oi, cc, OTP_BOUNDARY_OFF); ++ } ++ ++ if (hndotp_otproff(oi, cc, OTP_SWSIGN_OFF) == OTP_SIGNATURE) ++ oi->signvalid |= OTP_SW_REGION; ++ ++ if (hndotp_otproff(oi, cc, OTP_CIDSIGN_OFF) == OTP_SIGNATURE) ++ oi->signvalid |= OTP_CID_REGION; ++ ++ /* Set OTP clkdiv for stability */ ++ if (oi->ccrev == 22) ++ otpdiv = 12; ++ ++ if (otpdiv) { ++ clkdiv = R_REG(osh, &cc->clkdiv); ++ clkdiv = (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT); ++ W_REG(osh, &cc->clkdiv, clkdiv); ++ OTP_MSG(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv)); ++ } ++ OSL_DELAY(10); ++ ++ ret = (void *)oi; ++ } ++ ++ OTP_MSG(("%s: ccrev %d\tsize %d bytes\thwprot %x\tsignvalid %x\tboundary %x\n", ++ __FUNCTION__, oi->ccrev, oi->size, oi->hwprot, oi->signvalid, ++ oi->boundary)); ++ ++out: /* All done */ ++ si_setcoreidx(sih, idx); ++ ++ return ret; ++} ++ ++static int ++hndotp_read_region(void *oh, int region, uint16 *data, uint *wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 idx, st; ++ chipcregs_t *cc; ++ int i; ++ ++ /* Only support HW region (no active chips use HND OTP SW region) */ ++ ASSERT(region == OTP_HW_REGION); ++ ++ OTP_MSG(("%s: region %x wlen %d\n", __FUNCTION__, region, *wlen)); ++ ++ /* Region empty? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & region) == 0) ++ return BCME_NOTFOUND; ++ ++ *wlen = ((int)*wlen < oi->boundary/2) ? *wlen : (uint)oi->boundary/2; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ for (i = 0; i < (int)*wlen; i++) ++ data[i] = hndotp_otpr(oh, cc, i); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return 0; ++} ++ ++static int ++hndotp_read_word(void *oh, uint wn, uint16 *data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 idx; ++ chipcregs_t *cc; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ *data = hndotp_otpr(oh, cc, wn); ++ ++ si_setcoreidx(oi->sih, idx); ++ return 0; ++} ++ ++static int ++hndotp_nvread(void *oh, char *data, uint *len) ++{ ++ int rc = 0; ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 base, bound, lim = 0, st; ++ int i, chunk, gchunks, tsz = 0; ++ uint32 idx; ++ chipcregs_t *cc; ++ uint offset; ++ uint16 *rawotp = NULL; ++ ++ /* save the orig core */ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ st = hndotp_status(oh); ++ if (!(st & (OTP_HW_REGION | OTP_SW_REGION))) { ++ OTP_ERR(("OTP not programmed\n")); ++ rc = -1; ++ goto out; ++ } ++ ++ /* Read the whole otp so we can easily manipulate it */ ++ lim = hndotp_size(oh); ++ if (lim == 0) { ++ OTP_ERR(("OTP size is 0\n")); ++ rc = -1; ++ goto out; ++ } ++ if ((rawotp = MALLOC(si_osh(oi->sih), lim)) == NULL) { ++ OTP_ERR(("Out of memory for rawotp\n")); ++ rc = -2; ++ goto out; ++ } ++ for (i = 0; i < (int)(lim / 2); i++) ++ rawotp[i] = hndotp_otpr(oh, cc, i); ++ ++ if ((st & OTP_HW_REGION) == 0) { ++ OTP_ERR(("otp: hw region not written (0x%x)\n", st)); ++ ++ /* This could be a programming failure in the first ++ * chunk followed by one or more good chunks ++ */ ++ for (i = 0; i < (int)(lim / 2); i++) ++ if (rawotp[i] == OTP_MAGIC) ++ break; ++ ++ if (i < (int)(lim / 2)) { ++ base = i; ++ bound = (i * 2) + rawotp[i + 1]; ++ OTP_MSG(("otp: trying chunk at 0x%x-0x%x\n", i * 2, bound)); ++ } else { ++ OTP_MSG(("otp: unprogrammed\n")); ++ rc = -3; ++ goto out; ++ } ++ } else { ++ bound = rawotp[(lim / 2) + OTP_BOUNDARY_OFF]; ++ ++ /* There are two cases: 1) The whole otp is used as nvram ++ * and 2) There is a hardware header followed by nvram. ++ */ ++ if (rawotp[0] == OTP_MAGIC) { ++ base = 0; ++ if (bound != rawotp[1]) ++ OTP_MSG(("otp: Bound 0x%x != chunk0 len 0x%x\n", bound, ++ rawotp[1])); ++ } else ++ base = bound; ++ } ++ ++ /* Find and copy the data */ ++ ++ chunk = 0; ++ gchunks = 0; ++ i = base / 2; ++ offset = 0; ++ while ((i < (int)(lim / 2)) && (rawotp[i] == OTP_MAGIC)) { ++ int dsz, rsz = rawotp[i + 1]; ++ ++ if (((i * 2) + rsz) >= (int)lim) { ++ OTP_MSG((" bad chunk size, chunk %d, base 0x%x, size 0x%x\n", ++ chunk, i * 2, rsz)); ++ /* Bad length, try to find another chunk anyway */ ++ rsz = 6; ++ } ++ if (hndcrc16((uint8 *)&rawotp[i], rsz, ++ CRC16_INIT_VALUE) == CRC16_GOOD_VALUE) { ++ /* Good crc, copy the vars */ ++ OTP_MSG((" good chunk %d, base 0x%x, size 0x%x\n", ++ chunk, i * 2, rsz)); ++ gchunks++; ++ dsz = rsz - 6; ++ tsz += dsz; ++ if (offset + dsz >= *len) { ++ OTP_MSG(("Out of memory for otp\n")); ++ goto out; ++ } ++ bcopy((char *)&rawotp[i + 2], &data[offset], dsz); ++ offset += dsz; ++ /* Remove extra null characters at the end */ ++ while (offset > 1 && ++ data[offset - 1] == 0 && data[offset - 2] == 0) ++ offset --; ++ i += rsz / 2; ++ } else { ++ /* bad length or crc didn't check, try to find the next set */ ++ OTP_MSG((" chunk %d @ 0x%x size 0x%x: bad crc, ", ++ chunk, i * 2, rsz)); ++ if (rawotp[i + (rsz / 2)] == OTP_MAGIC) { ++ /* Assume length is good */ ++ i += rsz / 2; ++ } else { ++ while (++i < (int)(lim / 2)) ++ if (rawotp[i] == OTP_MAGIC) ++ break; ++ } ++ if (i < (int)(lim / 2)) ++ OTP_MSG(("trying next base 0x%x\n", i * 2)); ++ else ++ OTP_MSG(("no more chunks\n")); ++ } ++ chunk++; ++ } ++ ++ OTP_MSG((" otp size = %d, boundary = 0x%x, nv base = 0x%x\n", lim, bound, base)); ++ if (tsz != 0) { ++ OTP_MSG((" Found %d bytes in %d good chunks out of %d\n", tsz, gchunks, chunk)); ++ } else { ++ OTP_MSG((" No good chunks found out of %d\n", chunk)); ++ } ++ ++ *len = offset; ++ ++out: ++ if (rawotp) ++ MFREE(si_osh(oi->sih), rawotp, lim); ++ si_setcoreidx(oi->sih, idx); ++ ++ return rc; ++} ++ ++#ifdef BCMNVRAMW ++#if defined(BCMDBG) || defined(WLTEST) ++static uint st_n, st_s, st_hwm, pp_hwm; ++#ifdef OTP_FORCEFAIL ++static uint forcefail_bitcount = 0; ++#endif /* OTP_FORCEFAIL */ ++#endif /* BCMDBG || WLTEST */ ++ ++static int ++hndotp_write_bit(void *oh, chipcregs_t *cc, int bn, bool bit, int no_retry) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint row, col, j, k; ++ uint32 pwait, init_pwait, otpc, otpp, pst, st; ++ osl_t *osh; ++ ++ osh = si_osh(oi->sih); ++ ASSERT((bit >> 1) == 0); ++ ++#ifdef OTP_FORCEFAIL ++ OTP_MSG(("%s: [0x%x] = 0x%x\n", __FUNCTION__, wn * 2, data)); ++#endif ++ ++ /* This is bit-at-a-time writing, future cores may do word-at-a-time */ ++ if (oi->ccrev == 12) { ++ otpc = 0x20000001; ++ init_pwait = 0x00000200; ++ } else if (oi->ccrev == 22) { ++ otpc = 0x20000001; ++ init_pwait = 0x00000400; ++ } else { ++ otpc = 0x20000001; ++ init_pwait = 0x00004000; ++ } ++ ++ pwait = init_pwait; ++ row = bn / 65; ++ col = bn % 65; ++ otpp = OTPP_START_BUSY | ++ ((bit << OTPP_VALUE_SHIFT) & OTPP_VALUE_MASK) | ++ ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | ++ (col & OTPP_COL_MASK); ++ j = 0; ++ while (1) { ++ j++; ++ if (j > 1) { ++ OTP_DBG(("row %d, col %d, val %d, otpc 0x%x, otpp 0x%x\n", ++ row, col, bit, (otpc | pwait), otpp)); ++ } ++ W_REG(osh, &cc->otpcontrol, otpc | pwait); ++ W_REG(osh, &cc->otpprog, otpp); ++ pst = R_REG(osh, &cc->otpprog); ++ for (k = 0; ((pst & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES); k++) ++ pst = R_REG(osh, &cc->otpprog); ++#if defined(BCMDBG) || defined(WLTEST) ++ if (k > pp_hwm) ++ pp_hwm = k; ++#endif /* BCMDBG || WLTEST */ ++ if (k >= OTPP_TRIES) { ++ OTP_ERR(("BUSY stuck: pst=0x%x, count=%d\n", pst, k)); ++ st = OTPS_PROGFAIL; ++ break; ++ } ++ st = R_REG(osh, &cc->otpstatus); ++ if (((st & OTPS_PROGFAIL) == 0) || (pwait == OTPC_PROGWAIT) || (no_retry)) { ++ break; ++ } else { ++ if ((oi->ccrev == 12) || (oi->ccrev == 22)) ++ pwait = (pwait << 3) & OTPC_PROGWAIT; ++ else ++ pwait = (pwait << 1) & OTPC_PROGWAIT; ++ if (pwait == 0) ++ pwait = OTPC_PROGWAIT; ++ } ++ } ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n++; ++ st_s += j; ++ if (j > st_hwm) ++ st_hwm = j; ++#ifdef OTP_FORCEFAIL ++ if (forcefail_bitcount++ == OTP_FORCEFAIL * 16) { ++ OTP_DBG(("Forcing PROGFAIL on bit %d (FORCEFAIL = %d/0x%x)\n", ++ forcefail_bitcount, OTP_FORCEFAIL, OTP_FORCEFAIL)); ++ st = OTPS_PROGFAIL; ++ } ++#endif ++#endif /* BCMDBG || WLTEST */ ++ if (st & OTPS_PROGFAIL) { ++ OTP_ERR(("After %d tries: otpc = 0x%x, otpp = 0x%x/0x%x, otps = 0x%x\n", ++ j, otpc | pwait, otpp, pst, st)); ++ OTP_ERR(("otp prog failed. bit=%d, ppret=%d, ret=%d\n", bit, k, j)); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++hndotp_write_bits(void *oh, int bn, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx; ++ chipcregs_t *cc; ++ int i, j; ++ uint8 temp; ++ ++ if (bn < 0 || bn + bits >= oi->rows * oi->cols) ++ return BCME_RANGE; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ for (i = 0; i < bits; ) { ++ temp = *data++; ++ for (j = 0; j < 8; j++, i++) { ++ if (i >= bits) ++ break; ++ if (hndotp_write_bit(oh, cc, i + bn, (temp & 0x01), 0) != 0) { ++ return -1; ++ } ++ temp >>= 1; ++ } ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ return BCME_OK; ++} ++ ++static int ++hndotp_write_word(void *oh, chipcregs_t *cc, int wn, uint16 data) ++{ ++ uint base, i; ++ int err = 0; ++ ++ OTP_MSG(("%s: wn %d data %x\n", __FUNCTION__, wn, data)); ++ ++ /* There is one test bit for each row */ ++ base = (wn * 16) + (wn / 4); ++ ++ for (i = 0; i < 16; i++) { ++ err += hndotp_write_bit(oh, cc, base + i, data & 1, 0); ++ data >>= 1; ++ /* abort write after first error to avoid stress the charge-pump */ ++ if (err) { ++ OTP_DBG(("%s: wn %d fail on bit %d\n", __FUNCTION__, wn, i)); ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++static int ++hndotp_valid_rce(void *oh, chipcregs_t *cc, int i) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ osl_t *osh; ++ uint32 hwv, fw, rce, e, sign, row, st; ++ ++ ASSERT(oi->ccrev >= 18); ++ ++ /* HW valid bit */ ++ osh = si_osh(oi->sih); ++ st = R_REG(osh, &cc->otpstatus); ++ hwv = (st & OTPS_RCEV_MSK) & (1 << (OTPS_RCEV_SHIFT + i)); ++ BCM_REFERENCE(hwv); ++ ++ if (i < 3) { ++ e = i; ++ fw = hndotp_size(oh)/2 + OTP_RC0_OFF + e; ++ } else { ++ e = i - 3; ++ fw = hndotp_size(oh)/2 + OTP_RC1_OFF + e; ++ } ++ ++ rce = hndotp_otpr(oh, cc, fw+1) << 16 | hndotp_otpr(oh, cc, fw); ++ rce >>= ((e * OTP_RCE_BITS) + OTP_RCE_BIT0 - (e * 16)); ++ row = rce & OTP_RCE_ROW_MASK; ++ sign = (rce >> OTP_RCE_ROW_SZ) & OTP_RCE_SIGN_MASK; ++ ++ OTP_MSG(("rce %d sign %x row %d hwv %x\n", i, sign, row, hwv)); ++ ++ return (sign == OTP_SIGNATURE) ? row : -1; ++} ++ ++static int ++hndotp_write_rce(void *oh, chipcregs_t *cc, int r, uint16* data) ++{ ++ int i, rce = -1; ++ uint32 sign; ++ ++ ASSERT(((otpinfo_t *)oh)->ccrev >= 18); ++ ASSERT(r >= 0 && r < hndotp_size(oh)/(2*OTP_WPR)); ++ ASSERT(data); ++ ++ for (rce = OTP_RCE_ROW_SZ -1; rce >= 0; rce--) { ++ int e, rt, rcr, bit, err = 0; ++ ++ int rr = hndotp_valid_rce(oh, cc, rce); ++ /* redundancy row in use already */ ++ if (rr != -1) { ++ if (rr == r) { ++ OTP_MSG(("%s: row %d already replaced by RCE %d", ++ __FUNCTION__, r, rce)); ++ return 0; ++ } ++ ++ continue; /* If row used, go for the next row */ ++ } ++ ++ /* ++ * previously used bad rce entry maybe treaed as valid rce and used again, abort on ++ * first bit error to avoid stress the charge pump ++ */ ++ ++ /* Write the data to the redundant row */ ++ for (i = 0; i < OTP_WPR; i++) { ++ err += hndotp_write_word(oh, cc, hndotp_size(oh)/2+OTP_RD_OFF+rce*4+i, ++ data[i]); ++ if (err) { ++ OTP_MSG(("fail to write redundant row %d\n", rce)); ++ break; ++ } ++ } ++ ++ /* Now write the redundant row index */ ++ if (rce < 3) { ++ e = rce; ++ rcr = hndotp_size(oh)/2 + OTP_RC0_OFF; ++ } else { ++ e = rce - 3; ++ rcr = hndotp_size(oh)/2 + OTP_RC1_OFF; ++ } ++ ++ /* Write row numer bit-by-bit */ ++ bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0; ++ rt = r; ++ for (i = 0; i < OTP_RCE_ROW_SZ; i++) { ++ /* If any timeout happened, invalidate the subsequent bits with 0 */ ++ if (hndotp_write_bit(oh, cc, bit, (rt & (err ? 0 : 1)), err)) { ++ OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row" ++ " number bit %x\n", __FUNCTION__, r, rce, i)); ++ err++; ++ } ++ rt >>= 1; ++ bit ++; ++ } ++ ++ /* Write the RCE signature bit-by-bit */ ++ sign = OTP_SIGNATURE; ++ for (i = 0; i < OTP_RCE_SIGN_SZ; i++) { ++ /* If any timeout happened, invalidate the subsequent bits with 0 */ ++ if (hndotp_write_bit(oh, cc, bit, (sign & (err ? 0 : 1)), err)) { ++ OTP_MSG(("%s: timeout fixing row %d with RCE %d - at row" ++ " number bit %x\n", __FUNCTION__, r, rce, i)); ++ err++; ++ } ++ sign >>= 1; ++ bit ++; ++ } ++ ++ if (err) { ++ OTP_ERR(("%s: row %d not fixed by RCE %d due to %d timeouts. try next" ++ " RCE\n", __FUNCTION__, r, rce, err)); ++ continue; ++ } else { ++ OTP_MSG(("%s: Fixed row %d by RCE %d\n", __FUNCTION__, r, rce)); ++ return BCME_OK; ++ } ++ } ++ ++ OTP_ERR(("All RCE's are in use. Failed fixing OTP.\n")); ++ /* Fatal error, unfixable. MFGC will have to fail. Board needs to be discarded!! */ ++ return BCME_NORESOURCE; ++} ++ ++/* Write a row and fix it with RCE if any error detected */ ++static int ++hndotp_write_row(void *oh, chipcregs_t *cc, int wn, uint16* data, bool rewrite) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int err = 0, i; ++ ++ ASSERT(wn % OTP_WPR == 0); ++ ++ /* Write the data */ ++ for (i = 0; i < OTP_WPR; i++) { ++ if (rewrite && (data[i] == hndotp_otpr(oh, cc, wn+i))) ++ continue; ++ ++ err += hndotp_write_word(oh, cc, wn + i, data[i]); ++ } ++ ++ /* Fix this row if any error */ ++ if (err && (oi->ccrev >= 18)) { ++ OTP_DBG(("%s: %d write errors in row %d. Fixing...\n", __FUNCTION__, err, wn/4)); ++ if ((err = hndotp_write_rce(oh, cc, wn / OTP_WPR, data))) ++ OTP_MSG(("%s: failed to fix row %d\n", __FUNCTION__, wn/4)); ++ } ++ ++ return err; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++hndotp_write_region(void *oh, int region, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 st; ++ uint wn, base = 0, lim; ++ int ret = BCME_OK; ++ uint idx; ++ chipcregs_t *cc; ++ bool rewrite = FALSE; ++ uint32 save_clk; ++ ++ ASSERT(wlen % OTP_WPR == 0); ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Check valid region */ ++ if ((region != OTP_HW_REGION) && ++ (region != OTP_SW_REGION) && ++ (region != OTP_CID_REGION)) { ++ ret = BCME_BADARG; ++ goto out; ++ } ++ ++ /* Region already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & region) != 0) ++ rewrite = TRUE; ++ ++ /* HW and CID have to be written before SW */ ++ if ((((st & (OTP_HW_REGION | OTP_CID_REGION)) == 0) && ++ (st & OTP_SW_REGION) != 0)) { ++ OTP_ERR(("%s: HW/CID region should be programmed first\n", __FUNCTION__)); ++ ret = BCME_BADARG; ++ goto out; ++ } ++ ++ /* Bounds for the region */ ++ lim = (oi->size / 2) + OTP_SWLIM_OFF; ++ if (region == OTP_HW_REGION) { ++ base = 0; ++ } else if (region == OTP_SW_REGION) { ++ base = oi->boundary / 2; ++ } else if (region == OTP_CID_REGION) { ++ base = (oi->size / 2) + OTP_CID_OFF; ++ lim = (oi->size / 2) + OTP_LIM_OFF; ++ } ++ ++ if (wlen > (lim - base)) { ++ ret = BCME_BUFTOOLONG; ++ goto out; ++ } ++ lim = base + wlen; ++ ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n = st_s = st_hwm = pp_hwm = 0; ++#endif /* BCMDBG || WLTEST */ ++ ++ /* force ALP for progrramming stability */ ++ save_clk = R_REG(oi->osh, &cc->clk_ctl_st); ++ OR_REG(oi->osh, &cc->clk_ctl_st, CCS_FORCEALP); ++ OSL_DELAY(10); ++ ++ /* Write the data row by row */ ++ for (wn = base; wn < lim; wn += OTP_WPR, data += OTP_WPR) { ++ if ((ret = hndotp_write_row(oh, cc, wn, data, rewrite)) != 0) { ++ if (ret == BCME_NORESOURCE) { ++ OTP_ERR(("%s: Abort at word %x\n", __FUNCTION__, wn)); ++ break; ++ } ++ } ++ } ++ ++ /* Don't need to update signature & boundary if rewrite */ ++ if (rewrite) ++ goto out_rclk; ++ ++ /* Done with the data, write the signature & boundary if needed */ ++ if (region == OTP_HW_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, lim * 2) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->boundary = lim * 2; ++ oi->signvalid |= OTP_HW_REGION; ++ } else if (region == OTP_SW_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_SWSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->signvalid |= OTP_SW_REGION; ++ } else if (region == OTP_CID_REGION) { ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_CIDSIGN_OFF, ++ OTP_SIGNATURE) != 0) { ++ ret = BCME_NORESOURCE; ++ goto out_rclk; ++ } ++ oi->signvalid |= OTP_CID_REGION; ++ } ++ ++out_rclk: ++ /* Restore clock */ ++ W_REG(oi->osh, &cc->clk_ctl_st, save_clk); ++ ++out: ++#if defined(BCMDBG) || defined(WLTEST) ++ OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n", ++ st_n, st_s, st_n, st_n?(st_s / st_n):0, st_hwm, pp_hwm)); ++#endif ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ret; ++} ++ ++/* For HND OTP, there's no space for appending after filling in SROM image */ ++static int ++hndotp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ return otp_write_region(sih, region, (uint16*)vars, count/2); ++} ++ ++/* ++ * Fill all unwritten RCE signature with 0 and return the number of them. ++ * HNDOTP needs lock due to the randomness of unprogrammed content. ++ */ ++static int ++hndotp_lock(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ int i, j, e, rcr, bit, ret = 0; ++ uint32 st, idx; ++ chipcregs_t *cc; ++ ++ ASSERT(oi->ccrev >= 18); ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Region already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == 0) { ++ si_setcoreidx(oi->sih, idx); ++ return BCME_NOTREADY; /* Don't lock unprogrammed OTP */ ++ } ++ ++ /* Find the highest valid RCE */ ++ for (i = 0; i < OTP_RCE_ROW_SZ -1; i++) { ++ if ((hndotp_valid_rce(oh, cc, i) != -1)) ++ break; ++ } ++ i--; /* Start invalidating from the next RCE */ ++ ++ for (; i >= 0; i--) { ++ if ((hndotp_valid_rce(oh, cc, i) == -1)) { ++ ++ ret++; /* This is a unprogrammed row */ ++ ++ /* Invalidate the row with 0 */ ++ if (i < 3) { ++ e = i; ++ rcr = hndotp_size(oh)/2 + OTP_RC0_OFF; ++ } else { ++ e = i - 3; ++ rcr = hndotp_size(oh)/2 + OTP_RC1_OFF; ++ } ++ ++ /* Fill row numer and signature with 0 bit-by-bit */ ++ bit = (rcr * 16 + rcr / 4) + e * OTP_RCE_BITS + OTP_RCE_BIT0; ++ for (j = 0; j < (OTP_RCE_ROW_SZ + OTP_RCE_SIGN_SZ); j++) { ++ hndotp_write_bit(oh, cc, bit, 0, 1); ++ bit ++; ++ } ++ ++ OTP_MSG(("locking rce %d\n", i)); ++ } ++ } ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ret; ++} ++ ++/* expects the caller to disable interrupts before calling this routine */ ++static int ++hndotp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint32 st; ++ uint16 crc, clen, *p, hdr[2]; ++ uint wn, base = 0, lim; ++ int err, gerr = 0; ++ uint idx; ++ chipcregs_t *cc; ++ ++ /* otp already written? */ ++ st = oi->hwprot | oi-> signvalid; ++ if ((st & (OTP_HW_REGION | OTP_SW_REGION)) == (OTP_HW_REGION | OTP_SW_REGION)) ++ return BCME_EPERM; ++ ++ /* save the orig core */ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ /* Bounds for the region */ ++ lim = (oi->size / 2) + OTP_SWLIM_OFF; ++ base = 0; ++ ++ /* Look for possible chunks from the end down */ ++ wn = lim; ++ while (wn > 0) { ++ wn--; ++ if (hndotp_otpr(oh, cc, wn) == OTP_MAGIC) { ++ base = wn + (hndotp_otpr(oh, cc, wn + 1) / 2); ++ break; ++ } ++ } ++ if (base == 0) { ++ OTP_MSG(("Unprogrammed otp\n")); ++ } else { ++ OTP_MSG(("Found some chunks, skipping to 0x%x\n", base * 2)); ++ } ++ if ((wlen + 3) > (lim - base)) { ++ err = BCME_NORESOURCE; ++ goto out; ++ } ++ ++#if defined(BCMDBG) || defined(WLTEST) ++ st_n = st_s = st_hwm = pp_hwm = 0; ++#endif /* BCMDBG || WLTEST */ ++ ++ /* Prepare the header and crc */ ++ hdr[0] = OTP_MAGIC; ++ hdr[1] = (wlen + 3) * 2; ++ crc = hndcrc16((uint8 *)hdr, sizeof(hdr), CRC16_INIT_VALUE); ++ crc = hndcrc16((uint8 *)data, wlen * 2, crc); ++ crc = ~crc; ++ ++ do { ++ p = data; ++ wn = base + 2; ++ lim = base + wlen + 2; ++ ++ OTP_MSG(("writing chunk, 0x%x bytes @ 0x%x-0x%x\n", wlen * 2, ++ base * 2, (lim + 1) * 2)); ++ ++ /* Write the header */ ++ err = hndotp_write_word(oh, cc, base, hdr[0]); ++ ++ /* Write the data */ ++ while (wn < lim) { ++ err += hndotp_write_word(oh, cc, wn++, *p++); ++ ++ /* If there has been an error, close this chunk */ ++ if (err != 0) { ++ OTP_MSG(("closing early @ 0x%x\n", wn * 2)); ++ break; ++ } ++ } ++ ++ /* If we wrote the whole chunk, write the crc */ ++ if (wn == lim) { ++ OTP_MSG((" whole chunk written, crc = 0x%x\n", crc)); ++ err += hndotp_write_word(oh, cc, wn++, crc); ++ clen = hdr[1]; ++ } else { ++ /* If there was an error adjust the count to point to ++ * the word after the error so we can start the next ++ * chunk there. ++ */ ++ clen = (wn - base) * 2; ++ OTP_MSG((" partial chunk written, chunk len = 0x%x\n", clen)); ++ } ++ /* And now write the chunk length */ ++ err += hndotp_write_word(oh, cc, base + 1, clen); ++ ++ if (base == 0) { ++ /* Write the signature and boundary if this is the HW region, ++ * but don't report failure if either of these 2 writes fail. ++ */ ++ if (hndotp_write_word(oh, cc, (oi->size / 2) + OTP_BOUNDARY_OFF, ++ wn * 2) == 0) ++ gerr += hndotp_write_word(oh, cc, (oi->size / 2) + OTP_HWSIGN_OFF, ++ OTP_SIGNATURE); ++ else ++ gerr++; ++ oi->boundary = wn * 2; ++ oi->signvalid |= OTP_HW_REGION; ++ } ++ ++ if (err != 0) { ++ gerr += err; ++ /* Errors, do it all over again if there is space left */ ++ if ((wlen + 3) <= ((oi->size / 2) + OTP_SWLIM_OFF - wn)) { ++ base = wn; ++ lim = base + wlen + 2; ++ OTP_ERR(("Programming errors, retry @ 0x%x\n", wn * 2)); ++ } else { ++ OTP_ERR(("Programming errors, no space left ( 0x%x)\n", wn * 2)); ++ break; ++ } ++ } ++ } while (err != 0); ++ ++ OTP_MSG(("bits written: %d, average (%d/%d): %d, max retry: %d, pp max: %d\n", ++ st_n, st_s, st_n, st_s / st_n, st_hwm, pp_hwm)); ++ ++ if (gerr != 0) ++ OTP_MSG(("programming %s after %d errors\n", (err == 0) ? "succedded" : "failed", ++ gerr)); ++out: ++ /* done */ ++ si_setcoreidx(oi->sih, idx); ++ ++ if (err) ++ return BCME_ERROR; ++ else ++ return 0; ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++static uint16 ++hndotp_otprb16(void *oh, chipcregs_t *cc, uint wn) ++{ ++ uint base, i; ++ uint16 val, bit; ++ ++ base = (wn * 16) + (wn / 4); ++ val = 0; ++ for (i = 0; i < 16; i++) { ++ if ((bit = hndotp_read_bit(oh, cc, base + i)) == 0xffff) ++ break; ++ val = val | (bit << i); ++ } ++ if (i < 16) ++ val = 0xaaaa; ++ return val; ++} ++ ++static int ++hndotp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ chipcregs_t *cc; ++ uint idx, i, count, lil; ++ uint16 val; ++ struct bcmstrbuf b; ++ ++ idx = si_coreidx(oi->sih); ++ cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ ASSERT(cc != NULL); ++ ++ if (arg >= 16) ++ arg -= 16; ++ ++ if (arg == 2) { ++ count = 66 * 4; ++ lil = 3; ++ } else { ++ count = (oi->size / 2) + OTP_RC_LIM_OFF; ++ lil = 7; ++ } ++ ++ OTP_MSG(("%s: arg %d, size %d, words %d\n", __FUNCTION__, arg, size, count)); ++ bcm_binit(&b, buf, size); ++ for (i = 0; i < count; i++) { ++ if ((i & lil) == 0) ++ bcm_bprintf(&b, "0x%04x:", 2 * i); ++ ++ if (arg == 0) ++ val = hndotp_otpr(oh, cc, i); ++ else ++ val = hndotp_otprb16(oi, cc, i); ++ bcm_bprintf(&b, " 0x%04x", val); ++ if ((i & lil) == lil) { ++ if (arg == 2) { ++ bcm_bprintf(&b, " %d\n", ++ hndotp_read_bit(oh, cc, ((i / 4) * 65) + 64) & 1); ++ } else { ++ bcm_bprintf(&b, "\n"); ++ } ++ } ++ } ++ if ((i & lil) != lil) ++ bcm_bprintf(&b, "\n"); ++ ++ OTP_MSG(("%s: returning %d, left %d, wn %d\n", ++ __FUNCTION__, (int)(b.buf - b.origbuf), b.size, i)); ++ ++ si_setcoreidx(oi->sih, idx); ++ ++ return ((int)(b.buf - b.origbuf)); ++} ++#endif ++ ++static otp_fn_t hndotp_fn = { ++ (otp_size_t)hndotp_size, ++ (otp_read_bit_t)hndotp_read_bit, ++ (otp_dump_t)NULL, /* Assigned in otp_init */ ++ (otp_status_t)hndotp_status, ++ ++ (otp_init_t)hndotp_init, ++ (otp_read_region_t)hndotp_read_region, ++ (otp_nvread_t)hndotp_nvread, ++#ifdef BCMNVRAMW ++ (otp_write_region_t)hndotp_write_region, ++ (otp_cis_append_region_t)hndotp_cis_append_region, ++ (otp_lock_t)hndotp_lock, ++ (otp_nvwrite_t)hndotp_nvwrite, ++ (otp_write_word_t)NULL, ++#else /* BCMNVRAMW */ ++ (otp_write_region_t)NULL, ++ (otp_cis_append_region_t)NULL, ++ (otp_lock_t)NULL, ++ (otp_nvwrite_t)NULL, ++ (otp_write_word_t)NULL, ++#endif /* BCMNVRAMW */ ++ (otp_read_word_t)hndotp_read_word, ++#if defined(BCMNVRAMW) ++ (otp_write_bits_t)hndotp_write_bits ++#endif ++}; ++ ++#endif /* BCMHNDOTP */ ++ ++/* ++ * Common Code: Compiled for IPX / HND / AUTO ++ * otp_status() ++ * otp_size() ++ * otp_read_bit() ++ * otp_init() ++ * otp_read_region() ++ * otp_read_word() ++ * otp_nvread() ++ * otp_write_region() ++ * otp_write_word() ++ * otp_cis_append_region() ++ * otp_lock() ++ * otp_nvwrite() ++ * otp_dump() ++ */ ++ ++int ++otp_status(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->status(oh); ++} ++ ++int ++otp_size(void *oh) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->size(oh); ++} ++ ++uint16 ++otp_read_bit(void *oh, uint offset) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ uint idx = si_coreidx(oi->sih); ++ chipcregs_t *cc = si_setcoreidx(oi->sih, SI_CC_IDX); ++ uint16 readBit = (uint16)oi->fn->read_bit(oh, cc, offset); ++ si_setcoreidx(oi->sih, idx); ++ return readBit; ++} ++ ++#if defined(BCMNVRAMW) ++int ++otp_write_bits(void *oh, uint offset, int bits, uint8* data) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ return oi->fn->write_bits(oh, offset, bits, data); ++} ++#endif ++ ++void * ++BCMNMIATTACHFN(otp_init)(si_t *sih) ++{ ++ otpinfo_t *oi; ++ void *ret = NULL; ++ bool wasup = FALSE; ++ ++ oi = get_otpinfo(); ++ bzero(oi, sizeof(otpinfo_t)); ++ ++ oi->ccrev = sih->ccrev; ++ ++#ifdef BCMIPXOTP ++ if (OTPTYPE_IPX(oi->ccrev)) { ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++ /* Dump function is excluded from ROM */ ++ ipxotp_fn.dump = ipxotp_dump; ++#endif ++ oi->fn = &ipxotp_fn; ++ } ++#endif /* BCMIPXOTP */ ++ ++#ifdef BCMHNDOTP ++ if (OTPTYPE_HND(oi->ccrev)) { ++#if defined(WLTEST) && !defined(BCMROMBUILD) ++ /* Dump function is excluded from ROM */ ++ hndotp_fn.dump = hndotp_dump; ++#endif ++ oi->fn = &hndotp_fn; ++ } ++#endif /* BCMHNDOTP */ ++ ++ if (oi->fn == NULL) { ++ OTP_ERR(("otp_init: unsupported OTP type\n")); ++ return NULL; ++ } ++ ++ oi->sih = sih; ++ oi->osh = si_osh(oi->sih); ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ ret = (oi->fn->init)(sih); ++ ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return ret; ++} ++ ++int ++BCMNMIATTACHFN(otp_read_region)(si_t *sih, int region, uint16 *data, uint *wlen) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ err = (((otpinfo_t*)oh)->fn->read_region)(oh, region, data, wlen); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_read_word(si_t *sih, uint wn, uint16 *data) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ if (((otpinfo_t*)oh)->fn->read_word == NULL) { ++ err = BCME_UNSUPPORTED; ++ goto out; ++ } ++ err = (((otpinfo_t*)oh)->fn->read_word)(oh, wn, data); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_nvread(void *oh, char *data, uint *len) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->nvread(oh, data, len); ++} ++ ++#ifdef BCMNVRAMW ++int ++BCMNMIATTACHFN(otp_write_region)(si_t *sih, int region, uint16 *data, uint wlen) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ err = (((otpinfo_t*)oh)->fn->write_region)(oh, region, data, wlen); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_write_word(si_t *sih, uint wn, uint16 data) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int err = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ err = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ err = BCME_ERROR; ++ goto out; ++ } ++ ++ if (((otpinfo_t*)oh)->fn->write_word == NULL) { ++ err = BCME_UNSUPPORTED; ++ goto out; ++ } ++ err = (((otpinfo_t*)oh)->fn->write_word)(oh, wn, data); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return err; ++} ++ ++int ++otp_cis_append_region(si_t *sih, int region, char *vars, int count) ++{ ++ void *oh = otp_init(sih); ++ ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ return -1; ++ } ++ return (((otpinfo_t*)oh)->fn->cis_append_region)(sih, region, vars, count); ++} ++ ++int ++otp_lock(si_t *sih) ++{ ++ bool wasup = FALSE; ++ void *oh; ++ int ret = 0; ++ ++ if (!(wasup = si_is_otp_powered(sih))) ++ si_otp_power(sih, TRUE); ++ ++ if (!si_is_otp_powered(sih) || si_is_otp_disabled(sih)) { ++ ret = BCME_NOTREADY; ++ goto out; ++ } ++ ++ oh = otp_init(sih); ++ if (oh == NULL) { ++ OTP_ERR(("otp_init failed.\n")); ++ ret = BCME_ERROR; ++ goto out; ++ } ++ ++ ret = (((otpinfo_t*)oh)->fn->lock)(oh); ++ ++out: ++ if (!wasup) ++ si_otp_power(sih, FALSE); ++ ++ return ret; ++} ++ ++int ++otp_nvwrite(void *oh, uint16 *data, uint wlen) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ return oi->fn->nvwrite(oh, data, wlen); ++} ++#endif /* BCMNVRAMW */ ++ ++#if defined(WLTEST) ++int ++otp_dump(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ ++ if (oi->fn->dump == NULL) ++ return BCME_UNSUPPORTED; ++ else ++ return oi->fn->dump(oh, arg, buf, size); ++} ++ ++int ++otp_dumpstats(void *oh, int arg, char *buf, uint size) ++{ ++ otpinfo_t *oi = (otpinfo_t *)oh; ++ struct bcmstrbuf b; ++ ++ bcm_binit(&b, buf, size); ++ ++ bcm_bprintf(&b, "\nOTP, ccrev 0x%04x\n", oi->ccrev); ++#if defined(BCMIPXOTP) ++ bcm_bprintf(&b, "wsize %d rows %d cols %d\n", oi->wsize, oi->rows, oi->cols); ++ bcm_bprintf(&b, "hwbase %d hwlim %d swbase %d swlim %d fusebits %d\n", ++ oi->hwbase, oi->hwlim, oi->swbase, oi->swlim, oi->fbase, oi->flim, oi->fusebits); ++ bcm_bprintf(&b, "otpgu_base %d status %d\n", oi->otpgu_base, oi->status); ++#endif ++#if defined(BCMHNDOTP) ++ bcm_bprintf(&b, "OLD OTP, size %d hwprot 0x%x signvalid 0x%x boundary %d\n", ++ oi->size, oi->hwprot, oi->signvalid, oi->boundary); ++#endif ++ bcm_bprintf(&b, "\n"); ++ ++ return 200; /* real buf length, pick one to cover above print */ ++} ++ ++#endif +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c b/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c +new file mode 100755 +index 0000000..df74e4b +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmrobo.c +@@ -0,0 +1,1548 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom 53xx RoboSwitch device driver. ++ * ++ * $Id: bcmrobo.c 327582 2012-04-14 05:02:37Z $ ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_IPROC_OTP) ++#include "bcm5301x_otp.h" ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++#ifdef BCMDBG ++#define ET_ERROR(args) printf args ++#else /* BCMDBG */ ++#define ET_ERROR(args) ++#endif /* BCMDBG */ ++#define ET_MSG(args) ++ ++#define VARG(var, len) (((len) == 1) ? *((uint8 *)(var)) : \ ++ ((len) == 2) ? *((uint16 *)(var)) : \ ++ *((uint32 *)(var))) ++ ++//#define BRCM_TAG true ++ ++/* Page numbers */ ++#define PAGE_CTRL 0x00 /* Control page */ ++#define PAGE_STATUS 0x01 /* Status page */ ++#define PAGE_MMR 0x02 /* 5397 Management/Mirroring page */ ++#define PAGE_VTBL 0x05 /* ARL/VLAN Table access page */ ++#define PAGE_GPHYP0 0x10 /* Port0 internal GPHY registers page */ ++#define PAGE_VLAN 0x34 /* VLAN page */ ++ ++/* Control page registers */ ++#define REG_CTRL_PORT0 0x00 /* Port 0 traffic control register */ ++#define REG_CTRL_PORT1 0x01 /* Port 1 traffic control register */ ++#define REG_CTRL_PORT2 0x02 /* Port 2 traffic control register */ ++#define REG_CTRL_PORT3 0x03 /* Port 3 traffic control register */ ++#define REG_CTRL_PORT4 0x04 /* Port 4 traffic control register */ ++#define REG_CTRL_PORT5 0x05 /* Port 5 traffic control register */ ++#define REG_CTRL_PORT6 0x06 /* Port 6 traffic control register */ ++#define REG_CTRL_PORT7 0x07 /* Port 7 traffic control register */ ++#define REG_CTRL_IMP 0x08 /* IMP port traffic control register */ ++#define REG_CTRL_MODE 0x0B /* Switch Mode register */ ++#define REG_CTRL_MIIPO 0x0E /* 5325: MII Port Override register */ ++#define REG_CTRL_PWRDOWN 0x0F /* 5325: Power Down Mode register */ ++#define REG_CTRL_PPORT 0x24 /* Protected port register */ ++#define REG_CTRL_PHY_PWR 0x4a /* phy power down register */ ++#define REG_CTRL_SRST 0x79 /* Software reset control register */ ++ ++/* Status Page Registers */ ++#define REG_STATUS_LINK 0x00 /* Link Status Summary */ ++#define REG_STATUS_REV 0x50 /* Revision Register */ ++ ++#define REG_MGMT_CFG 0x00 /* Global Management Configuration */ ++#define REG_BRCM_HDR 0x03 /* BRCM Header Control */ ++#define REG_DEVICE_ID 0x30 /* 539x Device id: */ ++ ++/* VLAN page registers */ ++#define REG_VLAN_CTRL0 0x00 /* VLAN Control 0 register */ ++#define REG_VLAN_CTRL1 0x01 /* VLAN Control 1 register */ ++#define REG_VLAN_CTRL4 0x04 /* VLAN Control 4 register */ ++#define REG_VLAN_CTRL5 0x06 /* VLAN Control 5 register */ ++#define REG_VLAN_ACCESS 0x06 /* VLAN Table Access register */ ++#define REG_VLAN_WRITE 0x08 /* VLAN Write register */ ++#define REG_VLAN_READ 0x0C /* VLAN Read register */ ++#define REG_VLAN_PTAG0 0x10 /* VLAN Default Port Tag register - port 0 */ ++#define REG_VLAN_PTAG1 0x12 /* VLAN Default Port Tag register - port 1 */ ++#define REG_VLAN_PTAG2 0x14 /* VLAN Default Port Tag register - port 2 */ ++#define REG_VLAN_PTAG3 0x16 /* VLAN Default Port Tag register - port 3 */ ++#define REG_VLAN_PTAG4 0x18 /* VLAN Default Port Tag register - port 4 */ ++#define REG_VLAN_PTAG5 0x1a /* VLAN Default Port Tag register - port 5 */ ++#define REG_VLAN_PTAG6 0x1c /* VLAN Default Port Tag register - port 6 */ ++#define REG_VLAN_PTAG7 0x1e /* VLAN Default Port Tag register - port 7 */ ++#define REG_VLAN_PTAG8 0x20 /* 539x: VLAN Default Port Tag register - IMP port */ ++#define REG_VLAN_PMAP 0x20 /* 5325: VLAN Priority Re-map register */ ++ ++/* Port0 internal GPHY registers page */ ++#define PAGE_GPHYP0_DSP_COEF 0x2a /* dsp coefficient */ ++#define PAGE_GPHYP0_DSP_COEF_ADDR 0x2e /* dsp coefficient address */ ++ ++#define VLAN_NUMVLANS 16 /* # of VLANs */ ++ ++ ++/* ARL/VLAN Table Access page registers */ ++#define REG_VTBL_CTRL 0x00 /* ARL Read/Write Control */ ++#define REG_VTBL_MINDX 0x02 /* MAC Address Index */ ++#define REG_VTBL_VINDX 0x08 /* VID Table Index */ ++#define REG_VTBL_ARL_E0 0x10 /* ARL Entry 0 */ ++#define REG_VTBL_ARL_E1 0x18 /* ARL Entry 1 */ ++#define REG_VTBL_DAT_E0 0x18 /* ARL Table Data Entry 0 */ ++#define REG_VTBL_SCTRL 0x20 /* ARL Search Control */ ++#define REG_VTBL_SADDR 0x22 /* ARL Search Address */ ++#define REG_VTBL_SRES 0x24 /* ARL Search Result */ ++#define REG_VTBL_SREXT 0x2c /* ARL Search Result */ ++#define REG_VTBL_VID_E0 0x30 /* VID Entry 0 */ ++#define REG_VTBL_VID_E1 0x32 /* VID Entry 1 */ ++#define REG_VTBL_PREG 0xFF /* Page Register */ ++#define REG_VTBL_ACCESS 0x60 /* VLAN table access register */ ++#define REG_VTBL_INDX 0x61 /* VLAN table address index register */ ++#define REG_VTBL_ENTRY 0x63 /* VLAN table entry register */ ++#define REG_VTBL_ACCESS_5395 0x80 /* VLAN table access register */ ++#define REG_VTBL_INDX_5395 0x81 /* VLAN table address index register */ ++#define REG_VTBL_ENTRY_5395 0x83 /* VLAN table entry register */ ++ ++#define SRAB_MAX_RETRY 1000 ++ ++#if defined(CONFIG_IPROC_OTP) ++void * (*bcm5301x_otp_init_fptr )(void) = NULL; ++int (*bcm5301x_otp_read_dword_fptr)(void *oh, uint wn, u32 *data) = NULL; ++int (*bcm5301x_otp_exit_fptr)(void) = NULL; ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++static int ++srab_request_grant(robo_info_t *robo) ++{ ++ int i, ret = 0; ++ uint32 val32; ++ ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ val32 |= CFG_F_rcareq_MASK; ++ W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); ++ ++ /* Wait for command complete */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ if ((val32 & CFG_F_rcagnt_MASK)) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_request_grant: timeout")); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static void ++srab_release_grant(robo_info_t *robo) ++{ ++ uint32 val32; ++ ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ val32 &= ~CFG_F_rcareq_MASK; ++ W_REG(si_osh(robo->sih), &robo->srabregs->ctrls, val32); ++} ++ ++static int ++srab_interface_reset(robo_info_t *robo) ++{ ++ int i, ret = 0; ++ uint32 val32; ++ ++ /* Wait for switch initialization complete */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->ctrls); ++ if ((val32 & CFG_F_sw_init_done_MASK)) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_interface_reset: timeout sw_init_done")); ++ ret = -1; ++ } ++ ++ /* Set the SRAU reset bit */ ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, CFG_F_sra_rst_MASK); ++ ++ /* Wait for it to auto-clear */ ++ for (i = SRAB_MAX_RETRY * 10; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_rst_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_interface_reset: timeout sra_rst")); ++ ret |= -2; ++ } ++ ++ return ret; ++} ++ ++static int ++srab_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) ++{ ++ uint16 val16; ++ uint32 val32; ++ uint32 val_h = 0, val_l = 0; ++ int i, ret = 0; ++ uint8 *ptr = (uint8 *)val; ++ ++ /* validate value length and buffer address */ ++ ASSERT(len == 1 || len == 6 || len == 8 || ++ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); ++ ++ ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg, ++ VARG(val, len), len)); ++ ++ srab_request_grant(robo); ++ ++ /* Load the value to write */ ++ switch (len) { ++ case 8: ++ val16 = ptr[7]; ++ val16 = ((val16 << 8) | ptr[6]); ++ val_h = val16 << 16; ++ /* FALLTHRU */ ++ ++ case 6: ++ val16 = ptr[5]; ++ val16 = ((val16 << 8) | ptr[4]); ++ val_h |= val16; ++ ++ val16 = ptr[3]; ++ val16 = ((val16 << 8) | ptr[2]); ++ val_l = val16 << 16; ++ val16 = ptr[1]; ++ val16 = ((val16 << 8) | ptr[0]); ++ val_l |= val16; ++ break; ++ ++ case 4: ++ val_l = *(uint32 *)val; ++ break; ++ ++ case 2: ++ val_l = *(uint16 *)val; ++ break; ++ ++ case 1: ++ val_l = *(uint8 *)val; ++ break; ++ } ++ W_REG(si_osh(robo->sih), &robo->srabregs->wd_h, val_h); ++ W_REG(si_osh(robo->sih), &robo->srabregs->wd_l, val_l); ++ ++ /* We don't need this variable */ ++ if (robo->page != page) ++ robo->page = page; ++ ++ /* Issue the write command */ ++ val32 = ((page << CFG_F_sra_page_R) ++ | (reg << CFG_F_sra_offset_R) ++ | CFG_F_sra_gordyn_MASK ++ | CFG_F_sra_write_MASK); ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); ++ ++ /* Wait for command complete */ ++ for (i = SRAB_MAX_RETRY; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_gordyn_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_wreg: timeout")); ++ srab_interface_reset(robo); ++ ret = -1; ++ } ++ ++ srab_release_grant(robo); ++ ++ return ret; ++} ++ ++static int ++srab_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len) ++{ ++ uint32 val32; ++ uint32 val_h = 0, val_l = 0; ++ int i, ret = 0; ++ uint8 *ptr = (uint8 *)val; ++ ++ /* validate value length and buffer address */ ++ ASSERT(len == 1 || len == 6 || len == 8 || ++ ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3))); ++ ++ srab_request_grant(robo); ++ ++ /* We don't need this variable */ ++ if (robo->page != page) ++ robo->page = page; ++ ++ /* Assemble read command */ ++ srab_request_grant(robo); ++ ++ val32 = ((page << CFG_F_sra_page_R) ++ | (reg << CFG_F_sra_offset_R) ++ | CFG_F_sra_gordyn_MASK); ++ W_REG(si_osh(robo->sih), &robo->srabregs->cmdstat, val32); ++ ++ /* is operation finished? */ ++ for (i = SRAB_MAX_RETRY; i > 0; i --) { ++ val32 = R_REG(si_osh(robo->sih), &robo->srabregs->cmdstat); ++ if ((val32 & CFG_F_sra_gordyn_MASK) == 0) ++ break; ++ } ++ ++ /* timed out */ ++ if (!i) { ++ ET_ERROR(("srab_read: timeout")); ++ srab_interface_reset(robo); ++ ret = -1; ++ goto err; ++ } ++ ++ /* Didn't time out, read and return the value */ ++ val_h = R_REG(si_osh(robo->sih), &robo->srabregs->rd_h); ++ val_l = R_REG(si_osh(robo->sih), &robo->srabregs->rd_l); ++ ++ switch (len) { ++ case 8: ++ ptr[7] = (val_h >> 24); ++ ptr[6] = ((val_h >> 16) & 0xff); ++ /* FALLTHRU */ ++ ++ case 6: ++ ptr[5] = ((val_h >> 8) & 0xff); ++ ptr[4] = (val_h & 0xff); ++ ptr[3] = (val_l >> 24); ++ ptr[2] = ((val_l >> 16) & 0xff); ++ ptr[1] = ((val_l >> 8) & 0xff); ++ ptr[0] = (val_l & 0xff); ++ break; ++ ++ case 4: ++ *(uint32 *)val = val_l; ++ break; ++ ++ case 2: ++ *(uint16 *)val = (uint16)(val_l & 0xffff); ++ break; ++ ++ case 1: ++ *(uint8 *)val = (uint8)(val_l & 0xff); ++ break; ++ } ++ ++ ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, ++ VARG(val, len), len)); ++ ++err: ++ srab_release_grant(robo); ++ ++ return ret; ++} ++ ++/* SRAB interface functions */ ++static dev_ops_t srab = { ++ NULL, ++ NULL, ++ srab_wreg, ++ srab_rreg, ++ "SRAB" ++}; ++ ++#if defined(CONFIG_MACH_NSP) ++void ++srab_sgmii_set_blk(robo_info_t *robo, uint page, uint blk) ++{ ++ uint16 blkaddr; ++ uint16 destblk = (uint16)blk; ++ ++ /* printf("%s page(0x%x) blk(0x%x)\n", __FUNCTION__, page, blk); */ ++ /* check if need to update blk addr */ ++ robo->ops->read_reg(robo, page, REG_SGMII_BLK_ADDR, &blkaddr, sizeof(blkaddr)); ++ if (blkaddr!=destblk) { ++ /* write block address */ ++ robo->ops->write_reg(robo, page, REG_SGMII_BLK_ADDR, &destblk, sizeof(destblk)); ++ } ++} ++ ++int ++srab_sgmii_rreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val) ++{ ++ uint blk = reg&0xfff0; ++ uint8 off = reg&0x000f; ++ uint16 data; ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* spi offset is only even (multiple of 2) */ ++ off = off*2; ++ ++ /* check block addr */ ++ srab_sgmii_set_blk(robo, page, blk); ++ ++ /* read offset register */ ++ robo->ops->read_reg(robo, page, off, &data, sizeof(data)); ++ //printf("%s page(0x%x) blk(0x%x) offset(0x%x) value(0x%x)\n", __FUNCTION__, page, blk, off, data); ++ *val = data; ++ ++ return 0; ++} ++ ++int ++srab_sgmii_wreg(robo_info_t *robo, uint8 page, uint16 reg, uint16 *val) ++{ ++ uint blk = reg&0xfff0; ++ uint8 off = reg&0x000f; ++ uint16 data=*val; ++ ++ if (reg&0x8000) ++ off|=0x10; ++ ++ /* spi offset is only even (multiple of 2) */ ++ off = off*2; ++ ++ /* check block addr */ ++ srab_sgmii_set_blk(robo, page, blk); ++ ++ /* write offset register */ ++ robo->ops->write_reg(robo, page, off, &data, sizeof(data)); ++ //printf("%s page(0x%x) blk(0x%x) offset(0x%x) value(0x%x)\n", __FUNCTION__, page, blk, off, data); ++ ++ return 0; ++} ++#endif /* defined(CONFIG_MACH_NSP) */ ++ ++/* High level switch configuration functions. */ ++ ++/* Get access to the RoboSwitch */ ++robo_info_t * ++bcm_robo_attach(si_t *sih, void *h, char *vars, miird_f miird, miiwr_f miiwr) ++{ ++ robo_info_t *robo; ++ uint32 reset, idx; ++#ifndef _CFE_ ++// const char *et1port, *et1phyaddr; ++ int mdcport = 0, phyaddr = 0; ++#endif /* _CFE_ */ ++ int lan_portenable = 0; ++ ++ /* Allocate and init private state */ ++ if (!(robo = MALLOC(si_osh(sih), sizeof(robo_info_t)))) { ++ ET_ERROR(("robo_attach: out of memory, malloced %d bytes", ++ MALLOCED(si_osh(sih)))); ++ return NULL; ++ } ++ bzero(robo, sizeof(robo_info_t)); ++ ++ robo->h = h; ++ robo->sih = sih; ++ robo->vars = vars; ++ robo->miird = miird; ++ robo->miiwr = miiwr; ++ robo->page = -1; ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ robo->miird = NULL; ++ robo->miiwr = NULL; ++ robo->srabregs = (srabregs_t *)REG_MAP(SI_NS_CHIPCB_SRAB, SI_CORE_SIZE); ++ } ++ ++ /* Enable center tap voltage for LAN ports using gpio23. Usefull in case when ++ * romboot CFE loads linux over WAN port and Linux enables LAN ports later ++ */ ++ if ((lan_portenable = getgpiopin(robo->vars, "lanports_enable", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ lan_portenable = 1 << lan_portenable; ++ si_gpioouten(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); ++ si_gpioout(sih, lan_portenable, lan_portenable, GPIO_DRV_PRIORITY); ++ bcm_mdelay(5); ++ } ++ ++ /* Trigger external reset by nvram variable existance */ ++ if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) != ++ GPIO_PIN_NOTDEFINED) { ++ /* ++ * Reset sequence: RESET low(50ms)->high(20ms) ++ * ++ * We have to perform a full sequence for we don't know how long ++ * it has been from power on till now. ++ */ ++ ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset)); ++ reset = 1 << reset; ++ ++ /* Keep RESET low for 50 ms */ ++ si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY); ++ si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY); ++ bcm_mdelay(50); ++ ++ /* Keep RESET high for at least 20 ms */ ++ si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY); ++ bcm_mdelay(20); ++ } else { ++ /* In case we need it */ ++ idx = si_coreidx(sih); ++ ++ if (si_setcore(sih, ROBO_CORE_ID, 0)) { ++ /* If we have an internal robo core, reset it using si_core_reset */ ++ ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__)); ++ si_core_reset(sih, 0, 0); ++ robo->corerev = si_corerev(sih); ++ } ++ else if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ srab_interface_reset(robo); ++ srab_rreg(robo, PAGE_MMR, REG_VERSION_ID, &robo->corerev, 1); ++ } ++ else { ++ ET_ERROR(("%s: unknown switch\n", __FUNCTION__)); ++ } ++ si_setcoreidx(sih, idx); ++ ET_MSG(("%s: Internal robo rev %d\n", __FUNCTION__, robo->corerev)); ++ } ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ int rc; ++ ++ rc = srab_rreg(robo, PAGE_MMR, REG_DEVICE_ID, &robo->devid32, sizeof(uint32)); ++ ++ ET_MSG(("%s: devid read %ssuccesfully via srab: 0x%x\n", ++ __FUNCTION__, rc ? "un" : "", robo->devid32)); ++ ++ robo->ops = &srab; ++ if ((rc != 0) || (robo->devid32 == 0)) { ++ ET_ERROR(("%s: error reading devid\n", __FUNCTION__)); ++ MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); ++ return NULL; ++ } ++ ET_MSG(("%s: devid32: 0x%x\n", __FUNCTION__, robo->devid32)); ++ printf("%s: devid32: 0x%x\n", __FUNCTION__, robo->devid32); ++ } ++ ++#ifndef _CFE_ ++ if (!robo->ops) { ++ ET_ERROR(("%s: unknown switch", __FUNCTION__)); ++ goto error; ++ } ++#endif /* _CFE_ */ ++ ++ /* sanity check */ ++ ASSERT(robo->ops); ++ ASSERT(robo->ops->write_reg); ++ ASSERT(robo->ops->read_reg); ++ ASSERT(ROBO_IS_BCM5301X(robo->devid32)); ++ ++#ifndef _CFE_ ++ /* nvram variable switch_mode controls the power save mode on the switch ++ * set the default value in the beginning ++ */ ++ robo->pwrsave_mode_manual = getintvar(robo->vars, "switch_mode_manual"); ++ robo->pwrsave_mode_auto = getintvar(robo->vars, "switch_mode_auto"); ++ ++ /* Determining what all phys need to be included in ++ * power save operation ++ */ ++ //et1port = getvar(vars, "et1mdcport"); ++ //if (et1port) ++ // mdcport = bcm_atoi(et1port); ++ ++ //et1phyaddr = getvar(vars, "et1phyaddr"); ++ //if (et1phyaddr) ++ // phyaddr = bcm_atoi(et1phyaddr); ++ ++ if ((mdcport == 0) && (phyaddr == 4)) ++ /* For 5325F switch we need to do only phys 0-3 */ ++ robo->pwrsave_phys = 0xf; ++ else ++ /* By default all 5 phys are put into power save if there is no link */ ++ robo->pwrsave_phys = 0x1f; ++#endif /* _CFE_ */ ++ ++ return robo; ++ ++#ifndef _CFE_ ++error: ++ bcm_robo_detach(robo); ++ return NULL; ++#endif /* _CFE_ */ ++} ++ ++/* Release access to the RoboSwitch */ ++void ++bcm_robo_detach(robo_info_t *robo) ++{ ++ if (robo->srabregs) ++ REG_UNMAP(robo->srabregs); ++ ++ MFREE(si_osh(robo->sih), robo, sizeof(robo_info_t)); ++} ++ ++/* Enable the device and set it to a known good state */ ++int ++bcm_robo_enable_device(robo_info_t *robo) ++{ ++ int ret = 0; ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return ret; ++} ++ ++/* Port flags */ ++#define FLAG_TAGGED 't' /* output tagged (external ports only) */ ++#define FLAG_UNTAG 'u' /* input & output untagged (CPU port only, for OS (linux, ...) */ ++#define FLAG_LAN '*' /* input & output untagged (CPU port only, for CFE */ ++ ++/* port descriptor */ ++typedef struct { ++ uint32 untag; /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */ ++ uint32 member; /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */ ++ uint8 ptagr; /* port tag register address (Page 0x34 Address 0x10-0x1F) */ ++ uint8 cpu; /* is this cpu port? */ ++} pdesc_t; ++ ++pdesc_t pdesc97[] = { ++ /* 5395/5397/5398/53115S is 0 ~ 7. port 8 is IMP port. */ ++ /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0}, ++ /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0}, ++ /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0}, ++ /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0}, ++ /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0}, ++#ifdef GMAC3 ++ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0}, ++ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0}, ++ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0}, ++#else /* !GMAC3 */ ++ /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 1}, ++ /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 1}, ++ /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 1}, ++#endif /* !GMAC3 */ ++ /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1}, ++}; ++ ++/* Configure the VLANs */ ++int ++bcm_robo_config_vlan(robo_info_t *robo, uint8 *mac_addr) ++{ ++ uint8 val8; ++ uint16 val16; ++ uint32 val32; ++ pdesc_t *pdesc; ++ int pdescsz; ++ uint16 vid; ++ uint8 arl_entry[8] = { 0 }; ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* setup global vlan configuration */ ++ /* VLAN Control 0 Register (Page 0x34, Address 0) */ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ val8 |= ((1 << 7) | /* enable 802.1Q VLAN */ ++ (3 << 5)); /* individual VLAN learning mode */ ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ /* VLAN Control 1 Register (Page 0x34, Address 1) */ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ val8 |= ((1 << 2) | /* enable RSV multicast V Fwdmap */ ++ (1 << 3)); /* enable RSV multicast V Untagmap */ ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ ++ arl_entry[0] = mac_addr[5]; ++ arl_entry[1] = mac_addr[4]; ++ arl_entry[2] = mac_addr[3]; ++ arl_entry[3] = mac_addr[2]; ++ arl_entry[4] = mac_addr[1]; ++ arl_entry[5] = mac_addr[0]; ++ ++ /* Initialize the MAC Addr Index Register */ ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, ++ arl_entry, ETHER_ADDR_LEN); ++ ++ pdesc = pdesc97; ++ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); ++ ++ /* check if p5 is not CPU port */ ++ if (!robo_is_port5_cpu()) { ++ pdesc[5].cpu = 0; ++ } ++ ++ /* setup each vlan. max. 16 vlans. */ ++ /* force vlan id to be equal to vlan number */ ++ for (vid = 0; vid < VLAN_NUMVLANS; vid ++) { ++ char vlanports[] = "vlanXXXXports"; ++ char port[] = "XXXX", *next; ++ const char *ports, *cur; ++ uint32 untag = 0; ++ uint32 member = 0; ++ int pid, len; ++ int cpuport=0; ++ ++ /* no members if VLAN id is out of limitation */ ++ if (vid > VLAN_MAXVID) ++ goto vlan_setup; ++ ++ /* get vlan member ports from nvram */ ++ sprintf(vlanports, "vlan%dports", vid); ++ ports = getvar(robo->vars, vlanports); ++ ++ ET_MSG(("%s: getvar(%s) port %s \n", ++ __FUNCTION__, vlanports, ports)); ++ /* vid == 0 is invalid?? */ ++ if (vid == 0) { ++ if (ports) ++ ET_ERROR(("VID 0 is set in nvram, Ignoring\n")); ++ continue; ++ } ++ ++ /* disable this vlan if not defined */ ++ if (!ports) ++ goto vlan_setup; ++ ++ /* ++ * setup each port in the vlan. cpu port needs special handing ++ * (with or without output tagging) to support linux/pmon/cfe. ++ */ ++ for (cur = ports; cur; cur = next) { ++ /* tokenize the port list */ ++ while (*cur == ' ') ++ cur ++; ++ next = bcmstrstr(cur, " "); ++ len = next ? next - cur : strlen(cur); ++ if (!len) ++ break; ++ if (len > sizeof(port) - 1) ++ len = sizeof(port) - 1; ++ strncpy(port, cur, len); ++ port[len] = 0; ++ ++ /* make sure port # is within the range */ ++ pid = bcm_atoi(port); ++ if (pid >= pdescsz) { ++ ET_ERROR(("robo_config_vlan: port %d in vlan%dports is out " ++ "of range[0-%d]\n", pid, vid, pdescsz)); ++ continue; ++ } ++ if (pid == 6) { ++ ET_ERROR(("robo_config_vlan: port %d in vlan%dports is not valid\n", pid, vid)); ++ continue; ++ } ++ ++ /* build VLAN registers values */ ++#ifndef _CFE_ ++ if ((!pdesc[pid].cpu && !strchr(port, FLAG_TAGGED)) || ++ (pdesc[pid].cpu && strchr(port, FLAG_UNTAG))) ++#endif ++ untag |= pdesc[pid].untag; ++ ++ member |= pdesc[pid].member; ++ ++ /* set port tag - applies to untagged ingress frames */ ++ /* Default Port Tag Register (Page 0x34, Address 0x10-0x1D) */ ++#ifdef _CFE_ ++#define FL FLAG_LAN ++#else ++#define FL FLAG_UNTAG ++#endif /* _CFE_ */ ++ if (!pdesc[pid].cpu || strchr(port, FL)) { ++ val16 = ((0 << 13) | /* priority - always 0 */ ++ vid); /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VLAN, pdesc[pid].ptagr, ++ &val16, sizeof(val16)); ++ } ++ if (pdesc[pid].cpu) ++ cpuport=pid; ++ } ++ ++ /* Add static ARL entries */ ++ /* Set the VLAN Id in VLAN ID Index Register */ ++ val8 = vid; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, ++ &val8, sizeof(val8)); ++ ++ /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0 ++ * Register. ++ */ ++ arl_entry[6] = vid; ++ arl_entry[7] = 0x0; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, ++ arl_entry, sizeof(arl_entry)); ++ ++ /* Set the Static bit , Valid bit and Port ID fields in ++ * ARL Table Data Entry 0 Register ++ */ ++ //val16 = 0xc100; //0xc020; ++ val32 = 0x08000 + (1<ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, ++ &val32, sizeof(val32)); ++ ++ /* Clear the ARL_R/W bit and set the START/DONE bit in ++ * the ARL Read/Write Control Register. ++ */ ++ val8 = 0x80; ++ robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, ++ &val8, sizeof(val8)); ++ /* Wait for write to complete */ ++ SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, ++ &val8, sizeof(val8)), ((val8 & 0x80) != 0)), ++ 100 /* usec */); ++ ++vlan_setup: ++ /* setup VLAN ID and VLAN memberships */ ++ ++ val32 = (untag | /* untag enable */ ++ member); /* vlan members */ ++ { ++ uint8 vtble, vtbli, vtbla; ++ ++ vtble = REG_VTBL_ENTRY_5395; ++ vtbli = REG_VTBL_INDX_5395; ++ vtbla = REG_VTBL_ACCESS_5395; ++ ++ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32, ++ sizeof(val32)); ++ /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */ ++ val16 = vid; /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, ++ sizeof(val16)); ++ ++ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ ++ val8 = ((1 << 7) | /* start command */ ++ 0); /* write */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, ++ sizeof(val8)); ++ } ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return 0; ++} ++ ++/* Enable switching/forwarding */ ++int ++bcm_robo_enable_switch(robo_info_t *robo) ++{ ++ int i, max_port_ind, ret = 0; ++ uint8 val8; ++ uint16 val16; ++ bool bcm_tag_on=false; ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ char *var; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ uint32_t val32; ++#if defined(CONFIG_IPROC_OTP) ++ void *oh; ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ uint32_t skuid=0; ++ ++#if (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) ++ /* check if brcm tag is turned off */ ++ bcm_tag_on=true; ++ var = getvar(NULL, "brcmtag"); ++ if (var) { ++ int tag = bcm_strtoul(var, NULL, 0); ++ if (tag==0) { ++ ET_ERROR(("BRCM TAG disabled\n")); ++ /* if brcm tag == 0 tag disabled */ ++ bcm_tag_on = false; ++ } ++ } ++#elif defined(CONFIG_MACH_NSP) ++ bcm_tag_on=true; ++#endif /* (defined(CONFIG_IPROC_FA) || defined(CONFIG_IPROC_FA2)) */ ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Switch Mode register (Page 0, Address 0x0B) */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ ++ /* Bit 1 enables switching/forwarding */ ++ if (!(val8 & (1 << 1))) { ++ /* Set unmanaged mode */ ++ val8 &= (~(1 << 0)); ++ ++ /* Enable forwarding */ ++ val8 |= (1 << 1); ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ ++ /* Read back */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ if (!(val8 & (1 << 1))) { ++ ET_ERROR(("robo_enable_switch: enabling forwarding failed\n")); ++ ret = -1; ++ } ++ ++ /* No spanning tree for unmanaged mode */ ++ val8 = 0; ++ if (ROBO_IS_BCM5301X(robo->devid32)) ++ max_port_ind = REG_CTRL_PORT7; ++ else ++ max_port_ind = REG_CTRL_PORT4; ++ ++ for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) { ++ if (ROBO_IS_BCM5301X(robo->devid32) && i == REG_CTRL_PORT6) ++ continue; ++ robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8)); ++ } ++ ++ /* No spanning tree on IMP port too */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ } ++ else { ++ /* Set managed mode */ ++ val8 |= 1; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ } ++ ++ if (ROBO_IS_BCM5301X(robo->devid32)) { ++ /* ++ * Port N GMII Port States Override Register (Page 0x00 , address Offset: 0x0e , 0x58-0x5d and 0x5f ) ++ * SPEED/ DUPLEX_MODE/ LINK_STS ++ */ ++ ++ /* check if p5 is CPU port */ ++ if (robo_is_port5_cpu()) { ++ /* Over ride GMAC0 Port5 status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT5_GMIIPO, &val8, sizeof(val8)); ++ } ++ ++ /* Over ride GMAC1 Port7 status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PORT7_GMIIPO, &val8, sizeof(val8)); ++ ++ /* Over ride GMAC2 IMP(Port8) status to make it link by default */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); ++ /* 2G_ENABLED: ++ * Page :0x00 ++ * ( Offset: 0xe ) IMP Port States Override Register ++ * [6]: GMII SPEED UP 2G ++ */ ++ val8 |= 0xf1; /* Make Link pass and override it. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) config BRCM tag */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); ++ if (bcm_tag_on) ++ val8 |= 0x01; ++ else ++ val8 &= 0xfe; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_BRCM_HDR, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) Enable receive all packets */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ val8 |= 0x1c; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_IMP, &val8, sizeof(val8)); ++ ++ /* GMAC2 IMP(Port8) IMP port Enable */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ val8 |= 0x80; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ } ++ ++ if (bcm_tag_on) { ++ /* GMAC2 IMP(Port8) enable ignore crc check */ ++ val8 = 0; ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); ++ val8 |= 0x01; ++ robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8)); ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ /* make sure external ports are not in protected mode (Page 0, Address 0x24) */ ++ val16 = 0; ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PPORT, &val16, sizeof(val16)); ++ ++ ++#if defined(CONFIG_IPROC_OTP) ++ /* check if need to turn off unused ports */ ++ /* Check for Vega chip - get OTP skuid */ ++ bcm5301x_otp_init_fptr = symbol_get(bcm5301x_otp_init); ++ bcm5301x_otp_read_dword_fptr = symbol_get(bcm5301x_otp_read_dword); ++ bcm5301x_otp_exit_fptr = symbol_get(bcm5301x_otp_exit); ++ ++ ++ if ( (bcm5301x_otp_init_fptr != NULL) ++ && ( bcm5301x_otp_read_dword_fptr != NULL) ++ && (bcm5301x_otp_exit_fptr != NULL)) { ++ ++ oh = (*bcm5301x_otp_init_fptr)(); ++ (*bcm5301x_otp_read_dword_fptr)(oh, 0x0f, &skuid); ++ (*bcm5301x_otp_exit_fptr)(); ++ } ++ printf("%s OTP: offset 0x0f = 0x%x\n", __FUNCTION__, skuid); ++#else /* defined(CONFIG_IPROC_OTP) */ ++ printf("%s IPROC OTP is not configured, can not determine skuid\n", __FUNCTION__); ++#endif /* defined(CONFIG_IPROC_OTP) */ ++ ++ if (IS_BCM5301X_CHIP_ID(sih->chip)) { ++ printf("%s Northstar Family chip\n", __FUNCTION__); ++ if ( (robo->devid32==DEVID53010 && skuid==OTP_SKU_ID_53014) ++ || (robo->devid32==DEVID53011 && skuid==OTP_SKU_ID_53015) ++ || (robo->devid32==DEVID53012 && skuid==OTP_SKU_ID_53016) ) { ++ /* check for VEGA */ ++ printf("%s Vega chip\n", __FUNCTION__); ++ /* only have ports 0-1, power down phy of ports 2-4 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x1c; /* power down ports 2-4. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ } ++ else if ( robo->devid32 == DEVID53025 ) { ++ /* for nsp, skuid is actually gphy_ext_pwrdown[4-0] bits, ++ mask off other bits */ ++ skuid &= 0x1f; ++ printf("%s Checking powered down port (0x%x)\n", __FUNCTION__, skuid); ++ if (skuid == 0x1c) { ++ printf("%s Powering down ports 2-4\n", __FUNCTION__); ++ /* only have ports 0-1, power down phy of ports 2-4 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x1c; /* power down ports 2-4. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ } else if ((skuid == 0x07) || (skuid == 0x06)) { ++ printf("%s Powering down ports 0-2\n", __FUNCTION__); ++ /* only have ports 3-4, power down phy of ports 1-2 */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ val32 |= 0x6; /* power down ports 1-2. */ ++ robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_PHY_PWR, &val32, sizeof(val32)); ++ /* power down port 0 */ ++ val32 = 0xfff; ++ robo->ops->write_reg(robo, PAGE_GPHYP0, PAGE_GPHYP0_DSP_COEF_ADDR, &val32, sizeof(val32)); ++ val32 = 0x7fff; ++ robo->ops->write_reg(robo, PAGE_GPHYP0, PAGE_GPHYP0_DSP_COEF, &val32, sizeof(val32)); ++ } ++ } ++ } ++ ++#if defined(CONFIG_MACH_NSP) ++ if ( robo_is_port_cfg(PORTCFG_5, PORTCFG_SGMII) ++ || robo_is_port_cfg(PORTCFG_4, PORTCFG_SGMII) ) { ++ /* either port5 or port4 SGMII enabled */ ++ /* enable serdes */ ++ robo_serdes_reset_core(robo, PAGE_P5_SGMII); ++ if (robo_is_port_cfg(PORTCFG_5, PORTCFG_SGMII)) { ++ /* enable port5 sgmii */ ++ robo_serdes_init(robo, PAGE_P5_SGMII); ++ } ++ if (robo_is_port_cfg(PORTCFG_4, PORTCFG_SGMII)) { ++ /* enable port4 sgmii */ ++ robo_serdes_init(robo, PAGE_P4_SGMII); ++ } ++ /* start serdes pll */ ++ robo_serdes_start_pll(robo, PAGE_P5_SGMII); ++ } ++#endif /* defined(CONFIG_MACH_NSP) */ ++ ++ return ret; ++} ++ ++void ++robo_reset_mib(robo_info_t *robo) ++{ ++ uint8 val8; ++ ++ robo->ops->read_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ /* set clear mib bit */ ++ val8 |= 0x01; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++ /* clear clear mib bit */ ++ val8 &= 0xfe; ++ robo->ops->write_reg(robo, PAGE_MMR, REG_MGMT_CFG, &val8, sizeof(val8)); ++} ++ ++void ++robo_dump_mib(robo_info_t *robo) ++{ ++ uint32 tx32, rx32; ++ int port; ++ ++ for (port=0x20; port<=0x28; port++) { ++ if (port==0x26) ++ continue; ++ robo->ops->read_reg(robo, port, 0x00, &tx32, sizeof(tx32)); ++ robo->ops->read_reg(robo, port, 0x50, &rx32, sizeof(rx32)); ++ printf("port%d: TX Octets: 0x%x; RX Octets: 0x%x\n", port-0x20, tx32, rx32); ++ } ++} ++ ++void ++robo_bprintf_mib(robo_info_t *robo, struct bcmstrbuf *b) ++{ ++ uint32 tx32, txdrp32, txbcst32, txmcst32, txcol32, ucst32, txpause32; ++ uint32 rx32, rxusz32, rxosz32, rxale32, rxfcs32, rxdrp32, rxsachg32, rxfrag32, rxsym32, irec32, orec32, rxdis32; ++ int port; ++ ++ for (port=0x20; port<=0x28; port++) { ++ if (port==0x26) ++ continue; ++ robo->ops->read_reg(robo, port, 0x00, &tx32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x08, &txdrp32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x10, &txbcst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x14, &txmcst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x18, &ucst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x1c, &txcol32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x38, &txpause32, sizeof(uint32)); ++ bcm_bprintf(b, "port%d TX: Octs(%x); Drp(%x) Bcst(%x) Mcst(%x) Ucst(%x) Col(%x) Pause(%x)\n", ++ port-0x20, tx32, txdrp32, txbcst32, txmcst32, ucst32, txcol32, txpause32); ++ robo->ops->read_reg(robo, port, 0x50, &rx32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x58, &rxusz32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x78, &rxosz32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x80, &rxale32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x84, &rxfcs32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x90, &rxdrp32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0x94, &ucst32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xa0, &rxsachg32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xa4, &rxfrag32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xac, &rxsym32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xb0, &irec32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xb4, &orec32, sizeof(uint32)); ++ robo->ops->read_reg(robo, port, 0xc0, &rxdis32, sizeof(uint32)); ++ bcm_bprintf(b, "port%d RX: Octs(%x); USz(%x) OSz(%x) AlgnEr(%x) FcsEr(%x) Drp(%x) Ucst(%x); SacCh(%x); Frag(%x) SymEr(%x) IRngEr(%x) ORngEr(%x) Dis(%x)\n", ++ port-0x20, rx32, rxusz32, rxosz32, rxale32, rxfcs32, rxdrp32, ++ ucst32, rxsachg32, rxfrag32, rxsym32, irec32, orec32, rxdis32); ++ } ++ robo_reset_mib(robo); ++} ++ ++ ++void ++robo_dump_regs(robo_info_t *robo, struct bcmstrbuf *b) ++{ ++ uint8 val8; ++ uint16 val16; ++ uint32 val32; ++ pdesc_t *pdesc; ++ int pdescsz; ++ int i; ++ ++ bcm_bprintf(b, "%s:\n", robo->ops->desc); ++ if (robo->miird == NULL && !strcmp(robo->ops->desc, "SPI (GPIO)")) ++ bcm_bprintf(b, "SPI gpio pins: ss %d sck %d mosi %d miso %d\n", ++ robo->ss, robo->sck, robo->mosi, robo->miso); ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ /* Dump registers interested */ ++ robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x00,0x0B)Switch mode regsiter: 0x%02x\n", val8); ++ ++ pdesc = pdesc97; ++ pdescsz = sizeof(pdesc97) / sizeof(pdesc_t); ++ ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x34,0x00)VLAN control 0 register: 0x%02x\n", val8); ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8)); ++ bcm_bprintf(b, "(0x34,0x01)VLAN control 1 register: 0x%02x\n", val8); ++ robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8)); ++ { ++ uint8 vtble, vtbli, vtbla; ++ ++ vtble = REG_VTBL_ENTRY_5395; ++ vtbli = REG_VTBL_INDX_5395; ++ vtbla = REG_VTBL_ACCESS_5395; ++ ++ for (i = 0; i <= VLAN_MAXVID; i++) { ++ /* VLAN Table Address Index Register (Page 0x05, Address 0x61-0x62/0x81-0x82) */ ++ val16 = i; /* vlan id */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16, ++ sizeof(val16)); ++ /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */ ++ val8 = ((1 << 7) | /* start command */ ++ 1); /* read */ ++ robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8, ++ sizeof(val8)); ++ /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */ ++ robo->ops->read_reg(robo, PAGE_VTBL, vtble, &val32, ++ sizeof(val32)); ++ bcm_bprintf(b, "VLAN %d untag bits: 0x%02x member bits: 0x%02x\n", ++ i, (val32 & 0x3fe00) >> 9, (val32 & 0x1ff)); ++ } ++ } ++ for (i = 0; i < pdescsz; i++) { ++ robo->ops->read_reg(robo, PAGE_VLAN, pdesc[i].ptagr, &val16, sizeof(val16)); ++ bcm_bprintf(b, "(0x34,0x%02x)Port %d Tag: 0x%04x\n", pdesc[i].ptagr, i, val16); ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++} ++ ++#ifndef _CFE_ ++/* ++ * Update the power save configuration for ports that changed link status. ++ */ ++void ++robo_power_save_mode_update(robo_info_t *robo) ++{ ++ uint phy; ++ ++ for (phy = 0; phy < MAX_NO_PHYS; phy++) { ++ if (robo->pwrsave_mode_auto & (1 << phy)) { ++ ET_MSG(("%s: set port %d to auto mode\n", ++ __FUNCTION__, phy)); ++ robo_power_save_mode(robo, ROBO_PWRSAVE_AUTO, phy); ++ } ++ } ++ ++ return; ++} ++ ++static int32 ++robo_power_save_mode_clear_auto(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++} ++ ++static int32 ++robo_power_save_mode_clear_manual(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++ ++} ++ ++/* ++ * Function which periodically checks the power save mode on the switch ++ */ ++int32 ++robo_power_save_toggle(robo_info_t *robo, int32 normal) ++{ ++ int32 phy; ++ uint16 link_status; ++ ++ ++ /* read the link status of all ports */ ++ robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, ++ &link_status, sizeof(uint16)); ++ link_status &= 0x1f; ++ ++ /* Take the phys out of the manual mode first so that link status ++ * can be checked. Once out of that mode check the link status ++ * and if any of the link is up do not put that phy into ++ * manual power save mode ++ */ ++ for (phy = 0; phy < MAX_NO_PHYS; phy++) { ++ /* When auto+manual modes are enabled we toggle between ++ * manual and auto modes. When only manual mode is enabled ++ * we toggle between manual and normal modes. When only ++ * auto mode is enabled there is no need to do anything ++ * here since auto mode is one time config. ++ */ ++ if ((robo->pwrsave_phys & (1 << phy)) && ++ (robo->pwrsave_mode_manual & (1 << phy))) { ++ if (!normal) { ++ /* Take the port out of the manual mode */ ++ robo_power_save_mode_clear_manual(robo, phy); ++ } else { ++ /* If the link is down put it back to manual else ++ * remain in the current state ++ */ ++ if (!(link_status & (1 << phy))) { ++ ET_MSG(("%s: link down, set port %d to man mode\n", ++ __FUNCTION__, phy)); ++ robo_power_save_mode(robo, ROBO_PWRSAVE_MANUAL, phy); ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Switch the ports to normal mode. ++ */ ++static int32 ++robo_power_save_mode_normal(robo_info_t *robo, int32 phy) ++{ ++ int32 error = 0; ++ ++ /* If the phy in the power save mode come out of it */ ++ switch (robo->pwrsave_mode_phys[phy]) { ++ case ROBO_PWRSAVE_AUTO_MANUAL: ++ case ROBO_PWRSAVE_AUTO: ++ error = robo_power_save_mode_clear_auto(robo, phy); ++ if ((error == -1) || ++ (robo->pwrsave_mode_phys[phy] == ROBO_PWRSAVE_AUTO)) ++ break; ++ ++ case ROBO_PWRSAVE_MANUAL: ++ error = robo_power_save_mode_clear_manual(robo, phy); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return error; ++} ++ ++/* ++ * Switch all the inactive ports to auto power down mode. ++ */ ++static int32 ++robo_power_save_mode_auto(robo_info_t *robo, int32 phy) ++{ ++ return -1; ++} ++ ++/* ++ * Switch all the inactive ports to manual power down mode. ++ */ ++static int32 ++robo_power_save_mode_manual(robo_info_t *robo, int32 phy) ++{ ++ uint16 val16; ++ ++ /* For both 5325 and 53115 the link status register is the same */ ++ robo->ops->read_reg(robo, PAGE_STATUS, REG_STATUS_LINK, ++ &val16, sizeof(val16)); ++ if (val16 & (0x1 << phy)) ++ return 0; ++ ++ return -1; ++} ++ ++/* ++ * Set power save modes on the robo switch ++ */ ++int32 ++robo_power_save_mode(robo_info_t *robo, int32 mode, int32 phy) ++{ ++ int32 error = -1; ++ ++ if (phy > MAX_NO_PHYS) { ++ ET_ERROR(("Passed parameter phy is out of range\n")); ++ return -1; ++ } ++ ++ /* Enable management interface access */ ++ if (robo->ops->enable_mgmtif) ++ robo->ops->enable_mgmtif(robo); ++ ++ switch (mode) { ++ case ROBO_PWRSAVE_NORMAL: ++ /* If the phy in the power save mode come out of it */ ++ error = robo_power_save_mode_normal(robo, phy); ++ break; ++ ++ case ROBO_PWRSAVE_AUTO_MANUAL: ++ /* If the switch supports auto and manual power down ++ * enable both of them ++ */ ++ case ROBO_PWRSAVE_AUTO: ++ error = robo_power_save_mode_auto(robo, phy); ++ if ((error == -1) || (mode == ROBO_PWRSAVE_AUTO)) ++ break; ++ ++ case ROBO_PWRSAVE_MANUAL: ++ error = robo_power_save_mode_manual(robo, phy); ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Disable management interface access */ ++ if (robo->ops->disable_mgmtif) ++ robo->ops->disable_mgmtif(robo); ++ ++ return error; ++} ++ ++/* ++ * Get the current power save mode of the switch ports. ++ */ ++int32 ++robo_power_save_mode_get(robo_info_t *robo, int32 phy) ++{ ++ ASSERT(robo); ++ ++ if (phy >= MAX_NO_PHYS) ++ return -1; ++ ++ return robo->pwrsave_mode_phys[phy]; ++} ++ ++/* ++ * Configure the power save mode for the switch ports. ++ */ ++int32 ++robo_power_save_mode_set(robo_info_t *robo, int32 mode, int32 phy) ++{ ++ int32 error; ++ ++ ASSERT(robo); ++ ++ if (phy >= MAX_NO_PHYS) ++ return -1; ++ ++ error = robo_power_save_mode(robo, mode, phy); ++ ++ if (error) ++ return error; ++ ++ if (mode == ROBO_PWRSAVE_NORMAL) { ++ robo->pwrsave_mode_manual &= ~(1 << phy); ++ robo->pwrsave_mode_auto &= ~(1 << phy); ++ } else if (mode == ROBO_PWRSAVE_AUTO) { ++ robo->pwrsave_mode_auto |= (1 << phy); ++ robo->pwrsave_mode_manual &= ~(1 << phy); ++ robo_power_save_mode_clear_manual(robo, phy); ++ } else if (mode == ROBO_PWRSAVE_MANUAL) { ++ robo->pwrsave_mode_manual |= (1 << phy); ++ robo->pwrsave_mode_auto &= ~(1 << phy); ++ robo_power_save_mode_clear_auto(robo, phy); ++ } else { ++ robo->pwrsave_mode_auto |= (1 << phy); ++ robo->pwrsave_mode_manual |= (1 << phy); ++ } ++ ++ return 0; ++} ++#endif /* _CFE_ */ ++ ++void ++robo_watchdog(robo_info_t *robo) ++{ ++ return; ++} ++ ++int ++robo_write_reg(void *rih, unsigned char page, unsigned char reg, void *val, int len) ++{ ++ robo_info_t *robo = (robo_info_t*)rih; ++ return robo->ops->write_reg(robo, (uint8)page, (uint8)reg, val, len); ++} ++ ++ ++int ++robo_read_reg(void *rih, unsigned char page, unsigned char reg, void *val, int len) ++{ ++ robo_info_t *robo = (robo_info_t*)rih; ++ return robo->ops->read_reg(robo, (uint8)page, (uint8)reg, val, len); ++} ++ ++ ++int ++robo_is_port5_cpu(void) ++{ ++ char name[16]; ++ char *var; ++ ++ /* get port5 config */ ++ sprintf(name, PORTCFG, PORTCFG_5); ++ var = getvar(NULL, name); ++ ++ /* check if not CPU port */ ++ if (var == NULL) { ++ /* if no port 5 config then CPU port */ ++ return 1; ++ } ++ /* now check if valid CONFIGURATION */ ++ if (strcmp(var, PORTCFG_RGMII)==0) { ++ printf("%s port5 is configured as RGMII port\n", __FUNCTION__); ++ return 0; ++ } ++ if (strcmp(var, PORTCFG_SGMII)==0) { ++ printf("%s port5 is configured as SGMII port\n", __FUNCTION__); ++ return 0; ++ } ++ if (strcmp(var, PORTCFG_GPHY)==0) { ++ printf("%s port5 is configured as GPHY port\n", __FUNCTION__); ++ return 0; ++ } ++ ++ printf("%s port5 has UNKNOWN configuration: %s\n", __FUNCTION__, var); ++ /* must be CPU port */ ++ return 1; ++} ++ ++ ++int ++robo_is_port_cfg(int port, char *cfg) ++{ ++ char name[16]; ++ char *var; ++ ++ /* get port5 config */ ++ sprintf(name, PORTCFG, port); ++ var = getvar(NULL, name); ++ if (var == NULL) { ++ /* if no port config then normal port config */ ++ return 0; ++ } ++ ++ if (strcmp(var, cfg)==0) { ++ /* the port is the configuration we are looing for */ ++ return 1; ++ } ++ ++ /* not config we are looking for */ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c b/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c +new file mode 100755 +index 0000000..be26681 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmsrom.c +@@ -0,0 +1,5109 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Routines to access SPROM and to parse SROM/CIS variables. ++ * ++ * $Id: bcmsrom.c 323253 2012-03-23 17:21:10Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef BCMSPI ++#include ++#endif ++ ++#include ++#include ++ ++#if defined(BCMUSBDEV) ++#include ++#include ++#include ++#endif ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++#include ++#endif ++#include /* for sprom content groking */ ++ ++ ++#if defined(BCMDBG_ERR) || defined(WLTEST) ++#define BS_ERROR(args) printf args ++#else ++#define BS_ERROR(args) ++#endif ++ ++#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \ ++ (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \ ++ ((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \ ++ ((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET)) ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ ++#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ ++#endif ++ ++typedef struct varbuf { ++ char *base; /* pointer to buffer base */ ++ char *buf; /* pointer to current position */ ++ unsigned int size; /* current (residual) size in bytes */ ++} varbuf_t; ++extern char *_vars; ++extern uint _varsz; ++ ++#define SROM_CIS_SINGLE 1 ++ ++ ++static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *count); ++static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b); ++static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count); ++static int initvars_cis_pcmcia(si_t *sih, osl_t *osh, char **vars, uint *count); ++#if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) ++static int initvars_flash_si(si_t *sih, char **vars, uint *count); ++#endif ++#ifdef BCMSPI ++static int initvars_cis_spi(osl_t *osh, char **vars, uint *count); ++#endif /* BCMSPI */ ++static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd); ++static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data); ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data); ++#endif ++static int sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, ++ uint nwords, bool check_crc); ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz); ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, ++ uint16 data); ++ ++static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count); ++static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len); ++ ++#if defined(BCMUSBDEV) ++static int get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz, bool check_crc); ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++static int set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz); ++#endif ++#endif ++ ++#if defined(BCMUSBDEV) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++/* default to bcm94323 P200, other boards should have OTP programmed */ ++static char BCMATTACHDATA(defaultsromvars_4322usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:d3:04:73\0" ++ "sromrev=8\0" ++ "devid=0x432b\0" ++ "boardrev=0x1200\0" ++ "boardflags=0xa00\0" ++ "boardflags2=0x602\0" ++ "boardtype=0x04a8\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x0\0" ++ "pdetrange2g=0x0\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x2\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x0\0" ++ "pdetrange5g=0x0\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x2\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "pa2gw0a0=0xFEA8\0" ++ "pa2gw1a0=0x16CD\0" ++ "pa2gw2a0=0xFAA5\0" ++ "maxp5ga0=0x40\0" ++ "itt5ga0=0x3e\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x40\0" ++ "pa5gw0a0=0xFEB2\0" ++ "pa5gw1a0=0x1471\0" ++ "pa5gw2a0=0xFB1F\0" ++ "pa5glw0a0=0xFEA2\0" ++ "pa5glw1a0=0x149A\0" ++ "pa5glw2a0=0xFAFC\0" ++ "pa5ghw0a0=0xFEC6\0" ++ "pa5ghw1a0=0x13DD\0" ++ "pa5ghw2a0=0xFB48\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "pa2gw0a1=0xFEA3\0" ++ "pa2gw1a1=0x1687\0" ++ "pa2gw2a1=0xFAAA\0" ++ "maxp5ga1=0x40\0" ++ "itt5ga1=0x3e\0" ++ "maxp5gha1=0x3c\0" ++ "maxp5gla1=0x40\0" ++ "pa5gw0a1=0xFEBC\0" ++ "pa5gw1a1=0x14F9\0" ++ "pa5gw2a1=0xFB05\0" ++ "pa5glw0a1=0xFEBE\0" ++ "pa5glw1a1=0x1478\0" ++ "pa5glw2a1=0xFB1A\0" ++ "pa5ghw0a1=0xFEE1\0" ++ "pa5ghw1a1=0x14FD\0" ++ "pa5ghw2a1=0xFB38\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0x2\0" ++ "ledbh2=0x3\0" ++ "ledbh3=0xff\0" ++ "leddc=0xa0a0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43234usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:03:21:23\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x2\0" ++ "aa5g=0x2\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "txchain=0x2\0" ++ "rxchain=0x2\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4346\0" ++ "boardrev=0x1403\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x2000\0" ++ "boardtype=0x0521\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x4444\0" ++ "mcs2gpo5=0x4444\0" ++ "mcs2gpo6=0x4444\0" ++ "mcs2gpo7=0x4444\0" ++ "mcs5gpo4=0x2222\0" ++ "mcs5gpo5=0x2222\0" ++ "mcs5gpo6=0x2222\0" ++ "mcs5gpo7=0x2222\0" ++ "mcs5glpo4=0x2222\0" ++ "mcs5glpo5=0x2222\0" ++ "mcs5glpo6=0x2222\0" ++ "mcs5glpo7=0x2222\0" ++ "mcs5ghpo4=0x2222\0" ++ "mcs5ghpo5=0x2222\0" ++ "mcs5ghpo6=0x2222\0" ++ "mcs5ghpo7=0x2222\0" ++ "maxp2ga0=0x42\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xFF21\0" ++ "pa2gw1a0=0x13B7\0" ++ "pa2gw2a0=0xFB44\0" ++ "maxp5ga0=0x3E\0" ++ "maxp5gha0=0x3a\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xFEB2\0" ++ "pa5gw1a0=0x1570\0" ++ "pa5gw2a0=0xFAD6\0" ++ "pa5glw0a0=0xFE64\0" ++ "pa5glw1a0=0x13F7\0" ++ "pa5glw2a0=0xFAF6\0" ++ "pa5ghw0a0=0xFEAB\0" ++ "pa5ghw1a0=0x15BB\0" ++ "pa5ghw2a0=0xFAC6\0" ++ "maxp2ga1=0x42\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xFF17\0" ++ "pa2gw1a1=0x13C4\0" ++ "pa2gw2a1=0xFB3C\0" ++ "maxp5ga1=0x3E\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xFE6F\0" ++ "pa5gw1a1=0x13CC\0" ++ "pa5gw2a1=0xFAF8\0" ++ "pa5glw0a1=0xFE87\0" ++ "pa5glw1a1=0x14BE\0" ++ "pa5glw2a1=0xFAD6\0" ++ "pa5ghw0a1=0xFE68\0" ++ "pa5ghw1a1=0x13E9\0" ++ "pa5ghw2a1=0xFAF6\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43235usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:05:30:01\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4347\0" ++ "boardrev=0x1113\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x0\0" ++ "boardtype=0x0571\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x2222\0" ++ "mcs2gpo5=0x2222\0" ++ "mcs2gpo6=0x2222\0" ++ "mcs2gpo7=0x4444\0" ++ "maxp2ga0=0x42\0" ++ "itt2ga0=0x20\0" ++ "pa2gw0a0=0xFF00\0" ++ "pa2gw1a0=0x143C\0" ++ "pa2gw2a0=0xFB27\0" ++ "maxp2ga1=0x42\0" ++ "itt2ga1=0x20\0" ++ "pa2gw0a1=0xFF22\0" ++ "pa2gw1a1=0x142E\0" ++ "pa2gw2a1=0xFB45\0" ++ "tempthresh=120\0" ++ "temps_period=5\0" ++ "temp_hysteresis=5\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43236usb)[] = ++ "vendid=0x14e4\0" ++ "subvendid=0x0a5c\0" ++ "subdevid=0xbdc\0" ++ "macaddr=00:90:4c:03:21:23\0" ++ "cctl=0\0" ++ "ccode=US\0" ++ "regrev=0x0\0" ++ "ledbh0=0x82\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0x0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "sromrev=8\0" ++ "devid=0x4346\0" ++ "boardrev=0x1532\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x2000\0" ++ "boardtype=0x0521\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "ofdm2gpo=0x33333333\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x3333\0" ++ "mcs2gpo1=0x3333\0" ++ "mcs2gpo2=0x3333\0" ++ "mcs2gpo3=0x3333\0" ++ "mcs2gpo4=0x5555\0" ++ "mcs2gpo5=0x5555\0" ++ "mcs2gpo6=0x5555\0" ++ "mcs2gpo7=0x5555\0" ++ "mcs5gpo4=0x2222\0" ++ "mcs5gpo5=0x2222\0" ++ "mcs5gpo6=0x2222\0" ++ "mcs5gpo7=0x2222\0" ++ "mcs5glpo4=0x2222\0" ++ "mcs5glpo5=0x2222\0" ++ "mcs5glpo6=0x2222\0" ++ "mcs5glpo7=0x2222\0" ++ "mcs5ghpo4=0x2222\0" ++ "mcs5ghpo5=0x2222\0" ++ "mcs5ghpo6=0x2222\0" ++ "mcs5ghpo7=0x2222\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xFFD8\0" ++ "pa2gw1a0=0x171C\0" ++ "pa2gw2a0=0xFB14\0" ++ "maxp5ga0=0x3e\0" ++ "maxp5gha0=0x3a\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xFE88\0" ++ "pa5gw1a0=0x141C\0" ++ "pa5gw2a0=0xFB17\0" ++ "pa5glw0a0=0xFE8C\0" ++ "pa5glw1a0=0x1493\0" ++ "pa5glw2a0=0xFAFC\0" ++ "pa5ghw0a0=0xFE86\0" ++ "pa5ghw1a0=0x13CC\0" ++ "pa5ghw2a0=0xFB20\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0x0020\0" ++ "pa2gw1a1=0x1791\0" ++ "pa2gw2a1=0xFB5F\0" ++ "maxp5ga1=0x3e\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xFE7E\0" ++ "pa5gw1a1=0x1399\0" ++ "pa5gw2a1=0xFB27\0" ++ "pa5glw0a1=0xFE82\0" ++ "pa5glw1a1=0x13F3\0" ++ "pa5glw2a1=0xFB14\0" ++ "pa5ghw0a1=0xFE96\0" ++ "pa5ghw1a1=0x13BF\0" ++ "pa5ghw2a1=0xFB30\0" ++ "tempthresh=120\0" ++ "temps_period=5\0" ++ "temp_hysteresis=5\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319usb)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x4e7\0" ++ "boardrev=0x1508\0" ++ "boardflags=0x200\0" ++ "xtalfreq=30000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=255\0" ++ "opo=0\0" ++ "pa0b0=5756\0" ++ "pa0b1=64121\0" ++ "pa0b2=65153\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=76\0" ++ "rssismf2g=0xa\0" ++ "rssismc2g=0xb\0" ++ "rssisav2g=0x3\0" ++ "bxa2g=0\0" ++ "tri2g=78\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x44441111\0" ++ "mcs2gpo0=0xaaaa\0" ++ "mcs2gpo1=0xaaaa\0" ++ "boardnum=1\0" ++ "macaddr=00:90:4c:16:${maclo}\0" ++ "otpimagesize=182\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4360usb)[] = ++ "sromrev=11\0" ++ "boardtype=0x623\0" ++ "venid=0x14e4\0" ++ "boardvendor=0x14e4\0" ++ "devid=0x43a0\0" ++ "boardrev=0x1101\0" ++ "boardflags=0x10001000\0" ++ "boardflags2=0x0\0" ++ "boardflags3=0x0\0" ++ "macaddr=00:90:4c:0e:60:01\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "agbg0=0x2\0" ++ "agbg1=0x2\0" ++ "agbg2=0xff\0" ++ "aga0=0x2\0" ++ "aga1=0x2\0" ++ "aga2=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0\0" ++ "tssiposslope2g=1\0" ++ "epagain2g=0\0" ++ "pdgain2g=2\0" ++ "tworangetssi2g=0\0" ++ "papdcap2g=0\0" ++ "femctrl=1\0" ++ "tssiposslope5g=1\0" ++ "epagain5g=0\0" ++ "pdgain5g=2\0" ++ "tworangetssi5g=0\0" ++ "papdcap5g=0\0" ++ "gainctrlsph=0\0" ++ "tempthresh=0xff\0" ++ "tempoffset=0xff\0" ++ "rawtempsense=0x1ff\0" ++ "measpower=0x7f\0" ++ "tempsense_slope=0xff\0" ++ "tempcorrx=0x3f\0" ++ "tempsense_option=0x3\0" ++ "phycal_tempdelta=255\0" ++ "temps_period=15\0" ++ "temps_hysteresis=15\0" ++ "measpower1=0x7f\0" ++ "subband5gver=0x4\0" ++ "pcieingress_war=15\0" ++ "sar2g=18\0" ++ "sar5g=15\0" ++ "noiselvl2ga0=31\0" ++ "noiselvl2ga1=31\0" ++ "noiselvl2ga2=31\0" ++ "noiselvl5gla0=31\0" ++ "noiselvl5gla1=31\0" ++ "noiselvl5gla2=31\0" ++ "noiselvl5gma0=31\0" ++ "noiselvl5gma1=31\0" ++ "noiselvl5gma2=31\0" ++ "noiselvl5gha0=31\0" ++ "noiselvl5gha1=31\0" ++ "noiselvl5gha2=31\0" ++ "noiselvl5gua0=31\0" ++ "noiselvl5gua1=31\0" ++ "noiselvl5gua2=31\0" ++ "rxgainerr2g=0xffff\0" ++ "rxgainerr5g=0xffff,0xffff,0xffff,0xffff\0" ++ "maxp2ga0=76\0" ++ "pa2ga0=0xfe72,0x14c0,0xfac7\0" ++ "rxgains2gelnagaina0=4\0" ++ "rxgains2gtrisoa0=10\0" ++ "rxgains2gtrelnabypa0=1\0" ++ "rxgains5gelnagaina0=4\0" ++ "rxgains5gtrisoa0=11\0" ++ "rxgains5gtrelnabypa0=1\0" ++ "maxp5ga0=72,72,76,76\0" ++"pa5ga0=0xfe75,0x14b5,0xfad4,0xfe97,0x121a,0xfb6e,0xfe7f,0x149d,0xfad0,0xfe7c,0x1431,0xfae6\0" ++ "maxp2ga1=76\0" ++ "pa2ga1=0xfe80,0x1472,0xfabc\0" ++ "rxgains2gelnagaina1=4\0" ++ "rxgains2gtrisoa1=10\0" ++ "rxgains2gtrelnabypa1=1\0" ++ "rxgains5gelnagaina1=4\0" ++ "rxgains5gtrisoa1=11\0" ++ "rxgains5gtrelnabypa1=1\0" ++ "maxp5ga1=72,72,76,76\0" ++"pa5ga1=0xfe72,0x155e,0xfa96,0xfea1,0x125d,0xfb55,0xfe77,0x1596,0xfa8e,0xfe78,0x15e1,0xfa7a\0" ++ "END\0"; ++ ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++#endif /* BCMUSBDEV */ ++ ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++/* Also used by wl_readconfigdata for vars download */ ++char BCMATTACHDATA(mfgsromvars)[VARS_MAX]; ++int BCMATTACHDATA(defvarslen) = 0; ++#endif ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++static char BCMATTACHDATA(defaultsromvars_4331)[] = ++ "sromrev=9\0" ++ "boardrev=0x1104\0" ++ "boardflags=0x200\0" ++ "boardflags2=0x0\0" ++ "boardtype=0x524\0" ++ "boardvendor=0x14e4\0" ++ "boardnum=0x2064\0" ++ "macaddr=00:90:4c:1a:20:64\0" ++ "ccode=0x0\0" ++ "regrev=0x0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0xffff\0" ++ "opo=0x0\0" ++ "aa2g=0x7\0" ++ "aa5g=0x7\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0x2\0" ++ "ag3=0xff\0" ++ "pa0b0=0xfe7f\0" ++ "pa0b1=0x15d9\0" ++ "pa0b2=0xfac6\0" ++ "pa0itssit=0x20\0" ++ "pa0maxpwr=0x48\0" ++ "pa1b0=0xfe89\0" ++ "pa1b1=0x14b1\0" ++ "pa1b2=0xfada\0" ++ "pa1lob0=0xffff\0" ++ "pa1lob1=0xffff\0" ++ "pa1lob2=0xffff\0" ++ "pa1hib0=0xfe8f\0" ++ "pa1hib1=0x13df\0" ++ "pa1hib2=0xfafa\0" ++ "pa1itssit=0x3e\0" ++ "pa1maxpwr=0x3c\0" ++ "pa1lomaxpwr=0x3c\0" ++ "pa1himaxpwr=0x3c\0" ++ "bxa2g=0x3\0" ++ "rssisav2g=0x7\0" ++ "rssismc2g=0xf\0" ++ "rssismf2g=0xf\0" ++ "bxa5g=0x3\0" ++ "rssisav5g=0x7\0" ++ "rssismc5g=0xf\0" ++ "rssismf5g=0xf\0" ++ "tri2g=0xff\0" ++ "tri5g=0xff\0" ++ "tri5gl=0xff\0" ++ "tri5gh=0xff\0" ++ "rxpo2g=0xff\0" ++ "rxpo5g=0xff\0" ++ "txchain=0x7\0" ++ "rxchain=0x7\0" ++ "antswitch=0x0\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x4\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "elna2g=0xff\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x4\0" ++ "triso5g=0x3\0" ++ "antswctl5g=0x0\0" ++ "elna5g=0xff\0" ++ "cckbw202gpo=0x0\0" ++ "cckbw20ul2gpo=0x0\0" ++ "legofdmbw202gpo=0x0\0" ++ "legofdmbw20ul2gpo=0x0\0" ++ "legofdmbw205glpo=0x0\0" ++ "legofdmbw20ul5glpo=0x0\0" ++ "legofdmbw205gmpo=0x0\0" ++ "legofdmbw20ul5gmpo=0x0\0" ++ "legofdmbw205ghpo=0x0\0" ++ "legofdmbw20ul5ghpo=0x0\0" ++ "mcsbw202gpo=0x0\0" ++ "mcsbw20ul2gpo=0x0\0" ++ "mcsbw402gpo=0x0\0" ++ "mcsbw205glpo=0x0\0" ++ "mcsbw20ul5glpo=0x0\0" ++ "mcsbw405glpo=0x0\0" ++ "mcsbw205gmpo=0x0\0" ++ "mcsbw20ul5gmpo=0x0\0" ++ "mcsbw405gmpo=0x0\0" ++ "mcsbw205ghpo=0x0\0" ++ "mcsbw20ul5ghpo=0x0\0" ++ "mcsbw405ghpo=0x0\0" ++ "mcs32po=0x0\0" ++ "legofdm40duppo=0x0\0" ++ "maxp2ga0=0x48\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "pa2gw0a0=0xfe7f\0" ++ "pa2gw1a0=0x15d9\0" ++ "pa2gw2a0=0xfac6\0" ++ "maxp5ga0=0x3c\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xfe89\0" ++ "pa5gw1a0=0x14b1\0" ++ "pa5gw2a0=0xfada\0" ++ "pa5glw0a0=0xffff\0" ++ "pa5glw1a0=0xffff\0" ++ "pa5glw2a0=0xffff\0" ++ "pa5ghw0a0=0xfe8f\0" ++ "pa5ghw1a0=0x13df\0" ++ "pa5ghw2a0=0xfafa\0" ++ "maxp2ga1=0x48\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xfe54\0" ++ "pa2gw1a1=0x1563\0" ++ "pa2gw2a1=0xfa7f\0" ++ "maxp5ga1=0x3c\0" ++ "maxp5gha1=0x3c\0" ++ "maxp5gla1=0x3c\0" ++ "pa5gw0a1=0xfe53\0" ++ "pa5gw1a1=0x14fe\0" ++ "pa5gw2a1=0xfa94\0" ++ "pa5glw0a1=0xffff\0" ++ "pa5glw1a1=0xffff\0" ++ "pa5glw2a1=0xffff\0" ++ "pa5ghw0a1=0xfe6e\0" ++ "pa5ghw1a1=0x1457\0" ++ "pa5ghw2a1=0xfab9\0" ++ "END\0"; ++#endif ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++static char BCMATTACHDATA(defaultsromvars_wltest)[] = ++ "macaddr=00:90:4c:f8:00:01\0" ++ "et0macaddr=00:11:22:33:44:52\0" ++ "et0phyaddr=30\0" ++ "et0mdcport=0\0" ++ "gpio2=robo_reset\0" ++ "boardvendor=0x14e4\0" ++ "boardflags=0x210\0" ++ "boardflags2=0\0" ++ "boardtype=0x04c3\0" ++ "boardrev=0x1100\0" ++ "sromrev=8\0" ++ "devid=0x432c\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "ledbh0=255\0" ++ "ledbh1=255\0" ++ "ledbh2=255\0" ++ "ledbh3=255\0" ++ "leddc=0xffff\0" ++ "aa2g=3\0" ++ "ag0=2\0" ++ "ag1=2\0" ++ "aa5g=3\0" ++ "aa0=2\0" ++ "aa1=2\0" ++ "txchain=3\0" ++ "rxchain=3\0" ++ "antswitch=0\0" ++ "itt2ga0=0x20\0" ++ "maxp2ga0=0x48\0" ++ "pa2gw0a0=0xfe9e\0" ++ "pa2gw1a0=0x15d5\0" ++ "pa2gw2a0=0xfae9\0" ++ "itt2ga1=0x20\0" ++ "maxp2ga1=0x48\0" ++ "pa2gw0a1=0xfeb3\0" ++ "pa2gw1a1=0x15c9\0" ++ "pa2gw2a1=0xfaf7\0" ++ "tssipos2g=1\0" ++ "extpagain2g=0\0" ++ "pdetrange2g=0\0" ++ "triso2g=3\0" ++ "antswctl2g=0\0" ++ "tssipos5g=1\0" ++ "extpagain5g=0\0" ++ "pdetrange5g=0\0" ++ "triso5g=3\0" ++ "antswctl5g=0\0" ++ "cck2gpo=0\0" ++ "ofdm2gpo=0\0" ++ "mcs2gpo0=0\0" ++ "mcs2gpo1=0\0" ++ "mcs2gpo2=0\0" ++ "mcs2gpo3=0\0" ++ "mcs2gpo4=0\0" ++ "mcs2gpo5=0\0" ++ "mcs2gpo6=0\0" ++ "mcs2gpo7=0\0" ++ "cddpo=0\0" ++ "stbcpo=0\0" ++ "bw40po=4\0" ++ "bwduppo=0\0" ++ "END\0"; ++#endif ++ ++static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */ ++ ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) || (defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)) ++/* It must end with pattern of "END" */ ++static uint ++BCMATTACHFN(srom_vars_len)(char *vars) ++{ ++ uint pos = 0; ++ uint len; ++ char *s; ++ ++ for (s = vars; s && *s;) { ++ ++ if (strcmp(s, "END") == 0) ++ break; ++ ++ len = strlen(s); ++ s += strlen(s) + 1; ++ pos += len + 1; ++ /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */ ++ if (pos > 4000) { ++ return 0; ++ } ++ } ++ ++ return pos + 4; /* include the "END\0" */ ++} ++#endif ++ ++/* Initialization of varbuf structure */ ++static void ++BCMATTACHFN(varbuf_init)(varbuf_t *b, char *buf, uint size) ++{ ++ b->size = size; ++ b->base = b->buf = buf; ++} ++ ++/* append a null terminated var=value string */ ++static int ++BCMATTACHFN(varbuf_append)(varbuf_t *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ size_t len; ++ char *s; ++ ++ if (b->size < 2) ++ return 0; ++ ++ va_start(ap, fmt); ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ va_end(ap); ++ ++ /* C99 snprintf behavior returns r >= size on overflow, ++ * others return -1 on overflow. ++ * All return -1 on format error. ++ * We need to leave room for 2 null terminations, one for the current var ++ * string, and one for final null of the var table. So check that the ++ * strlen written, r, leaves room for 2 chars. ++ */ ++ if ((r == -1) || (r > (int)(b->size - 2))) { ++ b->size = 0; ++ return 0; ++ } ++ ++ /* Remove any earlier occurrence of the same variable */ ++ if ((s = strchr(b->buf, '=')) != NULL) { ++ len = (size_t)(s - b->buf); ++ for (s = b->base; s < b->buf;) { ++ if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') { ++ len = strlen(s) + 1; ++ memmove(s, (s + len), ((b->buf + r + 1) - (s + len))); ++ b->buf -= len; ++ b->size += (unsigned int)len; ++ break; ++ } ++ ++ while (*s++) ++ ; ++ } ++ } ++ ++ /* skip over this string's null termination */ ++ r++; ++ b->size -= r; ++ b->buf += r; ++ ++ return r; ++} ++ ++/* ++ * Initialize local vars from the right source for this platform. ++ * Return 0 on success, nonzero on error. ++ */ ++int ++BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ char **vars, uint *count) ++{ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ if (vars == NULL || count == NULL) ++ return (0); ++ ++ *vars = NULL; ++ *count = 0; ++ ++ switch (BUSTYPE(bustype)) { ++ case SI_BUS: ++ case JTAG_BUS: ++ return initvars_srom_si(sih, osh, curmap, vars, count); ++ ++ case PCI_BUS: ++ ASSERT(curmap != NULL); ++ if (curmap == NULL) ++ return (-1); ++ ++ return initvars_srom_pci(sih, curmap, vars, count); ++ ++ case PCMCIA_BUS: ++ return initvars_cis_pcmcia(sih, osh, vars, count); ++ ++ ++#ifdef BCMSPI ++ case SPI_BUS: ++ return initvars_cis_spi(osh, vars, count); ++#endif /* BCMSPI */ ++ ++ default: ++ ASSERT(0); ++ } ++ return (-1); ++} ++ ++/* support only 16-bit word read from srom */ ++int ++srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf, bool check_crc) ++{ ++ uint i, off, nw; ++ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ ++ /* check input - 16-bit access only */ ++ if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX) ++ return 1; ++ ++ off = byteoff / 2; ++ nw = nbytes / 2; ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ if (!curmap) ++ return 1; ++ ++ if (si_is_sprom_available(sih)) { ++ uint16 *srom; ++ ++ srom = (uint16 *)SROM_OFFSET(sih); ++ if (srom == NULL) ++ return 1; ++ ++ if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc)) ++ return 1; ++ } ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++ else { ++ if (otp_read_pci(osh, sih, buf, SROM_MAX)) ++ return 1; ++ } ++#endif ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ for (i = 0; i < nw; i++) { ++ if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16 *)(buf + i))) ++ return 1; ++ } ++#ifdef BCMSPI ++ } else if (BUSTYPE(bustype) == SPI_BUS) { ++ if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0) ++ return 1; ++#endif /* BCMSPI */ ++ } else if (BUSTYPE(bustype) == SI_BUS) { ++#if defined(BCMUSBDEV) ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint origidx; ++ void *regs; ++ int rc; ++ bool wasup; ++ ++ /* Don't bother if we can't talk to SPROM */ ++ if (!si_is_sprom_available(sih)) ++ return 1; ++ ++ origidx = si_coreidx(sih); ++ regs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!regs) ++ regs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(regs != NULL); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ rc = get_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes, check_crc); ++ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ return rc; ++ } ++#endif ++ ++ return 1; ++ } else { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* support only 16-bit word write into srom */ ++int ++srom_write(si_t *sih, uint bustype, void *curmap, osl_t *osh, ++ uint byteoff, uint nbytes, uint16 *buf) ++{ ++ uint i, nw, crc_range; ++ uint16 *old, *new; ++ uint8 crc; ++ volatile uint32 val32; ++ int rc = 1; ++ ++ ASSERT(bustype == BUSTYPE(bustype)); ++ ++ old = MALLOC(osh, SROM_MAXW * sizeof(uint16)); ++ new = MALLOC(osh, SROM_MAXW * sizeof(uint16)); ++ ++ if (old == NULL || new == NULL) ++ goto done; ++ ++ /* check input - 16-bit access only. use byteoff 0x55aa to indicate ++ * srclear ++ */ ++ if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1))) ++ goto done; ++ ++ if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX)) ++ goto done; ++ ++ if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ crc_range = SROM_MAX; ++ } ++#if defined(BCMUSBDEV) ++ else { ++ crc_range = srom_size(sih, osh); ++ } ++#else ++ else { ++ crc_range = (SROM8_SIGN + 1) * 2; /* must big enough for SROM8 */ ++ } ++#endif ++ ++ nw = crc_range / 2; ++ /* read first small number words from srom, then adjust the length, read all */ ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ ++ BS_ERROR(("%s: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n", ++ __FUNCTION__, old[SROM4_SIGN], old[SROM8_SIGN])); ++ /* Deal with blank srom */ ++ if (old[0] == 0xffff) { ++ /* see if the input buffer is valid SROM image or not */ ++ if (buf[SROM11_SIGN] == SROM11_SIGNATURE) { ++ BS_ERROR(("%s: buf[SROM11_SIGN] 0x%x\n", ++ __FUNCTION__, buf[SROM11_SIGN])); ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM11_WORDS * 2) { ++ rc = BCME_BUFTOOSHORT; ++ goto done; ++ } else if (nbytes > SROM11_WORDS * 2) { ++ rc = BCME_BUFTOOLONG; ++ goto done; ++ } ++ ++ nw = SROM11_WORDS; ++ } else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (buf[SROM8_SIGN] == SROM4_SIGNATURE)) { ++ BS_ERROR(("%s: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n", ++ __FUNCTION__, buf[SROM4_SIGN], buf[SROM8_SIGN])); ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM4_WORDS * 2) { ++ rc = BCME_BUFTOOSHORT; ++ goto done; ++ } else if (nbytes > SROM4_WORDS * 2) { ++ rc = BCME_BUFTOOLONG; ++ goto done; ++ } ++ ++ nw = SROM4_WORDS; ++ } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */ ++ BS_ERROR(("%s: Not SROM4 or SROM8.\n", __FUNCTION__)); ++ ++ nw = SROM_WORDS; ++ } else { ++ BS_ERROR(("%s: Invalid input file signature\n", __FUNCTION__)); ++ rc = BCME_BADARG; ++ goto done; ++ } ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else if (old[SROM11_SIGN] == SROM11_SIGNATURE) { ++ nw = SROM11_WORDS; ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (old[SROM8_SIGN] == SROM4_SIGNATURE)) { ++ nw = SROM4_WORDS; ++ crc_range = nw * 2; ++ if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) ++ goto done; ++ } else { ++ /* Assert that we have already read enough for sromrev 2 */ ++ ASSERT(crc_range >= SROM_WORDS * 2); ++ nw = SROM_WORDS; ++ crc_range = nw * 2; ++ } ++ ++ if (byteoff == 0x55aa) { ++ /* Erase request */ ++ crc_range = 0; ++ memset((void *)new, 0xff, nw * 2); ++ } else { ++ /* Copy old contents */ ++ bcopy((void *)old, (void *)new, nw * 2); ++ /* make changes */ ++ bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes); ++ } ++ ++ if (crc_range) { ++ /* calculate crc */ ++ htol16_buf(new, crc_range); ++ crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE); ++ ltoh16_buf(new, crc_range); ++ new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff); ++ } ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ uint16 *srom = NULL; ++ void *ccregs = NULL; ++ uint32 ccval = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* save current control setting */ ++ ccval = si_chipcontrl_read(sih); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { ++ /* Disable Ext PA lines to allow reading from SROM */ ++ si_chipcontrl_epa4331(sih, FALSE); ++ } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ si_chipcontrl_srom4360(sih, TRUE); ++ } ++ ++ /* enable writes to the SPROM */ ++ if (sih->ccrev > 31) { ++ ccregs = (void *)((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET); ++ srom = (uint16 *)((uint8 *)ccregs + CC_SROM_OTP); ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0); ++ } else { ++ srom = (uint16 *)((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET); ++ val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ val32 |= SPROM_WRITEEN; ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32); ++ } ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ if (old[i] != new[i]) { ++ if (sih->ccrev > 31) { ++ if ((sih->cccaps & CC_CAP_SROM) == 0) { ++ /* No srom support in this chip */ ++ BS_ERROR(("srom_write, invalid srom, skip\n")); ++ } else ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE, ++ i, new[i]); ++ } else { ++ W_REG(osh, &srom[i], new[i]); ++ } ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ } ++ /* disable writes to the SPROM */ ++ if (sih->ccrev > 31) { ++ (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0); ++ } else { ++ OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ++ ~SPROM_WRITEEN); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* Restore config after reading SROM */ ++ si_chipcontrl_restore(sih, ccval); ++ } ++ ++ } else if (BUSTYPE(bustype) == PCMCIA_BUS) { ++ /* enable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WEN)) ++ goto done; ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ /* write srom */ ++ for (i = 0; i < nw; i++) { ++ if (old[i] != new[i]) { ++ sprom_write_pcmcia(osh, (uint16)(i), new[i]); ++ bcm_mdelay(WRITE_WORD_DELAY); ++ } ++ } ++ /* disable writes to the SPROM */ ++ if (sprom_cmd_pcmcia(osh, SROM_WDS)) ++ goto done; ++ } else if (BUSTYPE(bustype) == SI_BUS) { ++#if defined(BCMUSBDEV) ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint origidx; ++ void *regs; ++ bool wasup; ++ ++ origidx = si_coreidx(sih); ++ regs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!regs) ++ regs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(regs != NULL); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ rc = set_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes); ++ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ goto done; ++ } ++#endif ++ goto done; ++ } else { ++ goto done; ++ } ++ ++ bcm_mdelay(WRITE_ENABLE_DELAY); ++ rc = 0; ++ ++done: ++ if (old != NULL) ++ MFREE(osh, old, SROM_MAXW * sizeof(uint16)); ++ if (new != NULL) ++ MFREE(osh, new, SROM_MAXW * sizeof(uint16)); ++ ++ return rc; ++} ++#endif ++ ++#if defined(BCMUSBDEV) ++#define SI_PCMCIA_READ(osh, regs, fcr) \ ++ R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2) ++#define SI_PCMCIA_WRITE(osh, regs, fcr, v) \ ++ W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v) ++ ++/* set PCMCIA srom command register */ ++static int ++srom_cmd_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint8 cmd) ++{ ++ uint8 status = 0; ++ uint wait_cnt = 0; ++ ++ /* write srom command register */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_CS, cmd); ++ ++ /* wait status */ ++ while (++wait_cnt < 1000000) { ++ status = SI_PCMCIA_READ(osh, pcmregs, SROM_CS); ++ if (status & SROM_DONE) ++ return 0; ++ OSL_DELAY(1); ++ } ++ ++ BS_ERROR(("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, status)); ++ return 1; ++} ++ ++/* read a word from the PCMCIA srom over SI */ ++static int ++srom_read_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l); ++ ++ /* do read */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_READ)) ++ return 1; ++ ++ /* read data */ ++ data_h = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAH); ++ data_l = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAL); ++ *data = ((uint16)data_h << 8) | data_l; ++ ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* write a word to the PCMCIA srom over SI */ ++static int ++srom_write_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ int rc; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l); ++ ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); ++ ++ /* write data */ ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAH, data_h); ++ SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAL, data_l); ++ ++ /* do write */ ++ rc = srom_cmd_si_pcmcia(osh, pcmregs, SROM_WRITE); ++ OSL_DELAY(20000); ++ return rc; ++} ++#endif ++ ++/* ++ * Read the srom for the pcmcia-srom over si case. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz, bool check_crc) ++{ ++ uint i, nw, woff, wsz; ++ int err = 0; ++ ++ /* read must be at word boundary */ ++ ASSERT((boff & 1) == 0 && (bsz & 1) == 0); ++ ++ /* read sprom size and validate the parms */ ++ if ((nw = srom_size(sih, osh)) == 0) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom size unknown\n")); ++ err = -1; ++ goto out; ++ } ++ if (boff + bsz > 2 * nw) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom size exceeded\n")); ++ err = -2; ++ goto out; ++ } ++ ++ /* read in sprom contents */ ++ for (woff = boff / 2, wsz = bsz / 2, i = 0; ++ woff < nw && i < wsz; woff ++, i ++) { ++ if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &srom[i])) { ++ BS_ERROR(("get_si_pcmcia_srom: sprom read failed\n")); ++ err = -3; ++ goto out; ++ } ++ } ++ ++ if (check_crc) { ++ if (srom[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: srom[0] == 0xffff, assuming unprogrammed srom\n", ++ __FUNCTION__)); ++ err = -4; ++ goto out; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(srom, nw * 2); ++ if (hndcrc8((uint8 *)srom, nw * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ BS_ERROR(("%s: bad crc\n", __FUNCTION__)); ++ err = -5; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(srom, nw * 2); ++ } ++ ++out: ++ return err; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* ++ * Write the srom for the pcmcia-srom over si case. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs, ++ uint boff, uint16 *srom, uint bsz) ++{ ++ uint i, nw, woff, wsz; ++ uint16 word; ++ uint8 crc; ++ int err = 0; ++ ++ /* write must be at word boundary */ ++ ASSERT((boff & 1) == 0 && (bsz & 1) == 0); ++ ++ /* read sprom size and validate the parms */ ++ if ((nw = srom_size(sih, osh)) == 0) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom size unknown\n")); ++ err = -1; ++ goto out; ++ } ++ if (boff + bsz > 2 * nw) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom size exceeded\n")); ++ err = -2; ++ goto out; ++ } ++ ++ /* enable write */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WEN)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom wen failed\n")); ++ err = -3; ++ goto out; ++ } ++ ++ /* write buffer to sprom */ ++ for (woff = boff / 2, wsz = bsz / 2, i = 0; ++ woff < nw && i < wsz; woff ++, i ++) { ++ if (srom_write_si_pcmcia(osh, pcmregs, (uint16)woff, srom[i])) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom write failed\n")); ++ err = -4; ++ goto out; ++ } ++ } ++ ++ /* fix crc */ ++ crc = CRC8_INIT_VALUE; ++ for (woff = 0; woff < nw; woff ++) { ++ if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &word)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom fix crc read failed\n")); ++ err = -5; ++ goto out; ++ } ++ word = htol16(word); ++ crc = hndcrc8((uint8 *)&word, woff != nw - 1 ? 2 : 1, crc); ++ } ++ word = (~crc << 8) + (ltoh16(word) & 0xff); ++ if (srom_write_si_pcmcia(osh, pcmregs, (uint16)(woff - 1), word)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom fix crc write failed\n")); ++ err = -6; ++ goto out; ++ } ++ ++ /* disable write */ ++ if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WDS)) { ++ BS_ERROR(("set_si_pcmcia_srom: sprom wds failed\n")); ++ err = -7; ++ goto out; ++ } ++ ++out: ++ return err; ++} ++#endif ++#endif ++ ++static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s"; ++static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s"; ++static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x"; ++static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x"; ++static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d"; ++static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d"; ++static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d"; ++static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x"; ++static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x"; ++static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x"; ++static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x"; ++static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x"; ++static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x"; ++static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d"; ++static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d"; ++static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" }; ++static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d"; ++static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1lob)[][11] = ++ { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1hib)[][11] = ++ { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" }; ++static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d"; ++static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d"; ++static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d"; ++static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x"; ++static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x"; ++static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x"; ++static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x"; ++static const char BCMATTACHDATA(vstr_ledbh)[] = "ledbh%d=0x%x"; ++static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0"; ++static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c"; ++static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x"; ++static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x"; ++static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d"; ++static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d"; ++static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d"; ++static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d"; ++static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d"; ++static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d"; ++static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d"; ++static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d"; ++static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d"; ++static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d"; ++static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d"; ++static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d"; ++static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d"; ++static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d"; ++static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d"; ++static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d"; ++static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d"; ++static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d"; ++static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d"; ++static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d"; ++static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x"; ++static const char BCMATTACHDATA(vstr_leddc)[] = "leddc=0x%04x"; ++static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x"; ++static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x"; ++static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d"; ++static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x"; ++static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x"; ++static const char BCMNMIATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x"; ++static const char BCMNMIATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x"; ++static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x"; ++static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x"; ++static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x"; ++static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x"; ++static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x"; ++static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x"; ++static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x"; ++static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x"; ++static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x"; ++static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x"; ++static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x"; ++static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x"; ++static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x"; ++static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x"; ++static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x"; ++static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x"; ++static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x"; ++static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x"; ++static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x"; ++static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x"; ++static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x"; ++static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d"; ++static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x"; ++#ifdef BCM_BOOTLOADER ++static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x"; ++static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x"; ++static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x"; ++static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x"; ++static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x"; ++static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x"; ++static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x"; ++static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x"; ++static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x"; ++static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x"; ++static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x"; ++static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x"; ++static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x"; ++static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x"; ++static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x"; ++static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x"; ++static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x"; ++#endif /* BCM_BOOTLOADER */ ++static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d"; ++static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s"; ++static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x"; ++ ++/* Power per rate for SROM V9 */ ++static const char BCMATTACHDATA(vstr_cckbw202gpo)[][19] = ++ { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x" }; ++static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][22] = ++ { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" }; ++static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] = ++ { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x", ++ "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x", ++ "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" }; ++ ++static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] = ++{ "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] = ++ { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] = ++ { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] = ++ { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x"}; ++ ++static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x"; ++static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x"; ++ ++/* SROM V11 */ ++static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d"; /* HNBU_TEMPTHRESH */ ++static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d"; ++static const char BCMATTACHDATA(vstr_temp_hysteresis)[] = "temp_hysteresis=%d"; ++static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d"; ++static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d"; ++static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d"; ++static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d"; ++static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d"; /* HNBU_FEM_CFG */ ++static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d"; ++static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d"; ++static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d"; ++static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d"; ++static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d"; ++static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d"; ++static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d"; /* HNBU_ACPA_CX */ ++static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," ++ "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina=%d"; ++static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d"; ++static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d"; ++static const char BCMATTACHDATA(vstr_measpower)[] = "measpower%d=0x%x"; /* HNBU_MEAS_PWR */ ++static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x"; ++static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x"; ++/* HNBU_ACPPR_2GPO */ ++static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805glpo)[] = "mcsbw805glpo=0x%x"; /* HNBU_ACPPR_5GPO */ ++static const char BCMATTACHDATA(vstr_mcsbw1605glpo)[] = "mcsbw1605glpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805gmpo)[] = "mcsbw805gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw1605gmpo)[] = "mcsbw1605gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw805ghpo)[] = "mcsbw805ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcsbw1605ghpo)[] = "mcsbw1605ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5rlpo)[] = "mcslr5rlpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5gmpo)[] = "mcslr5gmpo=0x%x"; ++static const char BCMATTACHDATA(vstr_mcslr5ghpo)[] = "mcslr5ghpo=0x%x"; ++static const char BCMATTACHDATA(vstr_sb20in40rrpo)[] = "sb20in40%crrpo=0x%x"; /* HNBU_ACPPR_SBPO */ ++static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x"; ++static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x"; ++static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x"; ++static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d"; /* HNBU_NOISELVL */ ++static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5g%ca%d=%d"; ++static const char BCMATTACHDATA(vstr_rxgainerr2g)[] = "rxgainerr2g=0x%x"; /* HNBU_RXGAIN_ERR */ ++static const char BCMATTACHDATA(vstr_rxgainerr5g)[] = "rxgainerr5g=0x%x,0x%x,0x%x,0x%x"; ++static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x"; /* HNBU_AGBGA */ ++static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x"; ++ ++static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s"; ++ ++static const char BCMATTACHDATA(vstr_end)[] = "END\0"; ++ ++uint8 patch_pair = 0; ++ ++/* For dongle HW, accept partial calibration parameters */ ++#if defined(BCMUSBDEV) ++#define BCMDONGLECASE(n) case n: ++#else ++#define BCMDONGLECASE(n) ++#endif ++ ++#ifdef BCM_BOOTLOADER ++/* The format of the PMUREGS OTP Tuple -> ++ * 1 byte -> Lower 5 bits has the address of the register ++ * Higher 3 bits has the mode of the register like ++ * PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask ++ * 4 bytes -> Value of the register to be updated. ++ */ ++#define PMUREGS_MODE_MASK 0xE0 ++#define PMUREGS_MODE_SHIFT 5 ++#define PMUREGS_ADDR_MASK 0x1F ++#define PMUREGS_TPL_SIZE 5 ++ ++enum { ++ PMU_PLLREG_MODE, ++ PMU_CCREG_MODE, ++ PMU_VOLTREG_MODE, ++ PMU_RES_TIME_MODE, ++ PMU_RESDEPEND_MODE ++}; ++ ++#define USBREGS_TPL_SIZE 5 ++enum { ++ USB_DEV_CTRL_REG, ++ HSIC_PHY_CTRL1_REG, ++ HSIC_PHY_CTRL2_REG ++}; ++ ++#define USBRDY_DLY_TYPE 0x8000 /* Bit indicating if the byte is pre or post delay value */ ++#define USBRDY_DLY_MASK 0x7FFF /* Bits indicating the amount of delay */ ++#define USBRDY_MAXOTP_SIZE 5 /* Max size of the OTP parameter */ ++ ++#endif /* BCM_BOOTLOADER */ ++ ++#ifdef BCM_BMAC_VARS_APPEND ++int ++BCMATTACHFN(srom_probe_boardtype)(uint8 *pcis[], uint ciscnt) ++{ ++ int i; ++ uint cisnum; ++ uint8 *cis, tup, tlen; ++ ++ for (cisnum = 0; cisnum < ciscnt; cisnum++) { ++ cis = *pcis++; ++ i = 0; ++ do { ++ tup = cis[i++]; ++ if (tup == CISTPL_NULL || tup == CISTPL_END) ++ tlen = 0; ++ else ++ tlen = cis[i++]; ++ ++ if ((i + tlen) >= CIS_SIZE) ++ break; ++ ++ if ((tup == CISTPL_BRCM_HNBU) && (cis[i] == HNBU_BOARDTYPE)) { ++ return (int)((cis[i + 2] << 8) + cis[i + 1]); ++ } ++ ++ i += tlen; ++ ++ } while (tup != CISTPL_END); ++ } ++ ++ return 0; ++} ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++int ++BCMATTACHFN(srom_parsecis)(osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *count) ++{ ++ char eabuf[32]; ++ char *base; ++ varbuf_t b; ++ uint8 *cis, tup, tlen, sromrev = 1; ++ int i, j; ++#ifndef BCM_BOOTLOADER ++ bool ag_init = FALSE; ++#endif ++ uint32 w32; ++ uint funcid; ++ uint cisnum; ++ int32 boardnum; ++ int err; ++ bool standard_cis; ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ boardnum = -1; ++ ++ base = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(base != NULL); ++ if (!base) ++ return -2; ++ ++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS); ++ bzero(base, MAXSZ_NVRAM_VARS); ++#ifdef BCM_BMAC_VARS_APPEND ++ /* 43236 use defaultsromvars_43236usb as the base, ++ * then append and update it with the content from OTP. ++ * Only revision/board specfic content or updates used to override ++ * the driver default will be stored in OTP ++ */ ++ *count -= (strlen(vstr_end) + 1 + 1); /* back off the termnating END\0\0 from fakenvram */ ++ bcopy(*vars, base, *count); ++ b.buf += *count; ++#endif /* BCM_BMAC_VARS_APPEND */ ++ eabuf[0] = '\0'; ++ for (cisnum = 0; cisnum < ciscnt; cisnum++) { ++ cis = *pcis++; ++ i = 0; ++ funcid = 0; ++ standard_cis = TRUE; ++ do { ++ if (standard_cis) { ++ tup = cis[i++]; ++ if (tup == CISTPL_NULL || tup == CISTPL_END) ++ tlen = 0; ++ else ++ tlen = cis[i++]; ++ } else { ++ if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) { ++ tlen = 0; ++ tup = cis[i]; ++ } else { ++ tlen = cis[i]; ++ tup = CISTPL_BRCM_HNBU; ++ } ++ ++i; ++ } ++ if ((i + tlen) >= CIS_SIZE) ++ break; ++ ++ switch (tup) { ++ case CISTPL_VERS_1: ++ /* assume the strings are good if the version field checks out */ ++ if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) { ++ varbuf_append(&b, vstr_manf, &cis[i + 2]); ++ varbuf_append(&b, vstr_productname, ++ &cis[i + 3 + strlen((char *)&cis[i + 2])]); ++ break; ++ } ++ ++ case CISTPL_MANFID: ++ varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]); ++ varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]); ++ break; ++ ++ case CISTPL_FUNCID: ++ funcid = cis[i]; ++ break; ++ ++ case CISTPL_FUNCE: ++ switch (funcid) { ++ case CISTPL_FID_SDIO: ++ funcid = 0; ++ break; ++ default: ++ /* set macaddr if HNBU_MACADDR not seen yet */ ++ if (eabuf[0] == '\0' && cis[i] == LAN_NID && ++ !(ETHER_ISNULLADDR(&cis[i + 2])) && ++ !(ETHER_ISMULTI(&cis[i + 2]))) { ++ ASSERT(cis[i + 1] == ETHER_ADDR_LEN); ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 2], ++ eabuf); ++ ++ /* set boardnum if HNBU_BOARDNUM not seen yet */ ++ if (boardnum == -1) ++ boardnum = (cis[i + 6] << 8) + cis[i + 7]; ++ } ++ break; ++ } ++ break; ++ ++ case CISTPL_CFTABLE: ++ varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]); ++ break; ++ ++ case CISTPL_BRCM_HNBU: ++ switch (cis[i]) { ++ case HNBU_SROMREV: ++ sromrev = cis[i + 1]; ++ varbuf_append(&b, vstr_sromrev, sromrev); ++ break; ++ ++ case HNBU_XTALFREQ: ++ varbuf_append(&b, vstr_xtalfreq, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_CHIPID: ++ varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) + ++ cis[i + 1]); ++ varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) + ++ cis[i + 3]); ++ if (tlen >= 7) { ++ varbuf_append(&b, vstr_chiprev, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ } ++ if (tlen >= 9) { ++ varbuf_append(&b, vstr_subvendid, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ } ++ if (tlen >= 11) { ++ varbuf_append(&b, vstr_subdevid, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ /* subdevid doubles for boardtype */ ++ varbuf_append(&b, vstr_boardtype, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ } ++ break; ++ ++ case HNBU_BOARDNUM: ++ boardnum = (cis[i + 2] << 8) + cis[i + 1]; ++ break; ++ ++ case HNBU_PATCH: ++ { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ ++ /* retrieve the patch pairs ++ * from tlen/6; where 6 is ++ * sizeof(patch addr(2)) + ++ * sizeof(patch data(4)). ++ */ ++ patch_pair = tlen/6; ++ ++ for (j = 0; j < patch_pair; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j); ++ ++ varbuf_append(&b, vstr_paddr, ++ (cis[i + (j*6) + 2] << 8) | ++ cis[i + (j*6) + 1]); ++ ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*6) + 6] << 24) | ++ (cis[i + (j*6) + 5] << 16) | ++ (cis[i + (j*6) + 4] << 8) | ++ cis[i + (j*6) + 3]); ++ } ++ } ++ break; ++ ++ case HNBU_BOARDREV: ++ if (tlen == 2) ++ varbuf_append(&b, vstr_boardrev, cis[i + 1]); ++ else ++ varbuf_append(&b, vstr_boardrev, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_BOARDFLAGS: ++ w32 = (cis[i + 2] << 8) + cis[i + 1]; ++ if (tlen >= 5) ++ w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16)); ++ varbuf_append(&b, vstr_boardflags, w32); ++ ++ if (tlen >= 7) { ++ w32 = (cis[i + 6] << 8) + cis[i + 5]; ++ if (tlen >= 9) ++ w32 |= ((cis[i + 8] << 24) + ++ (cis[i + 7] << 16)); ++ varbuf_append(&b, vstr_boardflags2, w32); ++ } ++ if (tlen >= 11) { ++ w32 = (cis[i + 10] << 8) + cis[i + 9]; ++ if (tlen >= 13) ++ w32 |= ((cis[i + 12] << 24) + ++ (cis[i + 11] << 16)); ++ varbuf_append(&b, vstr_boardflags3, w32); ++ } ++ break; ++ ++ case HNBU_USBFS: ++ varbuf_append(&b, vstr_usbfs, cis[i + 1]); ++ break; ++ ++ case HNBU_BOARDTYPE: ++ varbuf_append(&b, vstr_boardtype, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_HNBUCIS: ++ /* ++ * what follows is a nonstandard HNBU CIS ++ * that lacks CISTPL_BRCM_HNBU tags ++ * ++ * skip 0xff (end of standard CIS) ++ * after this tuple ++ */ ++ tlen++; ++ standard_cis = FALSE; ++ break; ++ ++ case HNBU_USBEPNUM: ++ varbuf_append(&b, vstr_usbepnum, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_PATCH_AUTOINC: { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ uint32 addr_inc; ++ uint8 pcnt; ++ ++ addr_inc = (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ (cis[i + 1]); ++ ++ pcnt = (tlen - 5)/4; ++ for (j = 0; j < pcnt; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j + patch_pair); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j + patch_pair); ++ ++ varbuf_append(&b, vstr_paddr, addr_inc); ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*4) + 8] << 24) | ++ (cis[i + (j*4) + 7] << 16) | ++ (cis[i + (j*4) + 6] << 8) | ++ cis[i + (j*4) + 5]); ++ addr_inc += 4; ++ } ++ patch_pair += pcnt; ++ } ++ break; ++ case HNBU_PATCH2: ++ { ++ char vstr_paddr[16]; ++ char vstr_pdata[16]; ++ ++ /* retrieve the patch pairs ++ * from tlen/8; where 8 is ++ * sizeof(patch addr(4)) + ++ * sizeof(patch data(4)). ++ */ ++ patch_pair = tlen/8; ++ ++ for (j = 0; j < patch_pair; j++) { ++ snprintf(vstr_paddr, sizeof(vstr_paddr), ++ "pa%d=0x%%x", j); ++ snprintf(vstr_pdata, sizeof(vstr_pdata), ++ "pd%d=0x%%x", j); ++ ++ varbuf_append(&b, vstr_paddr, ++ (cis[i + (j*8) + 4] << 24) | ++ (cis[i + (j*8) + 3] << 16) | ++ (cis[i + (j*8) + 2] << 8) | ++ cis[i + (j*8) + 1]); ++ ++ varbuf_append(&b, vstr_pdata, ++ (cis[i + (j*8) + 8] << 24) | ++ (cis[i + (j*8) + 7] << 16) | ++ (cis[i + (j*8) + 6] << 8) | ++ cis[i + (j*8) + 5]); ++ } ++ } ++ break; ++ case HNBU_USBFLAGS: ++ varbuf_append(&b, vstr_usbflags, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++#ifdef BCM_BOOTLOADER ++ case HNBU_MDIOEX_REGLIST: ++ case HNBU_MDIO_REGLIST: { ++ /* Format: addr (8 bits) | val (16 bits) */ ++ const uint8 msize = 3; ++ char mdiostr[24]; ++ const char *mdiodesc; ++ uint8 *st; ++ ++ mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ? ++ vstr_mdio : vstr_mdioex; ++ ++ ASSERT(((tlen - 1) % msize) == 0); ++ ++ st = &cis[i + 1]; /* start of reg list */ ++ for (j = 0; j < (tlen - 1); j += msize, st += msize) { ++ snprintf(mdiostr, sizeof(mdiostr), ++ mdiodesc, st[0]); ++ varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]); ++ } ++ } ++ break; ++ case HNBU_BRMIN: ++ varbuf_append(&b, vstr_brmin, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_BRMAX: ++ varbuf_append(&b, vstr_brmax, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++#endif /* BCM_BOOTLOADER */ ++ ++ case HNBU_RDLID: ++ varbuf_append(&b, vstr_rdlid, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_GCI_CCR: ++ { ++ /* format: ++ * |0x80 | <== brcm ++ * |len| <== variable, multiple of 5 ++ * |tup| <== tupletype ++ * |ccreg_ix0|<== ix of ccreg [1byte] ++ * |ccreg_val0|<= corr value [4bytes] ++ * --- ++ * Multiple registers are possible. for eg: we ++ * can specify reg_ix3val3 and reg_ix5val5, etc ++ */ ++ char vstr_gci_ccreg_entry[16]; ++ int num_entries = 0; ++ ++ /* retrieve the index-value pairs ++ * from tlen/5; where 5 is ++ * sizeof(ccreg_ix(1)) + ++ * sizeof(ccreg_val(4)). ++ */ ++ num_entries = tlen/5; ++ ++ for (j = 0; j < num_entries; j++) { ++ snprintf(vstr_gci_ccreg_entry, ++ sizeof(vstr_gci_ccreg_entry), ++ "gcr%d=0x%%x", cis[i + (j*5) + 1]); ++ ++ varbuf_append(&b, vstr_gci_ccreg_entry, ++ (cis[i + (j*5) + 5] << 24) | ++ (cis[i + (j*5) + 4] << 16) | ++ (cis[i + (j*5) + 3] << 8) | ++ cis[i + (j*5) + 2]); ++ } ++ } ++ break; ++ ++#ifdef BCM_BOOTLOADER ++ case HNBU_RDLRNDIS: ++ varbuf_append(&b, vstr_rdlrndis, cis[i + 1]); ++ break; ++ ++ case HNBU_RDLRWU: ++ varbuf_append(&b, vstr_rdlrwu, cis[i + 1]); ++ break; ++ ++ case HNBU_RDLSN: ++ if (tlen >= 5) ++ varbuf_append(&b, vstr_rdlsn, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ else ++ varbuf_append(&b, vstr_rdlsn, ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_PMUREGS: ++ { ++ uint8 offset = 1, mode_addr, mode, addr; ++ const char *fmt; ++ ++ do { ++ mode_addr = cis[i+offset]; ++ ++ mode = (mode_addr & PMUREGS_MODE_MASK) ++ >> PMUREGS_MODE_SHIFT; ++ addr = mode_addr & PMUREGS_ADDR_MASK; ++ ++ switch (mode) { ++ case PMU_PLLREG_MODE: ++ fmt = vstr_pllreg; ++ break; ++ case PMU_CCREG_MODE: ++ fmt = vstr_ccreg; ++ break; ++ case PMU_VOLTREG_MODE: ++ fmt = vstr_regctrl; ++ break; ++ case PMU_RES_TIME_MODE: ++ fmt = vstr_time; ++ break; ++ case PMU_RESDEPEND_MODE: ++ fmt = vstr_depreg; ++ break; ++ default: ++ fmt = NULL; ++ break; ++ } ++ ++ if (fmt != NULL) { ++ varbuf_append(&b, fmt, addr, ++ (cis[i + offset + 4] << 24) | ++ (cis[i + offset + 3] << 16) | ++ (cis[i + offset + 2] << 8) | ++ cis[i + offset + 1]); ++ } ++ ++ offset += PMUREGS_TPL_SIZE; ++ } while (offset < tlen); ++ } ++ break; ++ ++ case HNBU_USBREGS: ++ { ++ uint8 offset = 1, usb_reg; ++ const char *fmt; ++ ++ do { ++ usb_reg = cis[i+offset]; ++ ++ switch (usb_reg) { ++ case USB_DEV_CTRL_REG: ++ fmt = vstr_usbdevctrl; ++ break; ++ case HSIC_PHY_CTRL1_REG: ++ fmt = vstr_hsicphyctrl1; ++ break; ++ case HSIC_PHY_CTRL2_REG: ++ fmt = vstr_hsicphyctrl2; ++ break; ++ default: ++ fmt = NULL; ++ break; ++ } ++ ++ if (fmt != NULL) { ++ varbuf_append(&b, fmt, ++ (cis[i + offset + 4] << 24) | ++ (cis[i + offset + 3] << 16) | ++ (cis[i + offset + 2] << 8) | ++ cis[i + offset + 1]); ++ } ++ ++ offset += USBREGS_TPL_SIZE; ++ } while (offset < tlen); ++ } ++ break; ++ ++ case HNBU_USBRDY: ++ /* The first byte of this tuple indicate if the host ++ * needs to be informed about the readiness of ++ * the HSIC/USB for enumeration on which GPIO should ++ * the device assert this event. ++ */ ++ varbuf_append(&b, vstr_usbrdy, cis[i + 1]); ++ ++ /* The following fields in this OTP are optional. ++ * The remaining bytes will indicate the delay required ++ * before and/or after the ch_init(). The delay is defined ++ * using 16-bits of this the MSB(bit15 of 15:0) will be ++ * used indicate if the parameter is for Pre or Post delay. ++ */ ++ for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen; ++ j += 2) { ++ uint16 usb_delay; ++ ++ usb_delay = cis[i + j] | (cis[i + j + 1] << 8); ++ ++ /* The bit-15 of the delay field will indicate the ++ * type of delay (pre or post). ++ */ ++ if (usb_delay & USBRDY_DLY_TYPE) { ++ varbuf_append(&b, vstr_usbpostdly, ++ (usb_delay & USBRDY_DLY_MASK)); ++ } else { ++ varbuf_append(&b, vstr_usbpredly, ++ (usb_delay & USBRDY_DLY_MASK)); ++ } ++ } ++ break; ++ ++ case HNBU_BLDR_TIMEOUT: ++ /* The Delay after USBConnect for timeout till dongle ++ * receives get_descriptor request. ++ */ ++ varbuf_append(&b, vstr_bldr_reset_timeout, ++ (cis[i + 1] | (cis[i + 2] << 8))); ++ break; ++ case HNBU_MUXENAB: ++ varbuf_append(&b, vstr_muxenab, cis[i + 1]); ++ break; ++#else ++ case HNBU_AA: ++ varbuf_append(&b, vstr_aa2g, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_aa5g, cis[i + 2]); ++ break; ++ ++ case HNBU_AG: ++ varbuf_append(&b, vstr_ag, 0, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_ag, 1, cis[i + 2]); ++ if (tlen >= 4) ++ varbuf_append(&b, vstr_ag, 2, cis[i + 3]); ++ if (tlen >= 5) ++ varbuf_append(&b, vstr_ag, 3, cis[i + 4]); ++ ag_init = TRUE; ++ break; ++ ++ case HNBU_ANT5G: ++ varbuf_append(&b, vstr_aa5g, cis[i + 1]); ++ varbuf_append(&b, vstr_ag, 1, cis[i + 2]); ++ break; ++ ++ case HNBU_CC: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_cc, cis[i + 1]); ++ break; ++ ++ case HNBU_PAPARMS: ++ switch (tlen) { ++ case 2: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]); ++ break; ++ case 10: ++ ASSERT(sromrev >= 2); ++ varbuf_append(&b, vstr_opo, cis[i + 9]); ++ /* FALLTHROUGH */ ++ case 9: ++ varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]); ++ /* FALLTHROUGH */ ++ BCMDONGLECASE(8) ++ varbuf_append(&b, vstr_pa0itssit, cis[i + 7]); ++ /* FALLTHROUGH */ ++ BCMDONGLECASE(7) ++ for (j = 0; j < 3; j++) { ++ varbuf_append(&b, vstr_pa0b[j], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ break; ++ default: ++ ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10)); ++ break; ++ } ++ break; ++ ++ case HNBU_PAPARMS5G: ++ ASSERT((sromrev == 2) || (sromrev == 3)); ++ switch (tlen) { ++ case 23: ++ varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]); ++ varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]); ++ varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]); ++ /* FALLTHROUGH */ ++ case 20: ++ varbuf_append(&b, vstr_pa1itssit, cis[i + 19]); ++ /* FALLTHROUGH */ ++ case 19: ++ for (j = 0; j < 3; j++) { ++ varbuf_append(&b, vstr_pa1b[j], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ for (j = 3; j < 6; j++) { ++ varbuf_append(&b, vstr_pa1lob[j - 3], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ for (j = 6; j < 9; j++) { ++ varbuf_append(&b, vstr_pa1hib[j - 6], ++ (cis[i + (j * 2) + 2] << 8) + ++ cis[i + (j * 2) + 1]); ++ } ++ break; ++ default: ++ ASSERT((tlen == 19) || ++ (tlen == 20) || (tlen == 23)); ++ break; ++ } ++ break; ++ ++ case HNBU_OEM: ++ ASSERT(sromrev == 1); ++ varbuf_append(&b, vstr_oem, ++ cis[i + 1], cis[i + 2], ++ cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], ++ cis[i + 7], cis[i + 8]); ++ break; ++ ++ case HNBU_LEDS: ++ for (j = 1; j <= 4; j++) { ++ if (cis[i + j] != 0xff) { ++ varbuf_append(&b, vstr_ledbh, j-1, ++ cis[i + j]); ++ } ++ } ++ break; ++ ++ case HNBU_CCODE: ++ ASSERT(sromrev > 1); ++ if ((cis[i + 1] == 0) || (cis[i + 2] == 0)) ++ varbuf_append(&b, vstr_noccode); ++ else ++ varbuf_append(&b, vstr_ccode, ++ cis[i + 1], cis[i + 2]); ++ varbuf_append(&b, vstr_cctl, cis[i + 3]); ++ break; ++ ++ case HNBU_CCKPO: ++ ASSERT(sromrev > 2); ++ varbuf_append(&b, vstr_cckpo, ++ (cis[i + 2] << 8) | cis[i + 1]); ++ break; ++ ++ case HNBU_OFDMPO: ++ ASSERT(sromrev > 2); ++ varbuf_append(&b, vstr_ofdmpo, ++ (cis[i + 4] << 24) | ++ (cis[i + 3] << 16) | ++ (cis[i + 2] << 8) | ++ cis[i + 1]); ++ break; ++ ++ case HNBU_WPS: ++ varbuf_append(&b, vstr_wpsgpio, cis[i + 1]); ++ if (tlen >= 3) ++ varbuf_append(&b, vstr_wpsled, cis[i + 2]); ++ break; ++ ++ case HNBU_RSSISMBXA2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf); ++ varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf); ++ varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7); ++ varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3); ++ break; ++ ++ case HNBU_RSSISMBXA5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf); ++ varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf); ++ varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7); ++ varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3); ++ break; ++ ++ case HNBU_TRI2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_tri2g, cis[i + 1]); ++ break; ++ ++ case HNBU_TRI5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_tri5gl, cis[i + 1]); ++ varbuf_append(&b, vstr_tri5g, cis[i + 2]); ++ varbuf_append(&b, vstr_tri5gh, cis[i + 3]); ++ break; ++ ++ case HNBU_RXPO2G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rxpo2g, cis[i + 1]); ++ break; ++ ++ case HNBU_RXPO5G: ++ ASSERT(sromrev == 3); ++ varbuf_append(&b, vstr_rxpo5g, cis[i + 1]); ++ break; ++ ++ case HNBU_MACADDR: ++ if (!(ETHER_ISNULLADDR(&cis[i+1])) && ++ !(ETHER_ISMULTI(&cis[i+1]))) { ++ bcm_ether_ntoa((struct ether_addr *)&cis[i + 1], ++ eabuf); ++ ++ /* set boardnum if HNBU_BOARDNUM not seen yet */ ++ if (boardnum == -1) ++ boardnum = (cis[i + 5] << 8) + cis[i + 6]; ++ } ++ break; ++ ++ case HNBU_LEDDC: ++ /* CIS leddc only has 16bits, convert it to 32bits */ ++ w32 = ((cis[i + 2] << 24) | /* oncount */ ++ (cis[i + 1] << 8)); /* offcount */ ++ varbuf_append(&b, vstr_leddc, w32); ++ break; ++ ++ case HNBU_CHAINSWITCH: ++ varbuf_append(&b, vstr_txchain, cis[i + 1]); ++ varbuf_append(&b, vstr_rxchain, cis[i + 2]); ++ varbuf_append(&b, vstr_antswitch, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ break; ++ ++ case HNBU_ELNA2G: ++ varbuf_append(&b, vstr_elna2g, cis[i + 1]); ++ break; ++ ++ case HNBU_ELNA5G: ++ varbuf_append(&b, vstr_elna5g, cis[i + 1]); ++ break; ++ ++ case HNBU_REGREV: ++ varbuf_append(&b, vstr_regrev, cis[i + 1]); ++ break; ++ ++ case HNBU_FEM: { ++ uint16 fem = (cis[i + 2] << 8) + cis[i + 1]; ++ varbuf_append(&b, vstr_antswctl2g, (fem & ++ SROM8_FEM_ANTSWLUT_MASK) >> ++ SROM8_FEM_ANTSWLUT_SHIFT); ++ varbuf_append(&b, vstr_triso2g, (fem & ++ SROM8_FEM_TR_ISO_MASK) >> ++ SROM8_FEM_TR_ISO_SHIFT); ++ varbuf_append(&b, vstr_pdetrange2g, (fem & ++ SROM8_FEM_PDET_RANGE_MASK) >> ++ SROM8_FEM_PDET_RANGE_SHIFT); ++ varbuf_append(&b, vstr_extpagain2g, (fem & ++ SROM8_FEM_EXTPA_GAIN_MASK) >> ++ SROM8_FEM_EXTPA_GAIN_SHIFT); ++ varbuf_append(&b, vstr_tssipos2g, (fem & ++ SROM8_FEM_TSSIPOS_MASK) >> ++ SROM8_FEM_TSSIPOS_SHIFT); ++ if (tlen < 5) break; ++ ++ fem = (cis[i + 4] << 8) + cis[i + 3]; ++ varbuf_append(&b, vstr_antswctl5g, (fem & ++ SROM8_FEM_ANTSWLUT_MASK) >> ++ SROM8_FEM_ANTSWLUT_SHIFT); ++ varbuf_append(&b, vstr_triso5g, (fem & ++ SROM8_FEM_TR_ISO_MASK) >> ++ SROM8_FEM_TR_ISO_SHIFT); ++ varbuf_append(&b, vstr_pdetrange5g, (fem & ++ SROM8_FEM_PDET_RANGE_MASK) >> ++ SROM8_FEM_PDET_RANGE_SHIFT); ++ varbuf_append(&b, vstr_extpagain5g, (fem & ++ SROM8_FEM_EXTPA_GAIN_MASK) >> ++ SROM8_FEM_EXTPA_GAIN_SHIFT); ++ varbuf_append(&b, vstr_tssipos5g, (fem & ++ SROM8_FEM_TSSIPOS_MASK) >> ++ SROM8_FEM_TSSIPOS_SHIFT); ++ break; ++ } ++ ++ case HNBU_PAPARMS_C0: ++ varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]); ++ varbuf_append(&b, vstr_itt2ga0, cis[i + 2]); ++ varbuf_append(&b, vstr_pa, 2, 0, 0, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_pa, 2, 1, 0, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_pa, 2, 2, 0, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ if (tlen < 31) break; ++ ++ varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]); ++ varbuf_append(&b, vstr_itt5ga0, cis[i + 10]); ++ varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]); ++ varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]); ++ varbuf_append(&b, vstr_pa, 5, 0, 0, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_pa, 5, 1, 0, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_pa, 5, 2, 0, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0, ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0, ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0, ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0, ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0, ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0, ++ (cis[i + 30] << 8) + cis[i + 29]); ++ break; ++ ++ case HNBU_PAPARMS_C1: ++ varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]); ++ varbuf_append(&b, vstr_itt2ga1, cis[i + 2]); ++ varbuf_append(&b, vstr_pa, 2, 0, 1, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_pa, 2, 1, 1, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_pa, 2, 2, 1, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ if (tlen < 31) break; ++ ++ varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]); ++ varbuf_append(&b, vstr_itt5ga1, cis[i + 10]); ++ varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]); ++ varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]); ++ varbuf_append(&b, vstr_pa, 5, 0, 1, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_pa, 5, 1, 1, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_pa, 5, 2, 1, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1, ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1, ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1, ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1, ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1, ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1, ++ (cis[i + 30] << 8) + cis[i + 29]); ++ break; ++ ++ case HNBU_PO_CCKOFDM: ++ varbuf_append(&b, vstr_cck2gpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdm2gpo, ++ (cis[i + 6] << 24) + (cis[i + 5] << 16) + ++ (cis[i + 4] << 8) + cis[i + 3]); ++ if (tlen < 19) break; ++ ++ varbuf_append(&b, vstr_ofdm5gpo, ++ (cis[i + 10] << 24) + (cis[i + 9] << 16) + ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_ofdm5glpo, ++ (cis[i + 14] << 24) + (cis[i + 13] << 16) + ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_ofdm5ghpo, ++ (cis[i + 18] << 24) + (cis[i + 17] << 16) + ++ (cis[i + 16] << 8) + cis[i + 15]); ++ break; ++ ++ case HNBU_PO_MCS2G: ++ for (j = 0; j <= (tlen/2); j++) { ++ varbuf_append(&b, vstr_mcspo, 2, j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ break; ++ ++ case HNBU_PO_MCS5GM: ++ for (j = 0; j <= (tlen/2); j++) { ++ varbuf_append(&b, vstr_mcspo, 5, j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ break; ++ ++ case HNBU_PO_MCS5GLH: ++ for (j = 0; j <= (tlen/4); j++) { ++ varbuf_append(&b, vstr_mcspohl, 5, 'l', j, ++ (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); ++ } ++ ++ for (j = 0; j <= (tlen/4); j++) { ++ varbuf_append(&b, vstr_mcspohl, 5, 'h', j, ++ (cis[i + ((tlen/2)+2) + 2*j] << 8) + ++ cis[i + ((tlen/2)+1) + 2*j]); ++ } ++ ++ break; ++ ++ case HNBU_PO_CDD: ++ varbuf_append(&b, vstr_cddpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_STBC: ++ varbuf_append(&b, vstr_stbcpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_40M: ++ varbuf_append(&b, vstr_bw40po, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_PO_40MDUP: ++ varbuf_append(&b, vstr_bwduppo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_OFDMPO5G: ++ varbuf_append(&b, vstr_ofdm5gpo, ++ (cis[i + 4] << 24) + (cis[i + 3] << 16) + ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdm5glpo, ++ (cis[i + 8] << 24) + (cis[i + 7] << 16) + ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_ofdm5ghpo, ++ (cis[i + 12] << 24) + (cis[i + 11] << 16) + ++ (cis[i + 10] << 8) + cis[i + 9]); ++ break; ++ /* Power per rate for SROM V9 */ ++ case HNBU_CCKBW202GPO: ++ varbuf_append(&b, vstr_cckbw202gpo[0], ++ ((cis[i + 2] << 8) + cis[i + 1])); ++ if (tlen > 4) ++ varbuf_append(&b, vstr_cckbw202gpo[1], ++ ((cis[i + 4] << 8) + cis[i + 3])); ++ break; ++ ++ case HNBU_LEGOFDMBW202GPO: ++ varbuf_append(&b, vstr_legofdmbw202gpo[0], ++ ((cis[i + 4] << 24) + (cis[i + 3] << 16) + ++ (cis[i + 2] << 8) + cis[i + 1])); ++ if (tlen > 6) { ++ varbuf_append(&b, vstr_legofdmbw202gpo[1], ++ ((cis[i + 8] << 24) + (cis[i + 7] << 16) + ++ (cis[i + 6] << 8) + cis[i + 5])); ++ } ++ break; ++ ++ case HNBU_LEGOFDMBW205GPO: ++ for (j = 0; j < 6; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_legofdmbw205gpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS2GPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs2gpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GLPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5glpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GMPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5gmpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS5GHPO: ++ for (j = 0; j < 3; j++) { ++ if (tlen < (2 + 4 * j)) ++ break; ++ varbuf_append(&b, vstr_mcs5ghpo[j], ++ ((cis[4 * j + i + 4] << 24) ++ + (cis[4 * j + i + 3] << 16) ++ + (cis[4 * j + i + 2] << 8) ++ + cis[4 * j + i + 1])); ++ } ++ break; ++ ++ case HNBU_MCS32PO: ++ varbuf_append(&b, vstr_mcs32po, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_LEG40DUPPO: ++ varbuf_append(&b, vstr_legofdm40duppo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ break; ++ ++ case HNBU_CUSTOM1: ++ varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) + ++ (cis[i + 3] << 16) + (cis[i + 2] << 8) + ++ cis[i + 1])); ++ break; ++ ++#if defined(BCMCCISSR3) ++ case HNBU_SROM3SWRGN: ++ if (tlen >= 73) { ++ uint16 srom[35]; ++ uint8 srev = cis[i + 1 + 70]; ++ ASSERT(srev == 3); ++ /* make tuple value 16-bit aligned and parse it */ ++ bcopy(&cis[i + 1], srom, sizeof(srom)); ++ _initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b); ++ /* 2.4G antenna gain is included in SROM */ ++ ag_init = TRUE; ++ /* Ethernet MAC address is included in SROM */ ++ eabuf[0] = 0; ++ boardnum = -1; ++ } ++ /* create extra variables */ ++ if (tlen >= 75) ++ varbuf_append(&b, vstr_vendid, ++ (cis[i + 1 + 73] << 8) + ++ cis[i + 1 + 72]); ++ if (tlen >= 77) ++ varbuf_append(&b, vstr_devid, ++ (cis[i + 1 + 75] << 8) + ++ cis[i + 1 + 74]); ++ if (tlen >= 79) ++ varbuf_append(&b, vstr_xtalfreq, ++ (cis[i + 1 + 77] << 8) + ++ cis[i + 1 + 76]); ++ break; ++#endif ++ ++ case HNBU_CCKFILTTYPE: ++ varbuf_append(&b, vstr_cckdigfilttype, ++ (cis[i + 1])); ++ break; ++ ++ case HNBU_TEMPTHRESH: ++ varbuf_append(&b, vstr_tempthresh, ++ (cis[i + 1])); ++ /* period in msb nibble */ ++ varbuf_append(&b, vstr_temps_period, ++ (cis[i + 2] >> 4)); ++ /* hysterisis in lsb nibble */ ++ varbuf_append(&b, vstr_temp_hysteresis, ++ (cis[i + 2] & 0xF)); ++ if (tlen >= 4) ++ varbuf_append(&b, vstr_tempoffset, ++ (cis[i + 3])); ++ if (tlen >= 5) { ++ varbuf_append(&b, vstr_temp_corrx, ++ (cis[i + 4] >> 2)); ++ varbuf_append(&b, vstr_tempsense_option, ++ (cis[i + 4] & 0x3)); ++ } ++ if (tlen >= 6) ++ varbuf_append(&b, vstr_phycal_tempdelta, ++ (cis[i + 5])); ++ break; ++ ++ case HNBU_FEM_CFG: ++ /* fem_cfg1 */ ++ varbuf_append(&b, vstr_tssiposslopeg, 2, ++ (cis[i + 1] & 0x1)); ++ varbuf_append(&b, vstr_epagaing, 2, ++ (cis[i + 1] & 0xe) >> 1); ++ varbuf_append(&b, vstr_pdgaing, 2, ++ ((cis[i + 2] & 0x1) << 8) + ++ ((cis[i + 1] & 0xf0) >> 4)); ++ varbuf_append(&b, vstr_tworangetssi, 2, ++ (cis[i + 2] & 0x2) >> 1); ++ varbuf_append(&b, vstr_papdcap, 2, ++ (cis[i + 2] & 0x4) >> 2); ++ varbuf_append(&b, vstr_femctrl, ++ (cis[i + 2] & 0xf8) >> 3); ++ /* fem_cfg2 */ ++ varbuf_append(&b, vstr_tssiposslopeg, 5, ++ (cis[i + 3] & 0x1)); ++ varbuf_append(&b, vstr_epagaing, 5, ++ (cis[i + 3] & 0xe) >> 1); ++ varbuf_append(&b, vstr_pdgaing, 5, ++ ((cis[i + 4] & 0x1) << 8) + ++ ((cis[i + 3] & 0xf0) >> 4)); ++ varbuf_append(&b, vstr_tworangetssi, 2, ++ (cis[i + 4] & 0x2) >> 1); ++ varbuf_append(&b, vstr_papdcap, 5, ++ (cis[i + 4] & 0x4) >> 2); ++ varbuf_append(&b, vstr_gainctrlsph, ++ (cis[i + 4] & 0xf8) >> 3); ++ break; ++ ++ case HNBU_ACPA_C0: ++ { ++ const int a = 0; ++ ++ varbuf_append(&b, vstr_subband5gver, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7], ++ (cis[i + 10] << 8) + cis[i + 9]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 11] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 11] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 11] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 12] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 12] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 12] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 13], ++ cis[i + 14], ++ cis[i + 15], ++ cis[i + 16]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37], ++ (cis[i + 40] << 8) + cis[i + 39]); ++ break; ++ } ++ ++ case HNBU_ACPA_C1: ++ { ++ const int a = 1; ++ ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 9] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 9] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 9] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 10] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 10] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 10] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 11], ++ cis[i + 12], ++ cis[i + 13], ++ cis[i + 14]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 16] << 8) + cis[i + 15], ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37]); ++ break; ++ } ++ ++ case HNBU_ACPA_C2: ++ { ++ const int a = 2; ++ ++ varbuf_append(&b, vstr_maxp2ga, a, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ /* pa2g */ ++ varbuf_append(&b, vstr_pa2ga, 2, a, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7]); ++ /* rxgains */ ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, ++ cis[i + 9] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, ++ (cis[i + 9] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, ++ (cis[i + 9] & 0x80) >> 7); ++ varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, ++ cis[i + 10] & 0x7); ++ varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, ++ (cis[i + 10] & 0x78) >> 3); ++ varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, ++ (cis[i + 10] & 0x80) >> 7); ++ /* maxp5g */ ++ varbuf_append(&b, vstr_maxp5ga, a, ++ cis[i + 11], ++ cis[i + 12], ++ cis[i + 13], ++ cis[i + 14]); ++ /* pa5g */ ++ varbuf_append(&b, vstr_pa5ga, a, ++ (cis[i + 16] << 8) + cis[i + 15], ++ (cis[i + 18] << 8) + cis[i + 17], ++ (cis[i + 20] << 8) + cis[i + 19], ++ (cis[i + 22] << 8) + cis[i + 21], ++ (cis[i + 24] << 8) + cis[i + 23], ++ (cis[i + 26] << 8) + cis[i + 25], ++ (cis[i + 28] << 8) + cis[i + 27], ++ (cis[i + 30] << 8) + cis[i + 29], ++ (cis[i + 32] << 8) + cis[i + 31], ++ (cis[i + 34] << 8) + cis[i + 33], ++ (cis[i + 36] << 8) + cis[i + 35], ++ (cis[i + 38] << 8) + cis[i + 37]); ++ break; ++ } ++ ++ case HNBU_MEAS_PWR: ++ varbuf_append(&b, vstr_measpower, cis[i + 1]); ++ varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2])); ++ varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3])); ++ varbuf_append(&b, vstr_rawtempsense, ++ ((cis[i + 5] & 0x1) << 8) + cis[i + 4]); ++ break; ++ ++ case HNBU_ACPPR_2GPO: ++ varbuf_append(&b, vstr_dot11agofdmhrbw202gpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_ofdmlrbw202gpo, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ break; ++ ++ case HNBU_ACPPR_5GPO: ++ varbuf_append(&b, vstr_mcsbw805glpo, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_mcsbw1605glpo, ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_mcsbw805gmpo, ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_mcsbw1605gmpo, ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_mcsbw805ghpo, ++ (cis[i + 10] << 8) + cis[i + 9]); ++ varbuf_append(&b, vstr_mcsbw1605ghpo, ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_mcslr5rlpo, ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_mcslr5gmpo, ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_mcslr5ghpo, ++ (cis[i + 18] << 8) + cis[i + 17]); ++ break; ++ ++ case HNBU_ACPPR_SBPO: ++ varbuf_append(&b, vstr_sb20in40rrpo, 'h', ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l', ++ (cis[i + 4] << 8) + cis[i + 3]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l', ++ (cis[i + 6] << 8) + cis[i + 5]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm', ++ (cis[i + 8] << 8) + cis[i + 7]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm', ++ (cis[i + 10] << 8) + cis[i + 9]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h', ++ (cis[i + 12] << 8) + cis[i + 11]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h', ++ (cis[i + 14] << 8) + cis[i + 13]); ++ varbuf_append(&b, vstr_sb20in40rrpo, 'l', ++ (cis[i + 16] << 8) + cis[i + 15]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l', ++ (cis[i + 18] << 8) + cis[i + 17]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l', ++ (cis[i + 20] << 8) + cis[i + 19]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm', ++ (cis[i + 22] << 8) + cis[i + 21]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm', ++ (cis[i + 24] << 8) + cis[i + 23]); ++ varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h', ++ (cis[i + 26] << 8) + cis[i + 25]); ++ varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h', ++ (cis[i + 28] << 8) + cis[i + 27]); ++ varbuf_append(&b, vstr_dot11agduprpo, 'h', ++ (cis[i + 30] << 8) + cis[i + 24]); ++ varbuf_append(&b, vstr_dot11agduprpo, 'l', ++ (cis[i + 32] << 8) + cis[i + 26]); ++ break; ++ ++ case HNBU_NOISELVL: ++ /* noiselvl2g */ ++ varbuf_append(&b, vstr_noiselvl2ga, 0, ++ (cis[i + 1] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl2ga, 1, ++ ((cis[i + 2] & 0x3) << 4) + ++ ((cis[i + 1] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl2ga, 2, ++ (cis[i + 2] & 0x7c) >> 2); ++ /* noiselvl5gl */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 0, ++ (cis[i + 3] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 1, ++ ((cis[i + 4] & 0x3) << 4) + ++ ((cis[i + 3] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'l', 2, ++ (cis[i + 4] & 0x7c) >> 2); ++ /* noiselvl5gm */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 0, ++ (cis[i + 5] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 1, ++ ((cis[i + 6] & 0x3) << 4) + ++ ((cis[i + 5] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'm', 2, ++ (cis[i + 6] & 0x7c) >> 2); ++ /* noiselvl5gh */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 0, ++ (cis[i + 7] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 1, ++ ((cis[i + 8] & 0x3) << 4) + ++ ((cis[i + 7] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'h', 2, ++ (cis[i + 8] & 0x7c) >> 2); ++ /* noiselvl5gu */ ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 0, ++ (cis[i + 9] & 0x1f)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 1, ++ ((cis[i + 10] & 0x3) << 4) + ++ ((cis[i + 9] & 0xe0) >> 4)); ++ varbuf_append(&b, vstr_noiselvl5ga, 'u', 2, ++ (cis[i + 10] & 0x7c) >> 2); ++ break; ++ ++ case HNBU_RXGAIN_ERR: ++ varbuf_append(&b, vstr_rxgainerr2g, ++ (cis[i + 2] << 8) + cis[i + 1]); ++ varbuf_append(&b, vstr_rxgainerr5g, ++ (cis[i + 4] << 8) + cis[i + 3], ++ (cis[i + 6] << 8) + cis[i + 5], ++ (cis[i + 8] << 8) + cis[i + 7], ++ (cis[i + 10] << 8) + cis[i + 9]); ++ break; ++ ++ case HNBU_AGBGA: ++ varbuf_append(&b, vstr_agbg, 0, cis[i + 1]); ++ varbuf_append(&b, vstr_agbg, 1, cis[i + 2]); ++ varbuf_append(&b, vstr_agbg, 2, cis[i + 3]); ++ varbuf_append(&b, vstr_aga, 3, cis[i + 4]); ++ varbuf_append(&b, vstr_aga, 4, cis[i + 5]); ++ varbuf_append(&b, vstr_aga, 5, cis[i + 6]); ++ break; ++ ++ case HNBU_UUID: ++ { ++ /* uuid format 12345678-1234-5678-1234-567812345678 */ ++ ++ char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */ ++ ++ snprintf(uuidstr, sizeof(uuidstr), ++ "%02X%02X%02X%02X-%02X%02X-%02X%02X-" ++ "%02X%02X-%02X%02X%02X%02X%02X%02X", ++ cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4], ++ cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8], ++ cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12], ++ cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]); ++ ++ varbuf_append(&b, vstr_uuid, uuidstr); ++ break; ++ ++ } ++#endif /* !BCM_BOOTLOADER */ ++ } ++ ++ break; ++ } ++ i += tlen; ++ } while (tup != CISTPL_END); ++ } ++ ++ if (boardnum != -1) { ++ varbuf_append(&b, vstr_boardnum, boardnum); ++ } ++ ++ if (eabuf[0]) { ++ varbuf_append(&b, vstr_macaddr, eabuf); ++ } ++ ++#ifndef BCM_BOOTLOADER ++ /* if there is no antenna gain field, set default */ ++ if (getvar(NULL, "ag0") == NULL && ag_init == FALSE) { ++ varbuf_append(&b, vstr_ag, 0, 0xff); ++ } ++#endif ++ ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ varbuf_append(&b, vstr_end, NULL); ++#endif /* BCMUSBDEV_BMAC */ ++ ++ /* final nullbyte terminator */ ++ ASSERT(b.size >= 1); ++ *b.buf++ = '\0'; ++ ++ ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS); ++ err = initvars_table(osh, base, b.buf, vars, count); ++ ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ return err; ++} ++ ++/* set PCMCIA sprom command register */ ++static int ++sprom_cmd_pcmcia(osl_t *osh, uint8 cmd) ++{ ++ uint8 status = 0; ++ uint wait_cnt = 1000; ++ ++ /* write sprom command register */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1); ++ ++ /* wait status */ ++ while (wait_cnt--) { ++ OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1); ++ if (status & SROM_DONE) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/* read a word from the PCMCIA srom */ ++static int ++sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); ++ ++ /* do read */ ++ if (sprom_cmd_pcmcia(osh, SROM_READ)) ++ return 1; ++ ++ /* read data */ ++ data_h = data_l = 0; ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ *data = (data_h << 8) | data_l; ++ return 0; ++} ++ ++#if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG) ++/* write a word to the PCMCIA srom */ ++static int ++sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data) ++{ ++ uint8 addr_l, addr_h, data_l, data_h; ++ ++ addr_l = (uint8)((addr * 2) & 0xff); ++ addr_h = (uint8)(((addr * 2) >> 8) & 0xff); ++ data_l = (uint8)(data & 0xff); ++ data_h = (uint8)((data >> 8) & 0xff); ++ ++ /* set address */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1); ++ ++ /* write data */ ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1); ++ OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1); ++ ++ /* do write */ ++ return sprom_cmd_pcmcia(osh, SROM_WRITE); ++} ++#endif ++ ++/* In chips with chipcommon rev 32 and later, the srom is in chipcommon, ++ * not in the bus cores. ++ */ ++static uint16 ++srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, uint16 data) ++{ ++ chipcregs_t *cc = (chipcregs_t *)ccregs; ++ uint wait_cnt = 1000; ++ ++ if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) { ++ W_REG(osh, &cc->sromaddress, wordoff * 2); ++ if (cmd == SRC_OP_WRITE) ++ W_REG(osh, &cc->sromdata, data); ++ } ++ ++ W_REG(osh, &cc->sromcontrol, SRC_START | cmd); ++ ++ while (wait_cnt--) { ++ if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0) ++ break; ++ } ++ ++ if (!wait_cnt) { ++ BS_ERROR(("%s: Command 0x%x timed out\n", __FUNCTION__, cmd)); ++ return 0xffff; ++ } ++ if (cmd == SRC_OP_READ) ++ return (uint16)R_REG(osh, &cc->sromdata); ++ else ++ return 0xffff; ++} ++ ++/* ++ * Read in and validate sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, ++ bool check_crc) ++{ ++ int err = 0; ++ uint i; ++ void *ccregs = NULL; ++ uint32 ccval = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ /* save current control setting */ ++ ccval = si_chipcontrl_read(sih); ++ } ++ ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID)) { ++ /* Disable Ext PA lines to allow reading from SROM */ ++ si_chipcontrl_epa4331(sih, FALSE); ++ } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ si_chipcontrl_srom4360(sih, TRUE); ++ } ++ ++ /* read the sprom */ ++ for (i = 0; i < nwords; i++) { ++ ++ if (sih->ccrev > 31 && ISSIM_ENAB(sih)) { ++ /* use indirect since direct is too slow on QT */ ++ if ((sih->cccaps & CC_CAP_SROM) == 0) { ++ err = 1; ++ goto error; ++ } ++ ++ ccregs = (void *)((uint8 *)sprom - CC_SROM_OTP); ++ buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0); ++ ++ } else { ++ if (ISSIM_ENAB(sih)) ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); ++ ++ buf[i] = R_REG(osh, &sprom[wordoff + i]); ++ } ++ ++ } ++ ++ /* bypass crc checking for simulation to allow srom hack */ ++ if (ISSIM_ENAB(sih)) { ++ goto error; ++ } ++ ++ if (check_crc) { ++ ++ if (buf[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0])); ++ err = 1; ++ goto error; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, nwords * 2); ++ if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ /* DBG only pci always read srom4 first, then srom8/9 */ ++ /* BS_ERROR(("%s: bad crc\n", __FUNCTION__)); */ ++ err = 1; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, nwords * 2); ++ } ++ ++error: ++ if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4360_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43460_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { ++ ++ /* Restore config after reading SROM */ ++ si_chipcontrl_restore(sih, ccval); ++ } ++ ++ return err; ++} ++ ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++static int ++otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz) ++{ ++ uint8 *otp; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int err = 0; ++ ++ ASSERT(bufsz <= OTP_SZ_MAX); ++ ++ if ((otp = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return BCME_ERROR; ++ } ++ ++ bzero(otp, OTP_SZ_MAX); ++ ++ err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz); ++ ++ if (err) { ++ MFREE(osh, otp, OTP_SZ_MAX); ++ return err; ++ } ++ ++ bcopy(otp, buf, bufsz); ++ ++ MFREE(osh, otp, OTP_SZ_MAX); ++ ++ /* Check CRC */ ++ if (buf[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0])); ++ return 1; ++ } ++ ++ /* fixup the endianness so crc8 will pass */ ++ htol16_buf(buf, bufsz); ++ if (hndcrc8((uint8 *)buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && ++ hndcrc8((uint8 *)buf, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { ++ BS_ERROR(("%s: bad crc\n", __FUNCTION__)); ++ err = 1; ++ } ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf, bufsz); ++ ++ return err; ++} ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++ ++#if defined(WLTEST) || defined(BCMDBG) ++int ++srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write) ++{ ++ int err = 0, crc = 0; ++ uint8 *buf8; ++ ++ /* Check nbytes is not odd or too big */ ++ if ((nbytes & 1) || (nbytes > SROM_MAX)) ++ return 1; ++ ++ /* block invalid buffer size */ ++ if (nbytes < SROM4_WORDS * 2) ++ return BCME_BUFTOOSHORT; ++ else if (nbytes > SROM10_WORDS * 2) ++ return BCME_BUFTOOLONG; ++ ++ /* Verify signatures */ ++ if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) || ++ (buf16[SROM8_SIGN] == SROM4_SIGNATURE) || ++ (buf16[SROM10_SIGN] == SROM4_SIGNATURE))) { ++ BS_ERROR(("%s: wrong signature SROM4_SIGN %x SROM8_SIGN %x SROM10_SIGN %x\n", ++ __FUNCTION__, buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN])); ++ return BCME_ERROR; ++ } ++ ++ /* Check CRC */ ++ if (buf16[0] == 0xffff) { ++ /* The hardware thinks that an srom that starts with 0xffff ++ * is blank, regardless of the rest of the content, so declare ++ * it bad. ++ */ ++ BS_ERROR(("%s: invalid buf16[0] = 0x%x\n", __FUNCTION__, buf16[0])); ++ goto out; ++ } ++ ++ buf8 = (uint8*)buf16; ++ /* fixup the endianness and then calculate crc */ ++ htol16_buf(buf8, nbytes); ++ crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE); ++ /* now correct the endianness of the byte array */ ++ ltoh16_buf(buf8, nbytes); ++ if (nbytes == SROM10_WORDS * 2) ++ buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff); ++ else ++ buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff); ++ ++#ifdef BCMNVRAMW ++ /* Write the CRC back */ ++ if (write) ++ err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2); ++#endif /* BCMNVRAMW */ ++ ++out: ++ return write ? err : crc; ++} ++#endif ++ ++/* ++* Create variable table from memory. ++* Return 0 on success, nonzero on error. ++*/ ++static int ++BCMATTACHFN(initvars_table)(osl_t *osh, char *start, char *end, char **vars, uint *count) ++{ ++ int c = (int)(end - start); ++ ++ /* do it only when there is more than just the null string */ ++ if (c > 1) { ++ char *vp = MALLOC(osh, c); ++ ASSERT(vp != NULL); ++ if (!vp) ++ return BCME_NOMEM; ++ bcopy(start, vp, c); ++ *vars = vp; ++ *count = c; ++ } ++ else { ++ *vars = NULL; ++ *count = 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Find variables with from flash. 'base' points to the beginning ++ * of the table upon enter and to the end of the table upon exit when success. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len) ++{ ++ char *vp = *base; ++ char *flash; ++ int err; ++ char *s; ++ uint l, dl, copy_len; ++ char devpath[SI_DEVPATH_BUFSZ]; ++ char coded_name[SI_DEVPATH_BUFSZ] = {0}; ++ int path_len, coded_len, devid_len; ++ ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) ++ return BCME_NOMEM; ++ if ((err = nvram_getall(flash, NVRAM_SPACE))) ++ goto exit; ++ ++ /* create legacy devpath prefix */ ++ si_devpath(sih, devpath, sizeof(devpath)); ++ path_len = strlen(devpath); ++ ++ /* create coded devpath prefix */ ++ si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid"); ++ ++ /* coded_name now is 'xx:devid, eat ending 'devid' */ ++ /* to be 'xx:' */ ++ devid_len = strlen("devid"); ++ coded_len = strlen(coded_name); ++ if (coded_len > devid_len) { ++ coded_name[coded_len - devid_len] = '\0'; ++ coded_len -= devid_len; ++ } ++ else ++ coded_len = 0; ++ ++ /* grab vars with the prefix or previx in name */ ++ for (s = flash; s && *s; s += l + 1) { ++ l = strlen(s); ++ ++ /* skip non-matching variable */ ++ if (strncmp(s, devpath, path_len) == 0) ++ dl = path_len; ++ else if (coded_len && strncmp(s, coded_name, coded_len) == 0) ++ dl = coded_len; ++ else ++ continue; ++ ++ /* is there enough room to copy? */ ++ copy_len = l - dl + 1; ++ if (len < copy_len) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ ++ /* no prefix, just the name=value */ ++ strncpy(vp, &s[dl], copy_len); ++ vp += copy_len; ++ len -= copy_len; ++ } ++ ++ /* add null string as terminator */ ++ if (len < 1) { ++ err = BCME_BUFTOOSHORT; ++ goto exit; ++ } ++ *vp++ = '\0'; ++ ++ *base = vp; ++ ++exit: MFREE(osh, flash, NVRAM_SPACE); ++ return err; ++} ++ ++#if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) ++/* ++ * Initialize nonvolatile variable table from flash. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count) ++{ ++ osl_t *osh = si_osh(sih); ++ char *vp, *base; ++ int err; ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(vp != NULL); ++ if (!vp) ++ return BCME_NOMEM; ++ ++ if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0) ++ err = initvars_table(osh, base, vp, vars, count); ++ ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ ++ return err; ++} ++#endif ++ ++/* Parse SROM and create name=value pairs. 'srom' points to ++ * the SROM word array. 'off' specifies the offset of the ++ * first word 'srom' points to, which should be either 0 or ++ * SROM3_SWRG_OFF (full SROM or software region). ++ */ ++ ++static uint ++mask_shift(uint16 mask) ++{ ++ uint i; ++ for (i = 0; i < (sizeof(mask) << 3); i ++) { ++ if (mask & (1 << i)) ++ return i; ++ } ++ ASSERT(mask); ++ return 0; ++} ++ ++static uint ++mask_width(uint16 mask) ++{ ++ int i; ++ for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) { ++ if (mask & (1 << i)) ++ return (uint)(i - mask_shift(mask) + 1); ++ } ++ ASSERT(mask); ++ return 0; ++} ++ ++#ifdef BCMASSERT_SUPPORT ++static bool ++mask_valid(uint16 mask) ++{ ++ uint shift = mask_shift(mask); ++ uint width = mask_width(mask); ++ return mask == ((~0 << shift) & ~(~0 << (shift + width))); ++} ++#endif ++ ++static void ++BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b) ++{ ++ uint16 w; ++ uint32 val; ++ const sromvar_t *srv; ++ uint width; ++ uint flags; ++ uint32 sr = (1 << sromrev); ++ bool in_array = FALSE; ++ static char array_temp[256]; ++ uint array_curr = 0; ++ const char* array_name = NULL; ++ ++ varbuf_append(b, "sromrev=%d", sromrev); ++ ++ for (srv = pci_sromvars; srv->name != NULL; srv ++) { ++ const char *name; ++ static bool in_array = FALSE; ++ static char array_temp[256]; ++ static uint array_curr = 0; ++ static const char* array_name = NULL; ++ ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (srv->off < off) ++ continue; ++ ++ flags = srv->flags; ++ name = srv->name; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (flags & SRFL_NOVAR) ++ continue; ++ ++ if (flags & SRFL_ETHADDR) { ++ char eabuf[ETHER_ADDR_STR_LEN]; ++ struct ether_addr ea; ++ ++ ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff; ++ ea.octet[1] = srom[srv->off - off] & 0xff; ++ ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff; ++ ea.octet[3] = srom[srv->off + 1 - off] & 0xff; ++ ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff; ++ ea.octet[5] = srom[srv->off + 2 - off] & 0xff; ++ bcm_ether_ntoa(&ea, eabuf); ++ ++ varbuf_append(b, "%s=%s", name, eabuf); ++ } ++ else { ++ ASSERT(mask_valid(srv->mask)); ++ ASSERT(mask_width(srv->mask)); ++ ++ /* Start of an array */ ++ if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { ++ array_curr = 0; ++ array_name = (const char*)srv->name; ++ memset((void*)array_temp, 0, sizeof(array_temp)); ++ in_array = TRUE; ++ } ++ ++ w = srom[srv->off - off]; ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ while (srv->flags & SRFL_MORE) { ++ srv ++; ++ ASSERT(srv->name != NULL); ++ ++ if (srv->off == 0 || srv->off < off) ++ continue; ++ ++ ASSERT(mask_valid(srv->mask)); ++ ASSERT(mask_width(srv->mask)); ++ ++ w = srom[srv->off - off]; ++ val += ((w & srv->mask) >> mask_shift(srv->mask)) << width; ++ width += mask_width(srv->mask); ++ } ++ ++ if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ /* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */ ++ if (sromrev <= 9 && srv->flags & SRFL_ARRAY) { ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ } ++ ++ if (in_array) { ++ int ret; ++ ++ if (flags & SRFL_PRHEX) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "0x%x,", val); ++ } else if ((flags & SRFL_PRSIGN) && ++ (val & (1 << (width - 1)))) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%d,", ++ (int)(val | (~0 << width))); ++ } else { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%u,", val); ++ } ++ ++ if (ret > 0) { ++ array_curr += ret; ++ } else { ++ BS_ERROR(("%s: array %s parsing error. buffer too short.\n", ++ __FUNCTION__, array_name)); ++ ASSERT(0); ++ ++ /* buffer too small, skip this param */ ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ in_array = FALSE; ++ continue; ++ } ++ ++ if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ ++ /* Remove the last ',' */ ++ array_temp[array_curr-1] = '\0'; ++ in_array = FALSE; ++ varbuf_append(b, "%s=%s", array_name, array_temp); ++ } ++ } else if (flags & SRFL_CCODE) { ++ if (val == 0) ++ varbuf_append(b, "ccode="); ++ else ++ varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff)); ++ } ++ /* LED Powersave duty cycle has to be scaled: ++ *(oncount >> 24) (offcount >> 8) ++ */ ++ else if (flags & SRFL_LEDDC) { ++ uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */ ++ (((val & 0xff)) << 8); /* offcount */ ++ varbuf_append(b, "leddc=%d", w32); ++ } ++ else if (flags & SRFL_PRHEX) ++ varbuf_append(b, "%s=0x%x", name, val); ++ else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) ++ varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width))); ++ else ++ varbuf_append(b, "%s=%u", name, val); ++ } ++ } ++ ++ if (sromrev >= 4) { ++ /* Do per-path variables */ ++ uint p, pb, psz, path_num; ++ ++ if (sromrev >= 11) { ++ pb = SROM11_PATH0; ++ psz = SROM11_PATH1 - SROM11_PATH0; ++ path_num = MAX_PATH_SROM_11; ++ } else if (sromrev >= 8) { ++ pb = SROM8_PATH0; ++ psz = SROM8_PATH1 - SROM8_PATH0; ++ path_num = MAX_PATH_SROM; ++ } else { ++ pb = SROM4_PATH0; ++ psz = SROM4_PATH1 - SROM4_PATH0; ++ path_num = MAX_PATH_SROM; ++ } ++ ++ for (p = 0; p < path_num; p++) { ++ for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) { ++ if ((srv->revmask & sr) == 0) ++ continue; ++ ++ if (pb + srv->off < off) ++ continue; ++ ++ /* This entry is for mfgc only. Don't generate param for it, */ ++ if (srv->flags & SRFL_NOVAR) ++ continue; ++ ++ /* Start of an array */ ++ if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { ++ array_curr = 0; ++ array_name = (const char*)srv->name; ++ memset((void*)array_temp, 0, sizeof(array_temp)); ++ in_array = TRUE; ++ } ++ ++ w = srom[pb + srv->off - off]; ++ ++ ASSERT(mask_valid(srv->mask)); ++ val = (w & srv->mask) >> mask_shift(srv->mask); ++ width = mask_width(srv->mask); ++ ++ flags = srv->flags; ++ ++ /* Cheating: no per-path var is more than 1 word */ ++ ++ if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) ++ continue; ++ ++ if (in_array) { ++ int ret; ++ ++ if (flags & SRFL_PRHEX) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "0x%x,", val); ++ } else if ((flags & SRFL_PRSIGN) && ++ (val & (1 << (width - 1)))) { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%d,", ++ (int)(val | (~0 << width))); ++ } else { ++ ret = snprintf(array_temp + array_curr, ++ sizeof(array_temp) - array_curr, "%u,", val); ++ } ++ ++ if (ret > 0) { ++ array_curr += ret; ++ } else { ++ BS_ERROR( ++ ("%s: array %s parsing error. buffer too short.\n", ++ __FUNCTION__, array_name)); ++ ASSERT(0); ++ ++ /* buffer too small, skip this param */ ++ while (srv->flags & SRFL_ARRAY) ++ srv ++; ++ srv ++; ++ in_array = FALSE; ++ continue; ++ } ++ ++ if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ ++ /* Remove the last ',' */ ++ array_temp[array_curr-1] = '\0'; ++ in_array = FALSE; ++ varbuf_append(b, "%s%d=%s", ++ array_name, p, array_temp); ++ } ++ } else if (srv->flags & SRFL_PRHEX) ++ varbuf_append(b, "%s%d=0x%x", srv->name, p, val); ++ else ++ varbuf_append(b, "%s%d=%d", srv->name, p, val); ++ } ++ pb += psz; ++ } ++ } ++} ++ ++/* ++ * Initialize nonvolatile variable table from sprom. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_srom_pci)(si_t *sih, void *curmap, char **vars, uint *count) ++{ ++ uint16 *srom, *sromwindow; ++ uint8 sromrev = 0; ++ uint32 sr; ++ varbuf_t b; ++ char *vp, *base = NULL; ++ osl_t *osh = si_osh(sih); ++ bool flash = FALSE; ++ int err = 0; ++ ++ /* ++ * Apply CRC over SROM content regardless SROM is present or not, ++ * and use variable sromrev's existance in flash to decide ++ * if we should return an error when CRC fails or read SROM variables ++ * from flash. ++ */ ++ srom = MALLOC(osh, SROM_MAX); ++ ASSERT(srom != NULL); ++ if (!srom) ++ return -2; ++ ++ sromwindow = (uint16 *)SROM_OFFSET(sih); ++ if (si_is_sprom_available(sih)) { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM11_WORDS, TRUE); ++ ++ if (err == 0) { ++ if (srom[SROM11_SIGN] == SROM11_SIGNATURE) /* srom 11 */ ++ sromrev = srom[SROM11_CRCREV] & 0xff; ++ } else { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM4_WORDS, TRUE); ++ ++ if (err == 0) { ++ if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4 */ ++ (srom[SROM8_SIGN] == SROM4_SIGNATURE) ) { /* srom 8, 9 */ ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++ } else { ++ err = sprom_read_pci(osh, sih, sromwindow, 0, ++ srom, SROM_WORDS, TRUE); ++ ++ if (err == 0) { ++ /* srom is good and is rev < 4 */ ++ /* top word of sprom contains version and crc8 */ ++ sromrev = srom[SROM_CRCREV] & 0xff; ++ /* bcm4401 sroms misprogrammed */ ++ if (sromrev == 0x10) ++ sromrev = 1; ++ } ++ } ++ } ++ } ++ ++#if defined(BCMNVRAMW) || defined(BCMNVRAMR) ++ /* Use OTP if SPROM not available */ ++ else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) { ++ /* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */ ++ if (srom[SROM11_SIGN] == SROM11_SIGNATURE) ++ sromrev = srom[SROM11_CRCREV] & 0xff; ++ else if (srom[SROM10_SIGN] == SROM10_SIGNATURE) ++ sromrev = srom[SROM10_CRCREV] & 0xff; ++ else ++ sromrev = srom[SROM4_CRCREV] & 0xff; ++ } ++#endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ ++ else { ++ err = 1; ++ BS_ERROR(("Neither SPROM nor OTP has valid image\n")); ++ } ++ ++ BS_ERROR(("srom rev:%d\n", sromrev)); ++ ++ ++ /* We want internal/wltest driver to come up with default sromvars so we can ++ * program a blank SPROM/OTP. ++ */ ++ if (err) { ++ char *value; ++ uint32 val; ++ val = 0; ++ BCM_REFERENCE(val); ++ ++ if ((value = si_getdevpathvar(sih, "sromrev"))) { ++ sromrev = (uint8)bcm_strtoul(value, NULL, 0); ++ flash = TRUE; ++ goto varscont; ++ } ++ ++ BS_ERROR(("%s, SROM CRC Error\n", __FUNCTION__)); ++ ++#ifndef DONGLEBUILD ++ if ((value = si_getnvramflvar(sih, "sromrev"))) { ++ err = 0; ++ goto errout; ++ } ++#endif ++/* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++ val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); ++ if ((si_is_sprom_available(sih) && srom[0] == 0xffff) || ++ (val & SPROM_OTPIN_USE)) { ++ vp = base = mfgsromvars; ++ ++ if (defvarslen == 0) { ++ BS_ERROR(("No nvm file, use generic default (for programming" ++ " SPROM/OTP only)\n")); ++ ++ if (((sih->chip == BCM4331_CHIP_ID) || ++ (sih->chip == BCM43431_CHIP_ID)) && ++ (sih->chiprev < 3)) { ++ ++ defvarslen = srom_vars_len(defaultsromvars_4331); ++ bcopy(defaultsromvars_4331, vp, defvarslen); ++ ++ } else { ++ /* For 4311 A1 there is no signature to indicate that OTP is ++ * programmed, so can't really verify the OTP is ++ * unprogrammed or a bad OTP. ++ */ ++ if (sih->chip == BCM4311_CHIP_ID) { ++ const char *devid = "devid=0x4311"; ++ const size_t devid_strlen = strlen(devid); ++ BS_ERROR(("setting the devid to be 4311\n")); ++ bcopy(devid, vp, devid_strlen + 1); ++ vp += devid_strlen + 1; ++ } ++ defvarslen = srom_vars_len(defaultsromvars_wltest); ++ bcopy(defaultsromvars_wltest, vp, defvarslen); ++ } ++ } else { ++ BS_ERROR(("Use nvm file as default\n")); ++ } ++ ++ vp += defvarslen; ++ /* add final null terminator */ ++ *vp++ = '\0'; ++ ++ BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen)); ++ goto varsdone; ++ ++ } else if ((((sih->chip == BCM4331_CHIP_ID) || ++ (sih->chip == BCM43431_CHIP_ID)) && ++ (sih->chiprev < 3)) || (sih->chip == BCM4360_CHIP_ID) || ++ (sih->chip == BCM43460_CHIP_ID) || ++ (sih->chip == BCM4352_CHIP_ID)) { ++ base = vp = mfgsromvars; ++ ++ if ((sih->chip == BCM4360_CHIP_ID) || ++ (sih->chip == BCM43460_CHIP_ID) || ++ (sih->chip == BCM4352_CHIP_ID)) ++ BS_ERROR(("4360 BOOT w/o SPROM or OTP\n")); ++ else ++ BS_ERROR(("4331 BOOT w/o SPROM or OTP\n")); ++ ++ defvarslen = srom_vars_len(defaultsromvars_4331); ++ bcopy(defaultsromvars_4331, vp, defvarslen); ++ vp += defvarslen; ++ *vp++ = '\0'; ++ goto varsdone; ++ } else ++#endif ++ { ++ err = -1; ++ goto errout; ++ } ++ } ++ ++varscont: ++ /* Bitmask for the sromrev */ ++ sr = 1 << sromrev; ++ ++ /* srom version check: Current valid versions: 1-5, 8-11, SROM_MAXREV */ ++ if ((sr & 0xf3e) == 0) { ++ BS_ERROR(("Invalid SROM rev %d\n", sromrev)); ++ err = -2; ++ goto errout; ++ } ++ ++ ASSERT(vars != NULL); ++ ASSERT(count != NULL); ++ ++ base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS); ++ ASSERT(vp != NULL); ++ if (!vp) { ++ err = -2; ++ goto errout; ++ } ++ ++ /* read variables from flash */ ++ if (flash) { ++ if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS))) ++ goto errout; ++ goto varsdone; ++ } ++ ++ varbuf_init(&b, base, MAXSZ_NVRAM_VARS); ++ ++ /* parse SROM into name=value pairs. */ ++ _initvars_srom_pci(sromrev, srom, 0, &b); ++ ++ ++ /* final nullbyte terminator */ ++ ASSERT(b.size >= 1); ++ vp = b.buf; ++ *vp++ = '\0'; ++ ++ ASSERT((vp - base) <= MAXSZ_NVRAM_VARS); ++ ++varsdone: ++ err = initvars_table(osh, base, vp, vars, count); ++ ++errout: ++/* BCMHOSTVARS are enabled only if WLTEST is enabled or BCMEXTNVM is enabled */ ++#if defined(BCMHOSTVARS) ++ if (base && (base != mfgsromvars)) ++#else ++ if (base) ++#endif ++ MFREE(osh, base, MAXSZ_NVRAM_VARS); ++ ++ MFREE(osh, srom, SROM_MAX); ++ return err; ++} ++ ++/* ++ * Read the cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_pcmcia)(si_t *sih, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis = NULL; ++ int rc; ++ uint data_sz; ++ ++ data_sz = (sih->buscorerev == 1) ? SROM_MAX : CIS_SIZE; ++ ++ if ((cis = MALLOC(osh, data_sz)) == NULL) ++ return (-2); ++ ++ if (sih->buscorerev == 1) { ++ if (srom_read(sih, PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis, ++ TRUE)) { ++ MFREE(osh, cis, data_sz); ++ return (-1); ++ } ++ /* fix up endianess for 16-bit data vs 8-bit parsing */ ++ htol16_buf((uint16 *)cis, data_sz); ++ } else ++ OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz); ++ ++ rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count); ++ ++ MFREE(osh, cis, data_sz); ++ ++ return (rc); ++} ++ ++ ++#ifdef BCMSPI ++/* ++ * Read the SPI cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_spi)(osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis; ++ int rc; ++ ++#if defined(NDIS) && !defined(UNDER_CE) ++ uint8 cisd[SBSDIO_CIS_SIZE_LIMIT]; ++ cis = (uint8*)cisd; ++#else ++ if ((cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) { ++ return -1; ++ } ++#endif /* defined(NDIS) && (!defined(UNDER_CE)) */ ++ ++ bzero(cis, SBSDIO_CIS_SIZE_LIMIT); ++ ++ if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) { ++#if defined(NDIS) && !defined(UNDER_CE) ++ /* nothing to do */ ++#else ++ MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); ++#endif /* defined(NDIS) && (!defined(UNDER_CE)) */ ++ return -2; ++ } ++ ++ rc = srom_parsecis(osh, &cis, SDIO_FUNC_1, vars, count); ++ ++#if defined(NDIS) && !defined(UNDER_CE) ++ /* nothing to do here */ ++#else ++ MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); ++#endif ++ ++ return (rc); ++} ++#endif /* BCMSPI */ ++ ++#if defined(BCMUSBDEV) ++/* Return sprom size in 16-bit words */ ++uint ++srom_size(si_t *sih, osl_t *osh) ++{ ++ uint size = 0; ++ if (SPROMBUS == PCMCIA_BUS) { ++ uint32 origidx; ++ sdpcmd_regs_t *pcmregs; ++ bool wasup; ++ ++ origidx = si_coreidx(sih); ++ pcmregs = si_setcore(sih, PCMCIA_CORE_ID, 0); ++ if (!pcmregs) ++ pcmregs = si_setcore(sih, SDIOD_CORE_ID, 0); ++ ASSERT(pcmregs); ++ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ /* not worry about earlier core revs */ ++ /* valid for only pcmcia core */ ++ if (si_coreid(sih) == PCMCIA_CORE_ID) ++ if (si_corerev(sih) < 8) ++ goto done; ++ ++ ++ switch (SI_PCMCIA_READ(osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) { ++ case 1: ++ size = 256; /* SROM_INFO == 1 means 4kbit */ ++ break; ++ case 2: ++ size = 1024; /* SROM_INFO == 2 means 16kbit */ ++ break; ++ default: ++ break; ++ } ++ ++ done: ++ if (!wasup) ++ si_core_disable(sih, 0); ++ ++ si_setcoreidx(sih, origidx); ++ } ++ return size; ++} ++#endif ++ ++/* ++ * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at ++ * the same time, but only because all of the code is in attach functions and not in ROM. ++ */ ++ ++#if defined(BCMUSBDEV_ENABLED) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++/* ++ * Read the USB cis and call parsecis to initialize the vars. ++ * Return 0 on success, nonzero on error. ++ */ ++static int ++BCMATTACHFN(initvars_cis_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *count) ++{ ++ uint8 *cis; ++ uint sz = OTP_SZ_MAX/2; /* size in words */ ++ int rc = BCME_OK; ++ ++ if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) { ++ return -1; ++ } ++ ++ bzero(cis, OTP_SZ_MAX); ++ ++ if (otp_read_region(sih, OTP_SW_RGN, (uint16 *)cis, &sz)) { ++ BS_ERROR(("%s: OTP read SW region failure.\n*", __FUNCTION__)); ++ rc = -2; ++ } else { ++ BS_ERROR(("%s: OTP programmed. use OTP for srom vars\n*", __FUNCTION__)); ++ rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count); ++ } ++ ++ MFREE(osh, cis, OTP_SZ_MAX); ++ ++ return (rc); ++} ++ ++/* For driver(not bootloader), if nvram is not downloadable or missing, use default */ ++static int ++BCMATTACHFN(initvars_srom_si_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *varsz) ++{ ++ uint len; ++ char *base; ++ char *fakevars; ++ int rc = -1; ++ ++ base = fakevars = NULL; ++ len = 0; ++ switch (CHIPID(sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ fakevars = defaultsromvars_4322usb; ++ break; ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ /* check against real chipid instead of compile time flag */ ++ if (sih->chip == BCM43234_CHIP_ID) { ++ fakevars = defaultsromvars_43234usb; ++ } else if (sih->chip == BCM43235_CHIP_ID) { ++ fakevars = defaultsromvars_43235usb; ++ } else ++ fakevars = defaultsromvars_43236usb; ++ break; ++ ++ case BCM4319_CHIP_ID: ++ fakevars = defaultsromvars_4319usb; ++ break; ++ case BCM4360_CHIP_ID: ++ case BCM43460_CHIP_ID: ++ case BCM43526_CHIP_ID: ++ fakevars = defaultsromvars_4360usb; ++ break; ++ default: ++ ASSERT(0); ++ return rc; ++ } ++ ++#ifndef BCM_BMAC_VARS_APPEND ++ if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) { ++ /* Make OTP/SROM variables global */ ++ if (srvars_inited == FALSE) ++ nvram_append((void *)sih, *vars, *varsz); ++ return BCME_OK; ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++ /* NO OTP, if nvram downloaded, use it */ ++ if ((_varsz != 0) && (_vars != NULL)) { ++ len = _varsz + (strlen(vstr_end)); ++ base = MALLOC(osh, len + 2); /* plus 2 terminating \0 */ ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, len + 2); ++ ++ /* make a copy of the _vars, _vars is at the top of the memory, cannot append ++ * END\0\0 to it. copy the download vars to base, back of the terminating \0, ++ * then append END\0\0 ++ */ ++ bcopy((void *)_vars, base, _varsz); ++ /* backoff all the terminating \0s except the one the for the last string */ ++ len = _varsz; ++ while (!base[len - 1]) ++ len--; ++ len++; /* \0 for the last string */ ++ /* append END\0\0 to the end */ ++ bcopy((void *)vstr_end, (base + len), strlen(vstr_end)); ++ len += (strlen(vstr_end) + 2); ++ *vars = base; ++ *varsz = len; ++ ++ BS_ERROR(("%s USB nvram downloaded %d bytes\n", __FUNCTION__, _varsz)); ++ } else { ++ /* Fall back to fake srom vars if OTP not programmed */ ++ len = srom_vars_len(fakevars); ++ base = MALLOC(osh, (len + 1)); ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, (len + 1)); ++ bcopy(fakevars, base, len); ++ *(base + len) = '\0'; /* add final nullbyte terminator */ ++ *vars = base; ++ *varsz = len + 1; ++ BS_ERROR(("initvars_srom_usbdriver: faked nvram %d bytes\n", len)); ++ } ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) { ++ if (base) ++ MFREE(osh, base, (len + 1)); ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ /* Make OTP/SROM variables global */ ++ if (srvars_inited == FALSE) { ++ nvram_append((void *)sih, *vars, *varsz); ++ srvars_inited = TRUE; ++ } ++ return BCME_OK; ++ ++} ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++ ++#ifdef BCM_DONGLEVARS ++static int ++BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */ ++ uint sz = 0; /* srom size in bytes */ ++ void *oh = NULL; ++ int rc = BCME_OK; ++ ++ if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) { ++ /* Access OTP if it is present, powered on, and programmed */ ++ sz = otp_size(oh); ++ sel = 1; ++ } else if ((sz = srom_size(sih, osh)) != 0) { ++ /* Access the SPROM if it is present */ ++ sz <<= 1; ++ sel = 2; ++ } ++ ++ /* Read CIS in OTP/SPROM */ ++ if (sel != 0) { ++ uint16 *srom; ++ uint8 *body = NULL; ++ uint otpsz = sz; ++ ++ ASSERT(sz); ++ ++ /* Allocate memory */ ++ if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL) ++ return BCME_NOMEM; ++ ++ /* Read CIS */ ++ switch (sel) { ++ case 1: ++ rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz); ++ sz = otpsz; ++ body = (uint8 *)srom; ++ break; ++ case 2: ++ rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE); ++ /* sprom has 8 byte h/w header */ ++ body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET; ++ break; ++ default: ++ /* impossible to come here */ ++ ASSERT(0); ++ break; ++ } ++ ++ /* Parse CIS */ ++ if (rc == BCME_OK) { ++ /* each word is in host endian */ ++ htol16_buf((uint8 *)srom, sz); ++ ASSERT(body); ++ rc = srom_parsecis(osh, &body, SROM_CIS_SINGLE, vars, varsz); ++ } ++ ++ MFREE(osh, srom, sz); /* Clean up */ ++ ++ /* Make SROM variables global */ ++ if (rc == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ } ++ ++ return BCME_OK; ++} ++#endif /* #ifdef BCM_DONGLEVARS */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ ++ /* Bail out if we've dealt with OTP/SPROM before! */ ++ if (srvars_inited) ++ goto exit; ++ ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ /* read OTP or use faked var array */ ++ switch (CHIPID(sih->chip)) { ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID: ++ case BCM43234_CHIP_ID: ++ case BCM4319_CHIP_ID: ++ case BCM4360_CHIP_ID: ++ case BCM43460_CHIP_ID: ++ case BCM4352_CHIP_ID: ++ if (BCME_OK != initvars_srom_si_usbdriver(sih, osh, vars, varsz)) ++ goto exit; ++ return BCME_OK; ++ default: ++ UNUSED_PARAMETER(defaultsromvars_4322usb); ++ UNUSED_PARAMETER(defaultsromvars_43234usb); ++ UNUSED_PARAMETER(defaultsromvars_43235usb); ++ UNUSED_PARAMETER(defaultsromvars_43236usb); ++ UNUSED_PARAMETER(defaultsromvars_4319usb); ++ } ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++ ++#ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read OTP \ ++ or SROM */ ++ if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz)) ++ return BCME_ERROR; ++#endif ++ ++ /* update static local var to skip for next call */ ++ srvars_inited = TRUE; ++ ++exit: ++ /* Tell the caller there is no individual SROM variables */ ++ *vars = NULL; ++ *varsz = 0; ++ ++ /* return OK so the driver will load & use defaults if bad srom/otp */ ++ return BCME_OK; ++} ++ ++#elif defined(BCMSDIODEV_ENABLED) ++ ++#ifdef BCM_DONGLEVARS ++static uint8 BCMATTACHDATA(defcis4325)[] = { 0x20, 0x4, 0xd0, 0x2, 0x25, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4315)[] = { 0x20, 0x4, 0xd0, 0x2, 0x15, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4329)[] = { 0x20, 0x4, 0xd0, 0x2, 0x29, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4319)[] = { 0x20, 0x4, 0xd0, 0x2, 0x19, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4336)[] = { 0x20, 0x4, 0xd0, 0x2, 0x36, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4330)[] = { 0x20, 0x4, 0xd0, 0x2, 0x30, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis43237)[] = { 0x20, 0x4, 0xd0, 0x2, 0xe5, 0xa8, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4324)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff }; ++static uint8 BCMATTACHDATA(defcis4335)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff }; ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x05a1\0" ++ "boardrev=0x1102\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=26000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa\0" ++ "rssismc2g=0xb\0" ++ "rssisav2g=0x3\0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:06:c0:19\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio_hmb)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x058c\0" ++ "boardrev=0x1102\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=26000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa \0" ++ "rssismc2g=0xb \0" ++ "rssisav2g=0x3 \0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:06:c0:19\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_4319sdio_usbsd)[] = ++ "sromrev=3\0" ++ "vendid=0x14e4\0" ++ "devid=0x4338\0" ++ "boardtype=0x05a2\0" ++ "boardrev=0x1100\0" ++ "boardflags=0x400201\0" ++ "boardflags2=0x80\0" ++ "xtalfreq=30000\0" ++ "aa2g=3\0" ++ "aa5g=0\0" ++ "ag0=0\0" ++ "opo=0\0" ++ "pa0b0=0x1675\0" ++ "pa0b1=0xfa74\0" ++ "pa0b2=0xfea1\0" ++ "pa0itssit=62\0" ++ "pa0maxpwr=78\0" ++ "rssismf2g=0xa \0" ++ "rssismc2g=0xb \0" ++ "rssisav2g=0x3 \0" ++ "bxa2g=0\0" ++ "cckdigfilttype=6\0" ++ "rxpo2g=2\0" ++ "cckpo=0\0" ++ "ofdmpo=0x55553333\0" ++ "mcs2gpo0=0x9999\0" ++ "mcs2gpo1=0x9999\0" ++ "mcs2gpo2=0x0000\0" ++ "mcs2gpo3=0x0000\0" ++ "mcs2gpo4=0x9999\0" ++ "mcs2gpo5=0x9999\0" ++ "macaddr=00:90:4c:08:90:00\0" ++ "END\0"; ++ ++static char BCMATTACHDATA(defaultsromvars_43237)[] = ++ "vendid=0x14e4\0" ++ "devid=0x4355\0" ++ "boardtype=0x0583\0" ++ "boardrev=0x1103\0" ++ "boardnum=0x1\0" ++ "boardflags=0x200\0" ++ "boardflags2=0\0" ++ "sromrev=8\0" ++ "macaddr=00:90:4c:51:a8:e4\0" ++ "ccode=0\0" ++ "regrev=0\0" ++ "ledbh0=0xff\0" ++ "ledbh1=0xff\0" ++ "ledbh2=0xff\0" ++ "ledbh3=0xff\0" ++ "leddc=0xffff\0" ++ "opo=0x0\0" ++ "aa2g=0x3\0" ++ "aa5g=0x3\0" ++ "ag0=0x2\0" ++ "ag1=0x2\0" ++ "ag2=0xff\0" ++ "ag3=0xff\0" ++ "pa0b0=0xfed1\0" ++ "pa0b1=0x15fd\0" ++ "pa0b2=0xfac2\0" ++ "pa0itssit=0x20\0" ++ "pa0maxpwr=0x4c\0" ++ "pa1b0=0xfecd\0" ++ "pa1b1=0x1497\0" ++ "pa1b2=0xfae3\0" ++ "pa1lob0=0xfe87\0" ++ "pa1lob1=0x1637\0" ++ "pa1lob2=0xfa8e\0" ++ "pa1hib0=0xfedc\0" ++ "pa1hib1=0x144b\0" ++ "pa1hib2=0xfb01\0" ++ "pa1itssit=0x3e\0" ++ "pa1maxpwr=0x40\0" ++ "pa1lomaxpwr=0x3a\0" ++ "pa1himaxpwr=0x3c\0" ++ "bxa2g=0x3\0" ++ "rssisav2g=0x7\0" ++ "rssismc2g=0xf\0" ++ "rssismf2g=0xf\0" ++ "bxa5g=0x3\0" ++ "rssisav5g=0x7\0" ++ "rssismc5g=0xf\0" ++ "rssismf5g=0xf\0" ++ "tri2g=0xff\0" ++ "tri5g=0xff\0" ++ "tri5gl=0xff\0" ++ "tri5gh=0xff\0" ++ "rxpo2g=0xff\0" ++ "rxpo5g=0xff\0" ++ "txchain=0x3\0" ++ "rxchain=0x3\0" ++ "antswitch=0x0\0" ++ "tssipos2g=0x1\0" ++ "extpagain2g=0x2\0" ++ "pdetrange2g=0x2\0" ++ "triso2g=0x3\0" ++ "antswctl2g=0x0\0" ++ "tssipos5g=0x1\0" ++ "extpagain5g=0x2\0" ++ "pdetrange5g=0x2\0" ++ "triso5g=0x3\0" ++ "cck2gpo=0x0\0" ++ "ofdm2gpo=0x0\0" ++ "ofdm5gpo=0x0\0" ++ "ofdm5glpo=0x0\0" ++ "ofdm5ghpo=0x0\0" ++ "mcs2gpo0=0x0\0" ++ "mcs2gpo1=0x0\0" ++ "mcs2gpo2=0x0\0" ++ "mcs2gpo3=0x0\0" ++ "mcs2gpo4=0x0\0" ++ "mcs2gpo5=0x0\0" ++ "mcs2gpo6=0x0\0" ++ "mcs2gpo7=0x0\0" ++ "mcs5gpo0=0x0\0" ++ "mcs5gpo1=0x0\0" ++ "mcs5gpo2=0x0\0" ++ "mcs5gpo3=0x0\0" ++ "mcs5gpo4=0x0\0" ++ "mcs5gpo5=0x0\0" ++ "mcs5gpo6=0x0\0" ++ "mcs5gpo7=0x0\0" ++ "mcs5glpo0=0x0\0" ++ "mcs5glpo1=0x0\0" ++ "mcs5glpo2=0x0\0" ++ "mcs5glpo3=0x0\0" ++ "mcs5glpo4=0x0\0" ++ "mcs5glpo5=0x0\0" ++ "mcs5glpo6=0x0\0" ++ "mcs5glpo7=0x0\0" ++ "mcs5ghpo0=0x0\0" ++ "mcs5ghpo1=0x0\0" ++ "mcs5ghpo2=0x0\0" ++ "mcs5ghpo3=0x0\0" ++ "mcs5ghpo4=0x0\0" ++ "mcs5ghpo5=0x0\0" ++ "mcs5ghpo6=0x0\0" ++ "mcs5ghpo7=0x0\0" ++ "cddpo=0x0\0" ++ "stbcpo=0x0\0" ++ "bw40po=0x0\0" ++ "bwduppo=0x0\0" ++ "maxp2ga0=0x4c\0" ++ "pa2gw0a0=0xfed1\0" ++ "pa2gw1a0=0x15fd\0" ++ "pa2gw2a0=0xfac2\0" ++ "maxp5ga0=0x3c\0" ++ "maxp5gha0=0x3c\0" ++ "maxp5gla0=0x3c\0" ++ "pa5gw0a0=0xfeb0\0" ++ "pa5gw1a0=0x1491\0" ++ "pa5gw2a0=0xfaf8\0" ++ "pa5glw0a0=0xfeaa\0" ++ "pa5glw1a0=0x14b9\0" ++ "pa5glw2a0=0xfaf0\0" ++ "pa5ghw0a0=0xfec5\0" ++ "pa5ghw1a0=0x1439\0" ++ "pa5ghw2a0=0xfb18\0" ++ "maxp2ga1=0x4c\0" ++ "itt2ga0=0x20\0" ++ "itt5ga0=0x3e\0" ++ "itt2ga1=0x20\0" ++ "itt5ga1=0x3e\0" ++ "pa2gw0a1=0xfed2\0" ++ "pa2gw1a1=0x15d9\0" ++ "pa2gw2a1=0xfac6\0" ++ "maxp5ga1=0x3a\0" ++ "maxp5gha1=0x3a\0" ++ "maxp5gla1=0x3a\0" ++ "pa5gw0a1=0xfebe\0" ++ "pa5gw1a1=0x1306\0" ++ "pa5gw2a1=0xfb63\0" ++ "pa5glw0a1=0xfece\0" ++ "pa5glw1a1=0x1361\0" ++ "pa5glw2a1=0xfb5f\0" ++ "pa5ghw0a1=0xfe9e\0" ++ "pa5ghw1a1=0x12ca\0" ++ "pa5ghw2a1=0xfb41\0" ++ "END\0"; ++ ++static int ++srom_load_nvram(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *varsz) ++{ ++ uint len = 0, base_len; ++ char *base; ++ char *fakevars; ++ ++ base = fakevars = NULL; ++ switch (CHIPID(sih->chip)) { ++ case BCM4319_CHIP_ID: ++ printf("load driver default for chip %x\n", CHIPID(sih->chip)); ++ fakevars = defaultsromvars_4319sdio; ++ if (si_cis_source(sih) == CIS_OTP) { ++ switch (srom_probe_boardtype(pcis, ciscnt)) { ++ case BCM94319SDHMB_SSID: ++ fakevars = defaultsromvars_4319sdio_hmb; ++ break; ++ case BCM94319USBSDB_SSID: ++ fakevars = defaultsromvars_4319sdio_usbsd; ++ break; ++ default: ++ fakevars = defaultsromvars_4319sdio; ++ break; ++ } ++ } ++ break; ++ case BCM43237_CHIP_ID: ++ printf("load driver default for chip %x\n", CHIPID(sih->chip)); ++ fakevars = defaultsromvars_43237; ++ break; ++ default: ++ printf("unknown chip %x\n", CHIPID(sih->chip)); ++ return BCME_ERROR; /* fakevars == NULL for switch default */ ++ } ++ ++ ++ /* NO OTP, if nvram downloaded, use it */ ++ if ((_varsz != 0) && (_vars != NULL)) { ++ len = _varsz + (strlen(vstr_end)); ++ base_len = len + 2; /* plus 2 terminating \0 */ ++ base = MALLOC(osh, base_len); ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, base_len); ++ ++ /* make a copy of the _vars, _vars is at the top of the memory, cannot append ++ * END\0\0 to it. copy the download vars to base, back of the terminating \0, ++ * then append END\0\0 ++ */ ++ bcopy((void *)_vars, base, _varsz); ++ /* backoff all the terminating \0s except the one the for the last string */ ++ len = _varsz; ++ while (!base[len - 1]) ++ len--; ++ len++; /* \0 for the last string */ ++ /* append END\0\0 to the end */ ++ bcopy((void *)vstr_end, (base + len), strlen(vstr_end)); ++ len += (strlen(vstr_end) + 2); ++ *vars = base; ++ *varsz = len; ++ ++ BS_ERROR(("%s nvram downloaded %d bytes\n", __FUNCTION__, _varsz)); ++ } else { ++ /* Fall back to fake srom vars if OTP not programmed */ ++ len = srom_vars_len(fakevars); ++ base = MALLOC(osh, (len + 1)); ++ base_len = len + 1; ++ if (base == NULL) { ++ BS_ERROR(("initvars_srom_si: MALLOC failed.\n")); ++ return BCME_ERROR; ++ } ++ bzero(base, base_len); ++ bcopy(fakevars, base, len); ++ *(base + len) = '\0'; /* add final nullbyte terminator */ ++ *vars = base; ++ *varsz = len + 1; ++ BS_ERROR(("srom_load_driver)default: faked nvram %d bytes\n", len)); ++ } ++ /* Parse the CIS */ ++ if ((srom_parsecis(osh, pcis, ciscnt, vars, varsz)) == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ MFREE(osh, base, base_len); ++ return BCME_OK; ++} ++ ++#endif /* BCM_BMAC_VARS_APPEND */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ int cis_src; ++ uint msz = 0; ++ uint sz = 0; ++ void *oh = NULL; ++ int rc = BCME_OK; ++ bool new_cisformat = FALSE; ++ ++ uint16 *cisbuf = NULL; ++ ++ /* # sdiod fns + common + extra */ ++ uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 }; ++ ++ uint ciss = 0; ++ uint8 *defcis; ++ uint hdrsz; ++ ++ /* Bail out if we've dealt with OTP/SPROM before! */ ++ if (srvars_inited) ++ goto exit; ++ ++ /* Initialize default and cis format count */ ++ switch (CHIPID(sih->chip)) { ++ case BCM4325_CHIP_ID: ciss = 3; defcis = defcis4325; hdrsz = 8; break; ++ case BCM4315_CHIP_ID: ciss = 3; defcis = defcis4315; hdrsz = 8; break; ++ case BCM4329_CHIP_ID: ciss = 4; defcis = defcis4329; hdrsz = 12; break; ++ case BCM4319_CHIP_ID: ciss = 3; defcis = defcis4319; hdrsz = 12; break; ++ case BCM4336_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break; ++ case BCM43362_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break; ++ case BCM4330_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM43237_CHIP_ID: ciss = 1; defcis = defcis43237; hdrsz = 4; break; ++ case BCM4324_CHIP_ID: ciss = 1; defcis = defcis4324; hdrsz = 4; break; ++ case BCM4314_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM4334_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break; ++ case BCM4335_CHIP_ID: ciss = 1; defcis = defcis4335; hdrsz = 4; break; ++ default: ++ BS_ERROR(("%s: Unknown chip 0x%04x\n", __FUNCTION__, sih->chip)); ++ return BCME_ERROR; ++ } ++ if (sih->ccrev >= 36) { ++ uint32 otplayout; ++ otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout), 0, 0); ++ if (otplayout & OTP_CISFORMAT_NEW) { ++ ciss = 1; ++ hdrsz = 2; ++ new_cisformat = TRUE; ++ } ++ else { ++ ciss = 3; ++ hdrsz = 12; ++ } ++ } ++ ++ cis_src = si_cis_source(sih); ++ switch (cis_src) { ++ case CIS_SROM: ++ sz = srom_size(sih, osh) << 1; ++ break; ++ case CIS_OTP: ++ if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW)) ++ sz = otp_size(oh); ++ break; ++ } ++ ++ if (sz != 0) { ++ if ((cisbuf = (uint16*)MALLOC(osh, sz)) == NULL) ++ return BCME_NOMEM; ++ msz = sz; ++ ++ switch (cis_src) { ++ case CIS_SROM: ++ rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE); ++ break; ++ case CIS_OTP: ++ sz >>= 1; ++ rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz); ++ sz <<= 1; ++ break; ++ } ++ ++ ASSERT(sz > hdrsz); ++ if (rc == BCME_OK) { ++ if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) { ++ MFREE(osh, cisbuf, msz); ++ cisbuf = NULL; ++ } else if (new_cisformat) { ++ cis[0] = (uint8*)(cisbuf + hdrsz); ++ } else { ++ cis[0] = (uint8*)cisbuf + hdrsz; ++ cis[1] = (uint8*)cisbuf + hdrsz + ++ (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) - ++ SBSDIO_CIS_BASE_COMMON; ++ cis[2] = (uint8*)cisbuf + hdrsz + ++ cisbuf[3] - SBSDIO_CIS_BASE_COMMON; ++ cis[3] = (uint8*)cisbuf + hdrsz + ++ cisbuf[4] - SBSDIO_CIS_BASE_COMMON; ++ ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz)); ++ ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz)); ++ ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) || ++ (ciss <= 3)); ++ } ++ } ++ } ++ ++ /* Use default if strapped to, or strapped source empty */ ++ if (cisbuf == NULL) { ++ ciss = 1; ++ cis[0] = defcis; ++ } ++ ++#ifdef BCM_BMAC_VARS_APPEND ++ srom_load_nvram(sih, osh, cis, ciss, vars, varsz); ++#else ++ /* Parse the CIS */ ++ if (rc == BCME_OK) { ++ if ((rc = srom_parsecis(osh, cis, ciss, vars, varsz)) == BCME_OK) ++ nvram_append((void *)sih, *vars, *varsz); ++ } ++#endif /* BCM_BMAC_VARS_APPEND */ ++ /* Clean up */ ++ if (cisbuf != NULL) ++ MFREE(osh, cisbuf, msz); ++ ++ srvars_inited = TRUE; ++exit: ++ /* Tell the caller there is no individual SROM variables */ ++ *vars = NULL; ++ *varsz = 0; ++ ++ /* return OK so the driver will load & use defaults if bad srom/otp */ ++ return BCME_OK; ++} ++#else /* BCM_DONGLEVARS */ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ *vars = NULL; ++ *varsz = 0; ++ return BCME_OK; ++} ++#endif /* BCM_DONGLEVARS */ ++ ++#else /* !BCMUSBDEV && !BCMSDIODEV */ ++ ++static int ++BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz) ++{ ++ /* Search flash nvram section for srom variables */ ++ return initvars_flash_si(sih, vars, varsz); ++} ++#endif ++ ++void ++srom_var_deinit(si_t *sih) ++{ ++ srvars_inited = FALSE; ++} ++ ++extern void _make_gcc_happy_about_unused_variabe_(void); ++void ++_make_gcc_happy_about_unused_variabe_(void) ++{ ++#if defined(BCMUSBDEV) ++#if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND) ++ UNUSED_PARAMETER(defaultsromvars_4322usb); ++ UNUSED_PARAMETER(defaultsromvars_43234usb); ++ UNUSED_PARAMETER(defaultsromvars_43235usb); ++ UNUSED_PARAMETER(defaultsromvars_43236usb); ++ UNUSED_PARAMETER(defaultsromvars_4319usb); ++#endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */ ++#endif /* BCMUSBDEV */ ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/bcmutils.c b/drivers/bcmdrivers/gmac/src/shared/bcmutils.c +new file mode 100755 +index 0000000..9f45f68 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/bcmutils.c +@@ -0,0 +1,3253 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Driver O/S-independent utility routines ++ * ++ * $Id: bcmutils.c 325951 2012-04-05 06:03:27Z $ ++ */ ++ ++#include ++#include ++#include ++#if defined(__FreeBSD__) || defined(__NetBSD__) ++#include ++#else ++#include ++#endif ++#ifdef BCMDRIVER ++ ++#include ++#include ++#include ++#include ++ ++#else /* !BCMDRIVER */ ++ ++#include ++#include ++#include ++ ++#if defined(BCMEXTSUP) ++#include ++#endif ++ ++ ++#endif /* !BCMDRIVER */ ++ ++#if defined(_WIN32) || defined(NDIS) || defined(__vxworks) || defined(_CFE_) ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef BCMPERFSTATS ++#include ++#endif ++#include ++void *_bcmutils_dummy_fn = NULL; ++ ++#ifdef BCMDRIVER ++ ++#ifdef WLC_LOW ++/* nvram vars cache */ ++static char *nvram_vars = NULL; ++static int vars_len = -1; ++#endif /* WLC_LOW */ ++ ++int ++pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx) ++{ ++ int i, err = BCME_OK; ++ void *p; ++ int pktplen; ++ ++ ASSERT(pktp != NULL); ++ ASSERT(osh != NULL); ++ ASSERT(pplen != NULL); ++ ++ pktplen = *pplen; ++ ++ bzero(pktp, sizeof(pktpool_t)); ++ pktp->inited = TRUE; ++ pktp->istx = istx ? TRUE : FALSE; ++ pktp->plen = (uint16)plen; ++ *pplen = 0; ++ ++ pktp->maxlen = PKTPOOL_LEN_MAX; ++ if (pktplen > pktp->maxlen) ++ pktplen = pktp->maxlen; ++ ++ for (i = 0; i < pktplen; i++) { ++ p = PKTGET(osh, plen, pktp->istx); ++ if (p == NULL) { ++ /* Not able to allocate all requested pkts ++ * so just return what was actually allocated ++ * We can add to the pool later ++ */ ++ if (pktp->w == 0) ++ err = BCME_NOMEM; ++ ++ goto exit; ++ } ++ ++ PKTSETPOOL(osh, p, TRUE, pktp); ++ pktp->q[i] = p; ++ pktp->w++; ++ pktp->len++; ++#ifdef BCMDBG_POOL ++ pktp->dbg_q[pktp->dbg_qlen++].p = p; ++#endif ++ } ++ ++exit: ++ *pplen = pktp->w; ++ pktp->len++; /* Add one for end */ ++ return err; ++} ++ ++int ++pktpool_deinit(osl_t *osh, pktpool_t *pktp) ++{ ++ int i; ++ int cnt; ++ ++ ASSERT(osh != NULL); ++ ASSERT(pktp != NULL); ++ ++ cnt = pktp->len; ++ for (i = 0; i < cnt; i++) { ++ if (pktp->q[i] != NULL) { ++ PKTSETPOOL(osh, pktp->q[i], FALSE, NULL); ++ PKTFREE(osh, pktp->q[i], pktp->istx); ++ pktp->q[i] = NULL; ++ pktp->len--; ++ } ++#ifdef BCMDBG_POOL ++ if (pktp->dbg_q[i].p != NULL) ++ pktp->dbg_q[i].p = NULL; ++#endif ++ } ++ pktp->inited = FALSE; ++ ++ /* Are there still pending pkts? */ ++ ASSERT(pktpool_len(pktp) == 0); ++ ++ return 0; ++} ++ ++int ++pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal) ++{ ++ void *p; ++ int err = 0; ++ int len, psize, maxlen; ++ ++ ASSERT(pktpool_plen(pktp) != 0); ++ ++ maxlen = pktpool_maxlen(pktp); ++ psize = minimal ? (maxlen >> 2) : maxlen; ++ len = pktpool_len(pktp); ++ for (; len < psize; len++) { ++ p = PKTGET(osh, pktpool_plen(pktp), FALSE); ++ if (p == NULL) { ++ err = BCME_NOMEM; ++ break; ++ } ++ ++ if (pktpool_add(pktp, p) != BCME_OK) { ++ PKTFREE(osh, p, FALSE); ++ err = BCME_ERROR; ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++uint16 ++pktpool_avail(pktpool_t *pktp) ++{ ++ if (pktp->w == pktp->r) ++ return 0; ++ ++ return (pktp->w > pktp->r) ? (pktp->w - pktp->r) : ((pktp->len) - (pktp->r - pktp->w)); ++} ++ ++static void * ++pktpool_deq(pktpool_t *pktp) ++{ ++ void *p; ++ ++ if (pktp->r == pktp->w) ++ return NULL; ++ ++ p = pktp->q[pktp->r]; ++ ASSERT(p != NULL); ++ ++ pktp->q[pktp->r++] = NULL; ++ pktp->r %= (pktp->len); ++ ++ return p; ++} ++ ++static void ++pktpool_enq(pktpool_t *pktp, void *p) ++{ ++ uint16 next; ++ ++ ASSERT(p != NULL); ++ ++ next = (pktp->w + 1) % (pktp->len); ++ if (next == pktp->r) { ++ /* Should not happen; otherwise pkt leak */ ++ ASSERT(0); ++ return; ++ } ++ ++ ASSERT(pktp->q[pktp->w] == NULL); ++ ++ pktp->q[pktp->w] = p; ++ pktp->w = next; ++} ++ ++int ++pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb != NULL); ++ ++ i = pktp->cbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->cbs[i].cb == NULL); ++ pktp->cbs[i].cb = cb; ++ pktp->cbs[i].arg = arg; ++ pktp->cbcnt++; ++ ++ return 0; ++} ++ ++int ++pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb != NULL); ++ ++ i = pktp->ecbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->ecbs[i].cb == NULL); ++ pktp->ecbs[i].cb = cb; ++ pktp->ecbs[i].arg = arg; ++ pktp->ecbcnt++; ++ ++ return 0; ++} ++ ++static int ++pktpool_empty_notify(pktpool_t *pktp) ++{ ++ int i; ++ ++ pktp->empty = TRUE; ++ for (i = 0; i < pktp->ecbcnt; i++) { ++ ASSERT(pktp->ecbs[i].cb != NULL); ++ pktp->ecbs[i].cb(pktp, pktp->ecbs[i].arg); ++ } ++ pktp->empty = FALSE; ++ ++ return 0; ++} ++ ++#ifdef BCMDBG_POOL ++int ++pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ++{ ++ int i; ++ ++ ASSERT(cb); ++ ++ i = pktp->dbg_cbcnt; ++ if (i == PKTPOOL_CB_MAX) ++ return BCME_ERROR; ++ ++ ASSERT(pktp->dbg_cbs[i].cb == NULL); ++ pktp->dbg_cbs[i].cb = cb; ++ pktp->dbg_cbs[i].arg = arg; ++ pktp->dbg_cbcnt++; ++ ++ return 0; ++} ++ ++int pktpool_dbg_notify(pktpool_t *pktp); ++ ++int ++pktpool_dbg_notify(pktpool_t *pktp) ++{ ++ int i; ++ ++ for (i = 0; i < pktp->dbg_cbcnt; i++) { ++ ASSERT(pktp->dbg_cbs[i].cb); ++ pktp->dbg_cbs[i].cb(pktp, pktp->dbg_cbs[i].arg); ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_dbg_dump(pktpool_t *pktp) ++{ ++ int i; ++ ++ printf("pool len=%d maxlen=%d\n", pktp->dbg_qlen, pktp->maxlen); ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p); ++ printf("%d, p: 0x%x dur:%lu us state:%d\n", i, ++ pktp->dbg_q[i].p, pktp->dbg_q[i].dur/100, PKTPOOLSTATE(pktp->dbg_q[i].p)); ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats) ++{ ++ int i; ++ int state; ++ ++ bzero(stats, sizeof(pktpool_stats_t)); ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ state = PKTPOOLSTATE(pktp->dbg_q[i].p); ++ switch (state) { ++ case POOL_TXENQ: ++ stats->enq++; break; ++ case POOL_TXDH: ++ stats->txdh++; break; ++ case POOL_TXD11: ++ stats->txd11++; break; ++ case POOL_RXDH: ++ stats->rxdh++; break; ++ case POOL_RXD11: ++ stats->rxd11++; break; ++ case POOL_RXFILL: ++ stats->rxfill++; break; ++ case POOL_IDLE: ++ stats->idle++; break; ++ } ++ } ++ ++ return 0; ++} ++ ++int ++pktpool_start_trigger(pktpool_t *pktp, void *p) ++{ ++ uint32 cycles, i; ++ ++ if (!PKTPOOL(NULL, p)) ++ return 0; ++ ++ OSL_GETCYCLES(cycles); ++ ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ if (pktp->dbg_q[i].p == p) { ++ pktp->dbg_q[i].cycles = cycles; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++int pktpool_stop_trigger(pktpool_t *pktp, void *p); ++int ++pktpool_stop_trigger(pktpool_t *pktp, void *p) ++{ ++ uint32 cycles, i; ++ ++ if (!PKTPOOL(NULL, p)) ++ return 0; ++ ++ OSL_GETCYCLES(cycles); ++ ++ for (i = 0; i < pktp->dbg_qlen; i++) { ++ ASSERT(pktp->dbg_q[i].p != NULL); ++ ++ if (pktp->dbg_q[i].p == p) { ++ if (pktp->dbg_q[i].cycles == 0) ++ break; ++ ++ if (cycles >= pktp->dbg_q[i].cycles) ++ pktp->dbg_q[i].dur = cycles - pktp->dbg_q[i].cycles; ++ else ++ pktp->dbg_q[i].dur = ++ (((uint32)-1) - pktp->dbg_q[i].cycles) + cycles + 1; ++ ++ pktp->dbg_q[i].cycles = 0; ++ break; ++ } ++ } ++ ++ return 0; ++} ++#endif /* BCMDBG_POOL */ ++ ++int ++pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp) ++{ ++ ASSERT(pktp); ++ pktp->availcb_excl = NULL; ++ return 0; ++} ++ ++int ++pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb) ++{ ++ int i; ++ ++ ASSERT(pktp); ++ ASSERT(pktp->availcb_excl == NULL); ++ for (i = 0; i < pktp->cbcnt; i++) { ++ if (cb == pktp->cbs[i].cb) { ++ pktp->availcb_excl = &pktp->cbs[i]; ++ break; ++ } ++ } ++ ++ if (pktp->availcb_excl == NULL) ++ return BCME_ERROR; ++ else ++ return 0; ++} ++ ++static int ++pktpool_avail_notify(pktpool_t *pktp) ++{ ++ int i, k, idx; ++ int avail; ++ ++ ASSERT(pktp); ++ if (pktp->availcb_excl != NULL) { ++ pktp->availcb_excl->cb(pktp, pktp->availcb_excl->arg); ++ return 0; ++ } ++ ++ k = pktp->cbcnt - 1; ++ for (i = 0; i < pktp->cbcnt; i++) { ++ avail = pktpool_avail(pktp); ++ ++ if (avail) { ++ if (pktp->cbtoggle) ++ idx = i; ++ else ++ idx = k--; ++ ++ ASSERT(pktp->cbs[idx].cb != NULL); ++ pktp->cbs[idx].cb(pktp, pktp->cbs[idx].arg); ++ } ++ } ++ ++ /* Alternate between filling from head or tail ++ */ ++ pktp->cbtoggle ^= 1; ++ ++ return 0; ++} ++ ++void * ++pktpool_get(pktpool_t *pktp) ++{ ++ void *p; ++ ++ p = pktpool_deq(pktp); ++ ++ if (p == NULL) { ++ /* Notify and try to reclaim tx pkts */ ++ if (pktp->ecbcnt) ++ pktpool_empty_notify(pktp); ++ ++ p = pktpool_deq(pktp); ++ } ++ ++ return p; ++} ++ ++void ++pktpool_free(pktpool_t *pktp, void *p) ++{ ++ ASSERT(p != NULL); ++ ++#ifdef BCMDBG_POOL ++ /* pktpool_stop_trigger(pktp, p); */ ++#endif ++ ++ pktpool_enq(pktp, p); ++ ++ if (pktp->emptycb_disable) ++ return; ++ ++ if (pktp->cbcnt) { ++ if (pktp->empty == FALSE) ++ pktpool_avail_notify(pktp); ++ } ++} ++ ++int ++pktpool_add(pktpool_t *pktp, void *p) ++{ ++ ASSERT(p != NULL); ++ ++ if (pktpool_len(pktp) == pktp->maxlen) ++ return BCME_RANGE; ++ ++ ASSERT(pktpool_plen(pktp) == PKTLEN(NULL, p)); /* pkts in pool have same length */ ++ PKTSETPOOL(NULL, p, TRUE, pktp); ++ ++ pktp->len++; ++ if (pktp->r > pktp->w) { ++ /* Add to tail */ ++ ASSERT(pktp->q[pktp->len - 1] == NULL); ++ pktp->q[pktp->len - 1] = p; ++ } else ++ pktpool_enq(pktp, p); ++ ++#ifdef BCMDBG_POOL ++ pktp->dbg_q[pktp->dbg_qlen++].p = p; ++#endif ++ ++ return 0; ++} ++ ++int ++pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen) ++{ ++ if (maxlen > PKTPOOL_LEN_MAX) ++ maxlen = PKTPOOL_LEN_MAX; ++ ++ /* if pool is already beyond maxlen, then just cap it ++ * since we currently do not reduce the pool len ++ * already allocated ++ */ ++ pktp->maxlen = (pktpool_len(pktp) > maxlen) ? pktpool_len(pktp) : maxlen; ++ ++ return pktp->maxlen; ++} ++ ++void ++pktpool_emptycb_disable(pktpool_t *pktp, bool disable) ++{ ++ ASSERT(pktp); ++ ++ pktp->emptycb_disable = disable; ++} ++ ++bool ++pktpool_emptycb_disabled(pktpool_t *pktp) ++{ ++ ASSERT(pktp); ++ return pktp->emptycb_disable; ++} ++ ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ if (len < 0) ++ len = 4096; /* "infinite" */ ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(PKTDATA(osh, p) + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++/* copy a buffer into a pkt buffer chain */ ++uint ++pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(buf, PKTDATA(osh, p) + offset, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++#ifdef NOTYET ++/* copy data from one pkt buffer (chain) to another */ ++uint ++pkt2pktcopy(osl_t *osh, void *p1, uint offs1, void *p2, uint offs2, int maxlen) ++{ ++ uint8 *dp1, *dp2; ++ uint len1, len2, copylen, totallen; ++ ++ for (; p1 && offs; p1 = PKTNEXT(osh, p1)) { ++ if (offs1 < (uint)PKTLEN(osh, p1)) ++ break; ++ offs1 -= PKTLEN(osh, p1); ++ } ++ for (; p2 && offs; p2 = PKTNEXT(osh, p2)) { ++ if (offs2 < (uint)PKTLEN(osh, p2)) ++ break; ++ offs2 -= PKTLEN(osh, p2); ++ } ++ ++ /* Heck w/it, only need the above for now */ ++} ++#endif /* NOTYET */ ++ ++ ++/* return total length of buffer chain */ ++uint BCMFASTPATH ++pkttotlen(osl_t *osh, void *p) ++{ ++ uint total; ++ int len; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) { ++ len = PKTLEN(osh, p); ++#ifdef MACOSX ++ if (len < 0) { ++ /* Bad packet length, just drop and exit */ ++ printf("wl: pkttotlen bad (%p,%d)\n", p, len); ++ break; ++ } ++#endif /* MACOSX */ ++ total += len; ++ } ++ ++ return (total); ++} ++ ++/* return the last buffer of chained pkt */ ++void * ++pktlast(osl_t *osh, void *p) ++{ ++ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) ++ ; ++ ++ return (p); ++} ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt(osl_t *osh, void *p) ++{ ++ uint cnt; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) ++ cnt++; ++ ++ return cnt; ++} ++ ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt_war(osl_t *osh, void *p) ++{ ++ uint cnt; ++ uint8 *pktdata; ++ uint len, remain, align64; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) { ++ cnt++; ++ len = PKTLEN(osh, p); ++ if (len > 128) { ++ pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */ ++ /* Check for page boundary straddle (2048B) */ ++ if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff)) ++ cnt++; ++ ++ align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */ ++ align64 = (64 - align64) & 0x3f; ++ len -= align64; /* bytes from aligned 64B to end */ ++ /* if aligned to 128B, check for MOD 128 between 1 to 4B */ ++ remain = len % 128; ++ if (remain > 0 && remain <= 4) ++ cnt++; /* add extra seg */ ++ } ++ } ++ ++ return cnt; ++} ++ ++uint8 * BCMFASTPATH ++pktdataoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint pkt_off = 0, len = 0; ++ uint8 *pdata = (uint8 *) PKTDATA(osh, p); ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ pdata = (uint8 *) PKTDATA(osh, p); ++ pkt_off = offset - len; ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return (uint8*) (pdata+pkt_off); ++} ++ ++ ++/* given a offset in pdata, find the pkt seg hdr */ ++void * ++pktoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint len = 0; ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return p; ++} ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty precedence ++ */ ++void * BCMFASTPATH ++pktq_penq(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ PKTSETLINK(q->tail, p); ++ else ++ q->head = p; ++ ++ q->tail = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_penq_head(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == NULL) ++ q->tail = p; ++ ++ PKTSETLINK(p, q->head); ++ q->head = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if (prev_p == NULL) ++ return NULL; ++ ++ if ((p = PKTLINK(prev_p)) == NULL) ++ return NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(prev_p, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_tail(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ return p; ++} ++ ++void ++pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ struct pktq_prec *q; ++ void *p, *prev = NULL; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ if (fn == NULL || (*fn)(p, arg)) { ++ bool head = (p == q->head); ++ if (head) ++ q->head = PKTLINK(p); ++ else ++ PKTSETLINK(prev, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ PKTFREE(osh, p, dir); ++ q->len--; ++ pq->len--; ++ p = (head ? q->head : PKTLINK(prev)); ++ } else { ++ prev = p; ++ p = PKTLINK(p); ++ } ++ } ++ ++ if (q->head == NULL) { ++ ASSERT(q->len == 0); ++ q->tail = NULL; ++ } ++} ++ ++bool BCMFASTPATH ++pktq_pdel(struct pktq *pq, void *pktbuf, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (!pktbuf) ++ return FALSE; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == pktbuf) { ++ if ((q->head = PKTLINK(pktbuf)) == NULL) ++ q->tail = NULL; ++ } else { ++ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) ++ ; ++ if (p == NULL) ++ return FALSE; ++ ++ PKTSETLINK(p, PKTLINK(pktbuf)); ++ if (q->tail == pktbuf) ++ q->tail = p; ++ } ++ ++ q->len--; ++ pq->len--; ++ PKTSETLINK(pktbuf, NULL); ++ return TRUE; ++} ++ ++void ++pktq_init(struct pktq *pq, int num_prec, int max_len) ++{ ++ int prec; ++ ++ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); ++ ++ /* pq is variable size; only zero out what's requested */ ++ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); ++ ++ pq->num_prec = (uint16)num_prec; ++ ++ pq->max = (uint16)max_len; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} ++ ++void ++pktq_set_max_plen(struct pktq *pq, int prec, int max_len) ++{ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (prec < pq->num_prec) ++ pq->q[prec].max = (uint16)max_len; ++} ++ ++void * BCMFASTPATH ++pktq_deq(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_deq_tail(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * ++pktq_peek(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].head); ++} ++ ++void * ++pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].tail); ++} ++ ++void ++pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ int prec; ++ ++ /* Optimize flush, if pktq len = 0, just return. ++ * pktq len of 0 means pktq's prec q's are all empty. ++ */ ++ if (pq->len == 0) { ++ return; ++ } ++ ++ for (prec = 0; prec < pq->num_prec; prec++) ++ pktq_pflush(osh, pq, prec, dir, fn, arg); ++ if (fn == NULL) ++ ASSERT(pq->len == 0); ++} ++ ++/* Return sum of lengths of a specific set of precedences */ ++int ++pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; ++ ++ len = 0; ++ ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; ++ ++ return len; ++} ++ ++/* Priority peek from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ { ++ return NULL; ++ } ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return p; ++} ++/* Priority dequeue from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0)) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++#endif /* BCMDRIVER */ ++ ++#if defined(BCMROMBUILD) ++const unsigned char BCMROMDATA(bcm_ctype)[] = { ++#else ++const unsigned char bcm_ctype[] = { ++#endif ++ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ ++ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, ++ _BCM_C, /* 8-15 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ ++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ ++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ ++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ ++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ ++ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, ++ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ ++ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, ++ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ ++ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ ++}; ++ ++ulong ++BCMROMFN(bcm_strtoul)(const char *cp, char **endp, uint base) ++{ ++ ulong result, last_result = 0, value; ++ bool minus; ++ ++ minus = FALSE; ++ ++ while (bcm_isspace(*cp)) ++ cp++; ++ ++ if (cp[0] == '+') ++ cp++; ++ else if (cp[0] == '-') { ++ minus = TRUE; ++ cp++; ++ } ++ ++ if (base == 0) { ++ if (cp[0] == '0') { ++ if ((cp[1] == 'x') || (cp[1] == 'X')) { ++ base = 16; ++ cp = &cp[2]; ++ } else { ++ base = 8; ++ cp = &cp[1]; ++ } ++ } else ++ base = 10; ++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { ++ cp = &cp[2]; ++ } ++ ++ result = 0; ++ ++ while (bcm_isxdigit(*cp) && ++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { ++ result = result*base + value; ++ /* Detected overflow */ ++ if (result < last_result && !minus) ++ return (ulong)-1; ++ last_result = result; ++ cp++; ++ } ++ ++ if (minus) ++ result = (ulong)(-(long)result); ++ ++ if (endp) ++ *endp = DISCARD_QUAL(cp, char); ++ ++ return (result); ++} ++ ++int ++BCMROMFN(bcm_atoi)(const char *s) ++{ ++ return (int)bcm_strtoul(s, NULL, 10); ++} ++ ++/* return pointer to location of substring 'needle' in 'haystack' */ ++char * ++BCMROMFN(bcmstrstr)(const char *haystack, const char *needle) ++{ ++ int len, nlen; ++ int i; ++ ++ if ((haystack == NULL) || (needle == NULL)) ++ return DISCARD_QUAL(haystack, char); ++ ++ nlen = strlen(needle); ++ len = strlen(haystack) - nlen + 1; ++ ++ for (i = 0; i < len; i++) ++ if (memcmp(needle, &haystack[i], nlen) == 0) ++ return DISCARD_QUAL(&haystack[i], char); ++ return (NULL); ++} ++ ++char * ++BCMROMFN(bcmstrcat)(char *dest, const char *src) ++{ ++ char *p; ++ ++ p = dest + strlen(dest); ++ ++ while ((*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++char * ++BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size) ++{ ++ char *endp; ++ char *p; ++ ++ p = dest + strlen(dest); ++ endp = p + size; ++ ++ while (p != endp && (*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrtok ++* ++* Purpose: ++* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), ++* but allows strToken() to be used by different strings or callers at the same ++* time. Each call modifies '*string' by substituting a NULL character for the ++* first delimiter that is encountered, and updates 'string' to point to the char ++* after the delimiter. Leading delimiters are skipped. ++* ++* Parameters: ++* string (mod) Ptr to string ptr, updated by token. ++* delimiters (in) Set of delimiter characters. ++* tokdelim (out) Character that delimits the returned token. (May ++* be set to NULL if token delimiter is not required). ++* ++* Returns: Pointer to the next token found. NULL when no more tokens are found. ++***************************************************************************** ++*/ ++char * ++bcmstrtok(char **string, const char *delimiters, char *tokdelim) ++{ ++ unsigned char *str; ++ unsigned long map[8]; ++ int count; ++ char *nextoken; ++ ++ if (tokdelim != NULL) { ++ /* Prime the token delimiter */ ++ *tokdelim = '\0'; ++ } ++ ++ /* Clear control map */ ++ for (count = 0; count < 8; count++) { ++ map[count] = 0; ++ } ++ ++ /* Set bits in delimiter table */ ++ do { ++ map[*delimiters >> 5] |= (1 << (*delimiters & 31)); ++ } ++ while (*delimiters++); ++ ++ str = (unsigned char*)*string; ++ ++ /* Find beginning of token (skip over leading delimiters). Note that ++ * there is no token iff this loop sets str to point to the terminal ++ * null (*str == '\0') ++ */ ++ while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { ++ str++; ++ } ++ ++ nextoken = (char*)str; ++ ++ /* Find the end of the token. If it is not the end of the string, ++ * put a null there. ++ */ ++ for (; *str; str++) { ++ if (map[*str >> 5] & (1 << (*str & 31))) { ++ if (tokdelim != NULL) { ++ *tokdelim = *str; ++ } ++ ++ *str++ = '\0'; ++ break; ++ } ++ } ++ ++ *string = (char*)str; ++ ++ /* Determine if a token has been found. */ ++ if (nextoken == (char *) str) { ++ return NULL; ++ } ++ else { ++ return nextoken; ++ } ++} ++ ++ ++#define xToLower(C) \ ++ ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) ++ ++ ++/**************************************************************************** ++* Function: bcmstricmp ++* ++* Purpose: Compare to strings case insensitively. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstricmp(const char *s1, const char *s2) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ } ++ ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrnicmp ++* ++* Purpose: Compare to strings case insensitively, upto a max of 'cnt' ++* characters. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* cnt (in) Max characters to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstrnicmp(const char* s1, const char* s2, int cnt) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1 && cnt) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ cnt--; ++ } ++ ++ if (!cnt) return 0; ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ ++int ++BCMROMFN(bcm_ether_atoe)(const char *p, struct ether_addr *ea) ++{ ++ int i = 0; ++ char *ep; ++ ++ for (;;) { ++ ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); ++ p = ep; ++ if (!*p++ || i == 6) ++ break; ++ } ++ ++ return (i == 6); ++} ++ ++ ++#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) ++/* registry routine buffer preparation utility functions: ++ * parameter order is like strncpy, but returns count ++ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) ++ */ ++ulong ++wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) ++{ ++ ulong copyct = 1; ++ ushort i; ++ ++ if (abuflen == 0) ++ return 0; ++ ++ /* wbuflen is in bytes */ ++ wbuflen /= sizeof(ushort); ++ ++ for (i = 0; i < wbuflen; ++i) { ++ if (--abuflen == 0) ++ break; ++ *abuf++ = (char) *wbuf++; ++ ++copyct; ++ } ++ *abuf = '\0'; ++ ++ return copyct; ++} ++#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ ++ ++char * ++bcm_ether_ntoa(const struct ether_addr *ea, char *buf) ++{ ++ static const char hex[] = ++ { ++ '0', '1', '2', '3', '4', '5', '6', '7', ++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ++ }; ++ const uint8 *octet = ea->octet; ++ char *p = buf; ++ int i; ++ ++ for (i = 0; i < 6; i++, octet++) { ++ *p++ = hex[(*octet >> 4) & 0xf]; ++ *p++ = hex[*octet & 0xf]; ++ *p++ = ':'; ++ } ++ ++ *(p-1) = '\0'; ++ ++ return (buf); ++} ++ ++char * ++bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) ++{ ++ snprintf(buf, 16, "%d.%d.%d.%d", ++ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); ++ return (buf); ++} ++ ++#ifdef BCMDRIVER ++ ++void ++bcm_mdelay(uint ms) ++{ ++ uint i; ++ ++ for (i = 0; i < ms; i++) { ++ OSL_DELAY(1000); ++ } ++} ++ ++/* ++ * Search the name=value vars for a specific one and return its value. ++ * Returns NULL if not found. ++ */ ++char * ++getvar(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return NULL; ++#else ++ char *s; ++ int len; ++ ++ if (!name) ++ return NULL; ++ ++ len = strlen(name); ++ if (len == 0) ++ return NULL; ++ ++ /* first look in vars[] */ ++ for (s = vars; s && *s;) { ++ if ((bcmp(s, name, len) == 0) && (s[len] == '=') && (strlen(s)==len)) ++ return (&s[len+1]); ++ ++ while (*s++) ++ ; ++ } ++ ++ /* then query nvram */ ++ return (nvram_get(name)); ++#endif /* defined(_MINOSL_) */ ++} ++ ++/* ++ * Search the vars for a specific one and return its value as ++ * an integer. Returns 0 if not found. ++ */ ++int ++getintvar(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *val; ++ ++ if ((val = getvar(vars, name)) == NULL) ++ return (0); ++ ++ return (bcm_strtoul(val, NULL, 0)); ++#endif /* _MINOSL_ */ ++} ++ ++int ++getintvararray(char *vars, const char *name, int index) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *buf, *endp; ++ int i = 0; ++ int val = 0; ++ ++ if ((buf = getvar(vars, name)) == NULL) { ++ return (0); ++ } ++ ++ /* table values are always separated by "," or " " */ ++ while (*buf != '\0') { ++ val = bcm_strtoul(buf, &endp, 0); ++ if (i == index) { ++ return val; ++ } ++ buf = endp; ++ /* delimiter is ',' */ ++ if (*buf == ',') ++ buf++; ++ i++; ++ } ++ return 0; ++#endif /* _MINOSL_ */ ++} ++ ++int ++getintvararraysize(char *vars, const char *name) ++{ ++#ifdef _MINOSL_ ++ return 0; ++#else ++ char *buf, *endp; ++ int count = 0; ++ int val = 0; ++ ++ if ((buf = getvar(vars, name)) == NULL) { ++ return (0); ++ } ++ ++ /* table values are always separated by "," or " " */ ++ while (*buf != '\0') { ++ val = bcm_strtoul(buf, &endp, 0); ++ buf = endp; ++ /* delimiter is ',' */ ++ if (*buf == ',') ++ buf++; ++ count++; ++ } ++ BCM_REFERENCE(val); ++ return count; ++#endif /* _MINOSL_ */ ++} ++ ++/* Search for token in comma separated token-string */ ++static int ++findmatch(const char *string, const char *name) ++{ ++ uint len; ++ char *c; ++ ++ len = strlen(name); ++ while ((c = strchr(string, ',')) != NULL) { ++ if (len == (uint)(c - string) && !strncmp(string, name, len)) ++ return 1; ++ string = c + 1; ++ } ++ ++ return (!strcmp(string, name)); ++} ++ ++/* Return gpio pin number assigned to the named pin ++ * ++ * Variable should be in format: ++ * ++ * gpio=pin_name,pin_name ++ * ++ * This format allows multiple features to share the gpio with mutual ++ * understanding. ++ * ++ * 'def_pin' is returned if a specific gpio is not defined for the requested functionality ++ * and if def_pin is not used by others. ++ */ ++uint ++getgpiopin(char *vars, char *pin_name, uint def_pin) ++{ ++ char name[] = "gpioXXXX"; ++ char *val; ++ uint pin; ++ ++ /* Go thru all possibilities till a match in pin name */ ++ for (pin = 0; pin < GPIO_NUMPINS; pin ++) { ++ snprintf(name, sizeof(name), "gpio%d", pin); ++ val = getvar(vars, name); ++ if (val && findmatch(val, pin_name)) ++ return pin; ++ } ++ ++ if (def_pin != GPIO_PIN_NOTDEFINED) { ++ /* make sure the default pin is not used by someone else */ ++ snprintf(name, sizeof(name), "gpio%d", def_pin); ++ if (getvar(vars, name)) { ++ def_pin = GPIO_PIN_NOTDEFINED; ++ } ++ } ++ return def_pin; ++} ++ ++ ++/* Return the WAN port number ++ * ++ * 0 is returned if no wanport is configured. ++ */ ++int ++getwanport(void) ++{ ++ char name[] = "wanport"; ++ int retval; ++ ++ retval = getintvar(NULL, name); ++ return retval; ++} ++ ++ ++/* Return the brcmtag variable ++ * ++ * 0 is returned if no wanport is configured. ++ */ ++int ++getbrcmtag(void) ++{ ++ char name[] = "brcmtag"; ++ int retval; ++ ++ retval = getintvar(NULL, name); ++ return retval; ++} ++ ++ ++#if defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) ++ ++#define LOGSIZE 256 /* should be power of 2 to avoid div below */ ++static struct { ++ uint cycles; ++ char *fmt; ++ uint a1; ++ uint a2; ++} logtab[LOGSIZE]; ++ ++/* last entry logged */ ++static uint logi = 0; ++/* next entry to read */ ++static uint readi = 0; ++#endif /* defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) */ ++ ++#ifdef BCMPERFSTATS ++void ++bcm_perf_enable() ++{ ++ BCMPERF_ENABLE_INSTRCOUNT(); ++ BCMPERF_ENABLE_ICACHE_MISS(); ++ BCMPERF_ENABLE_ICACHE_HIT(); ++} ++ ++/* WARNING: This routine uses OSL_GETCYCLES(), which can give unexpected results on ++ * modern speed stepping CPUs. Use bcmtslog() instead in combination with TSF counter. ++ */ ++void ++bcmlog(char *fmt, uint a1, uint a2) ++{ ++ static uint last = 0; ++ uint cycles, i; ++ OSL_GETCYCLES(cycles); ++ ++ i = logi; ++ ++ logtab[i].cycles = cycles - last; ++ logtab[i].fmt = fmt; ++ logtab[i].a1 = a1; ++ logtab[i].a2 = a2; ++ ++ logi = (i + 1) % LOGSIZE; ++ last = cycles; ++} ++ ++ ++void ++bcmstats(char *fmt) ++{ ++ static uint last = 0; ++ static uint32 ic_miss = 0; ++ static uint32 instr_count = 0; ++ uint32 ic_miss_cur; ++ uint32 instr_count_cur; ++ uint cycles, i; ++ ++ OSL_GETCYCLES(cycles); ++ BCMPERF_GETICACHE_MISS(ic_miss_cur); ++ BCMPERF_GETINSTRCOUNT(instr_count_cur); ++ ++ i = logi; ++ ++ logtab[i].cycles = cycles - last; ++ logtab[i].a1 = ic_miss_cur - ic_miss; ++ logtab[i].a2 = instr_count_cur - instr_count; ++ logtab[i].fmt = fmt; ++ ++ logi = (i + 1) % LOGSIZE; ++ ++ last = cycles; ++ instr_count = instr_count_cur; ++ ic_miss = ic_miss_cur; ++} ++ ++ ++void ++bcmdumplog(char *buf, int size) ++{ ++ char *limit; ++ int j = 0; ++ int num; ++ ++ limit = buf + size - 80; ++ *buf = '\0'; ++ ++ num = logi - readi; ++ ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* print in chronological order */ ++ ++ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); ++ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, ++ logtab[readi].a2); ++ buf += snprintf(buf, (limit - buf), "\n"); ++ } ++ ++} ++ ++ ++/* ++ * Dump one log entry at a time. ++ * Return index of next entry or -1 when no more . ++ */ ++int ++bcmdumplogent(char *buf, uint i) ++{ ++ bool hit; ++ ++ /* ++ * If buf is NULL, return the starting index, ++ * interpreting i as the indicator of last 'i' entries to dump. ++ */ ++ if (buf == NULL) { ++ i = ((i > 0) && (i < (LOGSIZE - 1))) ? i : (LOGSIZE - 1); ++ return ((logi - i) % LOGSIZE); ++ } ++ ++ *buf = '\0'; ++ ++ ASSERT(i < LOGSIZE); ++ ++ if (i == logi) ++ return (-1); ++ ++ hit = FALSE; ++ for (; (i != logi) && !hit; i = (i + 1) % LOGSIZE) { ++ if (logtab[i].fmt == NULL) ++ continue; ++ buf += sprintf(buf, "%d: %d\t", i, logtab[i].cycles); ++ buf += sprintf(buf, logtab[i].fmt, logtab[i].a1, logtab[i].a2); ++ buf += sprintf(buf, "\n"); ++ hit = TRUE; ++ } ++ ++ return (i); ++} ++ ++#endif /* BCMPERFSTATS */ ++ ++#if defined(BCMTSTAMPEDLOGS) ++/* Store a TSF timestamp and a log line in the log buffer */ ++void ++bcmtslog(uint32 tstamp, char *fmt, uint a1, uint a2) ++{ ++ uint i = logi; ++ bool use_delta = FALSE; ++ static uint32 last = 0; /* used only when use_delta is true */ ++ ++ logtab[i].cycles = tstamp; ++ if (use_delta) ++ logtab[i].cycles -= last; ++ ++ logtab[i].fmt = fmt; ++ logtab[i].a1 = a1; ++ logtab[i].a2 = a2; ++ ++ if (use_delta) ++ last = tstamp; ++ logi = (i + 1) % LOGSIZE; ++} ++ ++/* Print out a microsecond timestamp as "sec.ms.us " */ ++void ++bcmprinttstamp(uint32 ticks) ++{ ++ uint us, ms, sec; ++ ++ us = (ticks % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; ++ ms = ticks / TSF_TICKS_PER_MS; ++ sec = ms / 1000; ++ ms -= sec * 1000; ++ printf("%04u.%03u.%03u ", sec, ms, us); ++} ++ ++/* Print out the log buffer with timestamps */ ++void ++bcmprinttslogs(void) ++{ ++ int j = 0; ++ int num; ++ ++ num = logi - readi; ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* Format and print the log entries directly in chronological order */ ++ for (j = 0; j < num; readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ bcmprinttstamp(logtab[readi].cycles); ++ printf(logtab[readi].fmt, logtab[readi].a1, logtab[readi].a2); ++ printf("\n"); ++ } ++} ++ ++void ++bcmdumptslog(char *buf, int size) ++{ ++ char *limit; ++ int j = 0; ++ int num; ++ uint us, ms, sec; ++ ++ limit = buf + size - 80; ++ *buf = '\0'; ++ ++ num = logi - readi; ++ ++ if (num < 0) ++ num += LOGSIZE; ++ ++ /* print in chronological order */ ++ for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) { ++ if (logtab[readi].fmt == NULL) ++ continue; ++ us = (logtab[readi].cycles % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS; ++ ms = logtab[readi].cycles / TSF_TICKS_PER_MS; ++ sec = ms / 1000; ++ ms -= sec * 1000; ++ ++ buf += snprintf(buf, (limit - buf), "%04u.%03u.%03u ", sec, ms, us); ++ /* buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles); */ ++ buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1, ++ logtab[readi].a2); ++ buf += snprintf(buf, (limit - buf), "\n"); ++ } ++} ++ ++#endif /* BCMTSTAMPEDLOGS */ ++ ++#if defined(BCMDBG) || defined(DHD_DEBUG) ++/* pretty hex print a pkt buffer chain */ ++void ++prpkt(const char *msg, osl_t *osh, void *p0) ++{ ++ void *p; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("%s:\n", msg); ++ ++ for (p = p0; p; p = PKTNEXT(osh, p)) ++ prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); ++} ++#endif /* BCMDBG || DHD_DEBUG */ ++ ++/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. ++ * Also updates the inplace vlan tag if requested. ++ * For debugging, it returns an indication of what it did. ++ */ ++uint BCMFASTPATH ++pktsetprio(void *pkt, bool update_vtag) ++{ ++ struct ether_header *eh; ++ struct ethervlan_header *evh; ++ uint8 *pktdata; ++ int priority = 0; ++ int rc = 0; ++ ++ pktdata = (uint8 *)PKTDATA(NULL, pkt); ++ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); ++ ++ eh = (struct ether_header *) pktdata; ++ ++ if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { ++ uint16 vlan_tag; ++ int vlan_prio, dscp_prio = 0; ++ ++ evh = (struct ethervlan_header *)eh; ++ ++ vlan_tag = ntoh16(evh->vlan_tag); ++ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; ++ ++ if (evh->ether_type == hton16(ETHER_TYPE_IP)) { ++ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ } ++ ++ /* DSCP priority gets precedence over 802.1P (vlan tag) */ ++ if (dscp_prio != 0) { ++ priority = dscp_prio; ++ rc |= PKTPRIO_VDSCP; ++ } else { ++ priority = vlan_prio; ++ rc |= PKTPRIO_VLAN; ++ } ++ /* ++ * If the DSCP priority is not the same as the VLAN priority, ++ * then overwrite the priority field in the vlan tag, with the ++ * DSCP priority value. This is required for Linux APs because ++ * the VLAN driver on Linux, overwrites the skb->priority field ++ * with the priority value in the vlan tag ++ */ ++ if (update_vtag && (priority != vlan_prio)) { ++ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); ++ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; ++ evh->vlan_tag = hton16(vlan_tag); ++ rc |= PKTPRIO_UPD; ++ } ++ } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) { ++ uint8 *ip_body = pktdata + sizeof(struct ether_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ rc |= PKTPRIO_DSCP; ++ } ++ ++ ASSERT(priority >= 0 && priority <= MAXPRIO); ++ PKTSETPRIO(pkt, priority); ++ return (rc | priority); ++} ++ ++#ifndef BCM_BOOTLOADER ++ ++static char bcm_undeferrstr[32]; ++static const char *const bcmerrorstrtable[] = BCMERRSTRINGTABLE; ++ ++/* Convert the error codes into related error strings */ ++const char * ++bcmerrorstr(int bcmerror) ++{ ++ /* check if someone added a bcmerror code but forgot to add errorstring */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); ++ ++ if (bcmerror > 0 || bcmerror < BCME_LAST) { ++ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); ++ return bcm_undeferrstr; ++ } ++ ++ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); ++ ++ return bcmerrorstrtable[-bcmerror]; ++} ++ ++#endif /* !BCM_BOOTLOADER */ ++ ++#ifdef WLC_LOW ++static void ++BCMINITFN(bcm_nvram_refresh)(char *flash) ++{ ++ int i; ++ int ret = 0; ++ ++ ASSERT(flash != NULL); ++ ++ /* default "empty" vars cache */ ++ bzero(flash, 2); ++ ++ if ((ret = nvram_getall(flash, NVRAM_SPACE))) ++ return; ++ ++ /* determine nvram length */ ++ for (i = 0; i < NVRAM_SPACE; i++) { ++ if (flash[i] == '\0' && flash[i+1] == '\0') ++ break; ++ } ++ ++ if (i > 1) ++ vars_len = i + 2; ++ else ++ vars_len = 0; ++} ++ ++char * ++bcm_nvram_vars(uint *length) ++{ ++#ifndef BCMNVRAMR ++ /* cache may be stale if nvram is read/write */ ++ if (nvram_vars) { ++ ASSERT(!bcmreclaimed); ++ bcm_nvram_refresh(nvram_vars); ++ } ++#endif ++ if (length) ++ *length = vars_len; ++ return nvram_vars; ++} ++ ++/* copy nvram vars into locally-allocated multi-string array */ ++int ++BCMINITFN(bcm_nvram_cache)(void *sih) ++{ ++ int ret = 0; ++ void *osh; ++ char *flash = NULL; ++ ++ if (vars_len >= 0) { ++#ifndef BCMNVRAMR ++ bcm_nvram_refresh(nvram_vars); ++#endif ++ return 0; ++ } ++ ++ osh = si_osh((si_t *)sih); ++ ++ /* allocate memory and read in flash */ ++ if (!(flash = MALLOC(osh, NVRAM_SPACE))) { ++ ret = BCME_NOMEM; ++ goto exit; ++ } ++ ++ bcm_nvram_refresh(flash); ++ ++#ifdef BCMNVRAMR ++ if (vars_len > 3) { ++ /* copy into a properly-sized buffer */ ++ if (!(nvram_vars = MALLOC(osh, vars_len))) { ++ ret = BCME_NOMEM; ++ } else ++ bcopy(flash, nvram_vars, vars_len); ++ } ++ MFREE(osh, flash, NVRAM_SPACE); ++#else ++ /* cache must be full size of nvram if read/write */ ++ nvram_vars = flash; ++#endif /* BCMNVRAMR */ ++ ++exit: ++ return ret; ++} ++#endif /* WLC_LOW */ ++ ++ ++int32 ++exthdr_validate(char *ptr, uint size) ++{ ++ char *exthdr, *trx_offset; ++ uint hdrsz; ++ int trxof = 0; ++ ++ if ((exthdr = nvram_get("ext_imghdr"))) { ++ char s[] = "XXX"; ++ uint i, j; ++ ++ hdrsz = strlen(exthdr); ++ ++ if (hdrsz > size) { ++ printf("Exthdr_size(%d) > Image_size(%d)\n", hdrsz, size); ++ trxof = -1; ++ goto done; ++ } ++ ++ if (hdrsz == 0) ++ goto match; ++ ++ for (i = 0, j = 0; i < (hdrsz >> 1); i++) { ++ sprintf(s, "%02x", (ptr[i] & 0xff)); ++ if ((exthdr[j++] != s[0]) || (exthdr[j++] != s[1])) { ++ printf("Header mismatch\n"); ++ goto done; ++ } ++ } ++ } ++ ++match: ++ if ((trx_offset = nvram_get("trx_offset"))) ++ trxof = bcm_strtoul(trx_offset, NULL, 0); ++ ++done: ++ return trxof; ++} ++ ++/* iovar table lookup */ ++const bcm_iovar_t* ++bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) ++{ ++ const bcm_iovar_t *vi; ++ const char *lookup_name; ++ ++ /* skip any ':' delimited option prefixes */ ++ lookup_name = strrchr(name, ':'); ++ if (lookup_name != NULL) ++ lookup_name++; ++ else ++ lookup_name = name; ++ ++ ASSERT(table != NULL); ++ ++ for (vi = table; vi->name; vi++) { ++ if (!strcmp(vi->name, lookup_name)) ++ return vi; ++ } ++ /* ran to end of table */ ++ ++ return NULL; /* var name not found */ ++} ++ ++int ++bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) ++{ ++ int bcmerror = 0; ++ ++ /* length check on io buf */ ++ switch (vi->type) { ++ case IOVT_BOOL: ++ case IOVT_INT8: ++ case IOVT_INT16: ++ case IOVT_INT32: ++ case IOVT_UINT8: ++ case IOVT_UINT16: ++ case IOVT_UINT32: ++ /* all integers are int32 sized args at the ioctl interface */ ++ if (len < (int)sizeof(int)) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_BUFFER: ++ /* buffer must meet minimum length requirement */ ++ if (len < vi->minlen) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_VOID: ++ if (!set) { ++ /* Cannot return nil... */ ++ bcmerror = BCME_UNSUPPORTED; ++ } else if (len) { ++ /* Set is an action w/o parameters */ ++ bcmerror = BCME_BUFTOOLONG; ++ } ++ break; ++ ++ default: ++ /* unknown type for length check in iovar info */ ++ ASSERT(0); ++ bcmerror = BCME_UNSUPPORTED; ++ } ++ ++ return bcmerror; ++} ++ ++#endif /* BCMDRIVER */ ++ ++ ++/******************************************************************************* ++ * crc8 ++ * ++ * Computes a crc8 over the input data using the polynomial: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ * ++ * The caller provides the initial value (either CRC8_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC8_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint8 crc8_table[256] = { ++ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F ++}; ++ ++#define CRC_INNER_LOOP(n, c, x) \ ++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] ++ ++uint8 ++BCMROMFN(hndcrc8)( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ ++) ++{ ++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro ++ * to avoid the undefined and unnecessary (uint8 >> 8) operation. ++ */ ++ while (nbytes-- > 0) ++ crc = crc8_table[(crc ^ *pdata++) & 0xff]; ++ ++ return crc; ++} ++ ++/******************************************************************************* ++ * crc16 ++ * ++ * Computes a crc16 over the input data using the polynomial: ++ * ++ * x^16 + x^12 +x^5 + 1 ++ * ++ * The caller provides the initial value (either CRC16_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC16_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint16 crc16_table[256] = { ++ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, ++ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, ++ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, ++ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, ++ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, ++ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, ++ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, ++ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, ++ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, ++ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, ++ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, ++ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, ++ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, ++ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, ++ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, ++ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, ++ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, ++ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, ++ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, ++ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, ++ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, ++ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, ++ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, ++ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, ++ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, ++ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, ++ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, ++ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, ++ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, ++ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, ++ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, ++ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 ++}; ++ ++uint16 ++BCMROMFN(hndcrc16)( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint16 crc /* either CRC16_INIT_VALUE or previous return value */ ++) ++{ ++ while (nbytes-- > 0) ++ CRC_INNER_LOOP(16, crc, *pdata++); ++ return crc; ++} ++ ++static const uint32 crc32_table[256] = { ++ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, ++ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, ++ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, ++ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, ++ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, ++ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, ++ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, ++ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, ++ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, ++ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, ++ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, ++ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, ++ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, ++ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, ++ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, ++ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, ++ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, ++ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, ++ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, ++ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, ++ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, ++ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, ++ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, ++ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, ++ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, ++ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, ++ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, ++ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, ++ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, ++ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, ++ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, ++ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, ++ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, ++ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, ++ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, ++ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, ++ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, ++ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, ++ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, ++ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, ++ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, ++ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, ++ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, ++ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, ++ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, ++ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, ++ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, ++ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, ++ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, ++ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, ++ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, ++ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, ++ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, ++ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, ++ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, ++ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, ++ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, ++ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, ++ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, ++ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, ++ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, ++ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, ++ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, ++ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D ++}; ++ ++/* ++ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if ++ * accumulating over multiple pieces. ++ */ ++uint32 ++BCMROMFN(hndcrc32)(uint8 *pdata, uint nbytes, uint32 crc) ++{ ++ uint8 *pend; ++#ifdef __mips__ ++ uint8 tmp[4]; ++ ulong *tptr = (ulong *)tmp; ++ ++ if (nbytes > 3) { ++ /* in case the beginning of the buffer isn't aligned */ ++ pend = (uint8 *)((uint)(pdata + 3) & ~0x3); ++ nbytes -= (pend - pdata); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++ } ++ ++ if (nbytes > 3) { ++ /* handle bulk of data as 32-bit words */ ++ pend = pdata + (nbytes & ~0x3); ++ while (pdata < pend) { ++ *tptr = *(ulong *)pdata; ++ pdata += sizeof(ulong *); ++ CRC_INNER_LOOP(32, crc, tmp[0]); ++ CRC_INNER_LOOP(32, crc, tmp[1]); ++ CRC_INNER_LOOP(32, crc, tmp[2]); ++ CRC_INNER_LOOP(32, crc, tmp[3]); ++ } ++ } ++ ++ /* 1-3 bytes at end of buffer */ ++ pend = pdata + (nbytes & 0x03); ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#else ++ pend = pdata + nbytes; ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++#endif /* __mips__ */ ++ ++ return crc; ++} ++ ++#ifdef notdef ++#define CLEN 1499 /* CRC Length */ ++#define CBUFSIZ (CLEN+4) ++#define CNBUFS 5 /* # of bufs */ ++ ++void ++testcrc32(void) ++{ ++ uint j, k, l; ++ uint8 *buf; ++ uint len[CNBUFS]; ++ uint32 crcr; ++ uint32 crc32tv[CNBUFS] = ++ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; ++ ++ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); ++ ++ /* step through all possible alignments */ ++ for (l = 0; l <= 4; l++) { ++ for (j = 0; j < CNBUFS; j++) { ++ len[j] = CLEN; ++ for (k = 0; k < len[j]; k++) ++ *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; ++ } ++ ++ for (j = 0; j < CNBUFS; j++) { ++ crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); ++ ASSERT(crcr == crc32tv[j]); ++ } ++ } ++ ++ MFREE(buf, CBUFSIZ*CNBUFS); ++ return; ++} ++#endif /* notdef */ ++ ++/* ++ * Advance from the current 1-byte tag/1-byte length/variable-length value ++ * triple, to the next, returning a pointer to the next. ++ * If the current or next TLV is invalid (does not fit in given buffer length), ++ * NULL is returned. ++ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented ++ * by the TLV parameter's length if it is valid. ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen) ++{ ++ int len; ++ ++ /* validate current elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ /* advance to next elt */ ++ len = elt->len; ++ elt = (bcm_tlv_t*)(elt->data + len); ++ *buflen -= (TLV_HDR_LEN + len); ++ ++ /* validate next elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ return elt; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ int len = elt->len; ++ ++ /* validate remaining totlen */ ++ if ((elt->id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag. Stop parsing when we see an element whose ID is greater ++ * than the target key. ++ */ ++bcm_tlv_t * ++BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ uint id = elt->id; ++ int len = elt->len; ++ ++ /* Punt if we start seeing IDs > than target key */ ++ if (id > key) ++ return (NULL); ++ ++ /* validate remaining totlen */ ++ if ((id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ return NULL; ++} ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(WLMSG_PRHDRS) || \ ++ defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || defined(DHD_DEBUG) ++int ++bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) ++{ ++ int i; ++ char* p = buf; ++ char hexstr[16]; ++ int slen = 0, nlen = 0; ++ uint32 bit; ++ const char* name; ++ ++ if (len < 2 || !buf) ++ return 0; ++ ++ buf[0] = '\0'; ++ ++ for (i = 0; flags != 0; i++) { ++ bit = bd[i].bit; ++ name = bd[i].name; ++ if (bit == 0 && flags != 0) { ++ /* print any unnamed bits */ ++ snprintf(hexstr, 16, "0x%X", flags); ++ name = hexstr; ++ flags = 0; /* exit loop */ ++ } else if ((flags & bit) == 0) ++ continue; ++ flags &= ~bit; ++ nlen = strlen(name); ++ slen += nlen; ++ /* count btwn flag space */ ++ if (flags != 0) ++ slen += 1; ++ /* need NULL char as well */ ++ if (len <= slen) ++ break; ++ /* copy NULL char but don't count it */ ++ strncpy(p, name, nlen + 1); ++ p += nlen; ++ /* copy btwn flag space and NULL char */ ++ if (flags != 0) ++ p += snprintf(p, 2, " "); ++ } ++ ++ /* indicate the str was too short */ ++ if (flags != 0) { ++ if (len < 2) ++ p -= 2 - len; /* overwrite last char */ ++ p += snprintf(p, 2, ">"); ++ } ++ ++ return (int)(p - buf); ++} ++ ++/* print bytes formatted as hex to a string. return the resulting string length */ ++int ++bcm_format_hex(char *str, const void *bytes, int len) ++{ ++ int i; ++ char *p = str; ++ const uint8 *src = (const uint8*)bytes; ++ ++ for (i = 0; i < len; i++) { ++ p += snprintf(p, 3, "%02X", *src); ++ src++; ++ } ++ return (int)(p - str); ++} ++#endif ++ ++/* pretty hex print a contiguous buffer */ ++void ++prhex(const char *msg, uchar *buf, uint nbytes) ++{ ++ char line[128], *p; ++ int len = sizeof(line); ++ int nchar; ++ uint i; ++ ++ if (msg && (msg[0] != '\0')) ++ printf("%s:\n", msg); ++ ++ p = line; ++ for (i = 0; i < nbytes; i++) { ++ if (i % 16 == 0) { ++ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */ ++ p += nchar; ++ len -= nchar; ++ } ++ if (len > 0) { ++ nchar = snprintf(p, len, "%02x ", buf[i]); ++ p += nchar; ++ len -= nchar; ++ } ++ ++ if (i % 16 == 15) { ++ printf("%s\n", line); /* flush line */ ++ p = line; ++ len = sizeof(line); ++ } ++ } ++ ++ /* flush last partial line */ ++ if (p != line) ++ printf("%s\n", line); ++} ++ ++static const char *crypto_algo_names[] = { ++ "NONE", ++ "WEP1", ++ "TKIP", ++ "WEP128", ++ "AES_CCM", ++ "AES_OCB_MSDU", ++ "AES_OCB_MPDU", ++ "NALG" ++ "UNDEF", ++ "UNDEF", ++ "UNDEF", ++ "UNDEF" ++}; ++ ++const char * ++bcm_crypto_algo_name(uint algo) ++{ ++ return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; ++} ++ ++#ifdef BCMDBG ++void ++deadbeef(void *p, size_t len) ++{ ++ static uint8 meat[] = { 0xde, 0xad, 0xbe, 0xef }; ++ ++ while (len-- > 0) { ++ *(uint8*)p = meat[((uintptr)p) & 3]; ++ p = (uint8*)p + 1; ++ } ++} ++#endif /* BCMDBG */ ++ ++char * ++bcm_chipname(uint chipid, char *buf, uint len) ++{ ++ const char *fmt; ++ ++ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; ++ snprintf(buf, len, fmt, chipid); ++ return buf; ++} ++ ++/* Produce a human-readable string for boardrev */ ++char * ++bcm_brev_str(uint32 brev, char *buf) ++{ ++ if (brev < 0x100) ++ snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); ++ else ++ snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); ++ ++ return (buf); ++} ++ ++#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ ++ ++/* dump large strings to console */ ++void ++printbig(char *buf) ++{ ++ uint len, max_len; ++ char c; ++ ++ len = strlen(buf); ++ ++ max_len = BUFSIZE_TODUMP_ATONCE; ++ ++ while (len > max_len) { ++ c = buf[max_len]; ++ buf[max_len] = '\0'; ++ printf("%s", buf); ++ buf[max_len] = c; ++ ++ buf += max_len; ++ len -= max_len; ++ } ++ /* print the remaining string */ ++ printf("%s\n", buf); ++ return; ++} ++ ++/* routine to dump fields in a fileddesc structure */ ++uint ++bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, ++ char *buf, uint32 bufsize) ++{ ++ uint filled_len; ++ int len; ++ struct fielddesc *cur_ptr; ++ ++ filled_len = 0; ++ cur_ptr = fielddesc_array; ++ ++ while (bufsize > 1) { ++ if (cur_ptr->nameandfmt == NULL) ++ break; ++ len = snprintf(buf, bufsize, cur_ptr->nameandfmt, ++ read_rtn(arg0, arg1, cur_ptr->offset)); ++ /* check for snprintf overflow or error */ ++ if (len < 0 || (uint32)len >= bufsize) ++ len = bufsize - 1; ++ buf += len; ++ bufsize -= len; ++ filled_len += len; ++ cur_ptr++; ++ } ++ return filled_len; ++} ++ ++uint ++bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++{ ++ uint len; ++ ++ len = strlen(name) + 1; ++ ++ if ((len + datalen) > buflen) ++ return 0; ++ ++ strncpy(buf, name, buflen); ++ ++ /* append data onto the end of the name string */ ++ memcpy(&buf[len], data, datalen); ++ len += datalen; ++ ++ return len; ++} ++ ++/* Quarter dBm units to mW ++ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 ++ * Table is offset so the last entry is largest mW value that fits in ++ * a uint16. ++ */ ++ ++#define QDBM_OFFSET 153 /* Offset for first entry */ ++#define QDBM_TABLE_LEN 40 /* Table size */ ++ ++/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. ++ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 ++ */ ++#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ ++ ++/* Largest mW value that will round down to the last table entry, ++ * QDBM_OFFSET + QDBM_TABLE_LEN-1. ++ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. ++ */ ++#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ ++ ++static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { ++/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ ++/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, ++/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, ++/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, ++/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, ++/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 ++}; ++ ++uint16 ++BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm) ++{ ++ uint factor = 1; ++ int idx = qdbm - QDBM_OFFSET; ++ ++ if (idx >= QDBM_TABLE_LEN) { ++ /* clamp to max uint16 mW value */ ++ return 0xFFFF; ++ } ++ ++ /* scale the qdBm index up to the range of the table 0-40 ++ * where an offset of 40 qdBm equals a factor of 10 mW. ++ */ ++ while (idx < 0) { ++ idx += 40; ++ factor *= 10; ++ } ++ ++ /* return the mW value scaled down to the correct factor of 10, ++ * adding in factor/2 to get proper rounding. ++ */ ++ return ((nqdBm_to_mW_map[idx] + factor/2) / factor); ++} ++ ++uint8 ++BCMROMFN(bcm_mw_to_qdbm)(uint16 mw) ++{ ++ uint8 qdbm; ++ int offset; ++ uint mw_uint = mw; ++ uint boundary; ++ ++ /* handle boundary case */ ++ if (mw_uint <= 1) ++ return 0; ++ ++ offset = QDBM_OFFSET; ++ ++ /* move mw into the range of the table */ ++ while (mw_uint < QDBM_TABLE_LOW_BOUND) { ++ mw_uint *= 10; ++ offset -= 40; ++ } ++ ++ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { ++ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - ++ nqdBm_to_mW_map[qdbm])/2; ++ if (mw_uint < boundary) break; ++ } ++ ++ qdbm += (uint8)offset; ++ ++ return (qdbm); ++} ++ ++ ++uint ++BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint length) ++{ ++ uint bitcount = 0, i; ++ uint8 tmp; ++ for (i = 0; i < length; i++) { ++ tmp = bitmap[i]; ++ while (tmp) { ++ bitcount++; ++ tmp &= (tmp - 1); ++ } ++ } ++ return bitcount; ++} ++ ++#ifdef BCMDRIVER ++ ++/* Initialization of bcmstrbuf structure */ ++void ++bcm_binit(struct bcmstrbuf *b, char *buf, uint size) ++{ ++ b->origsize = b->size = size; ++ b->origbuf = b->buf = buf; ++} ++ ++/* Buffer sprintf wrapper to guard against buffer overflow */ ++int ++bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ ++ va_start(ap, fmt); ++ ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ ++ /* Non Ansi C99 compliant returns -1, ++ * Ansi compliant return r >= b->size, ++ * bcmstdlib returns 0, handle all ++ */ ++ /* r == 0 is also the case when strlen(fmt) is zero. ++ * typically the case when "" is passed as argument. ++ */ ++ if ((r == -1) || (r >= (int)b->size)) { ++ b->size = 0; ++ } else { ++ b->size -= r; ++ b->buf += r; ++ } ++ ++ va_end(ap); ++ ++ return r; ++} ++ ++void ++bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len) ++{ ++ int i; ++ ++ if (msg != NULL && msg[0] != '\0') ++ bcm_bprintf(b, "%s", msg); ++ for (i = 0; i < len; i ++) ++ bcm_bprintf(b, "%02X", buf[i]); ++ if (newline) ++ bcm_bprintf(b, "\n"); ++} ++ ++void ++bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) ++{ ++ int i; ++ ++ for (i = 0; i < num_bytes; i++) { ++ num[i] += amount; ++ if (num[i] >= amount) ++ break; ++ amount = 1; ++ } ++} ++ ++int ++bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) ++{ ++ int i; ++ ++ for (i = nbytes - 1; i >= 0; i--) { ++ if (arg1[i] != arg2[i]) ++ return (arg1[i] - arg2[i]); ++ } ++ return 0; ++} ++ ++void ++bcm_print_bytes(const char *name, const uchar *data, int len) ++{ ++ int i; ++ int per_line = 0; ++ ++ printf("%s: %d \n", name ? name : "", len); ++ for (i = 0; i < len; i++) { ++ printf("%02x ", *data++); ++ per_line++; ++ if (per_line == 16) { ++ per_line = 0; ++ printf("\n"); ++ } ++ } ++ printf("\n"); ++} ++#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \ ++ defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) ++ ++int ++bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) ++{ ++ uint i, c; ++ char *p = buf; ++ char *endp = buf + SSID_FMT_BUF_LEN; ++ ++ if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; ++ ++ for (i = 0; i < ssid_len; i++) { ++ c = (uint)ssid[i]; ++ if (c == '\\') { ++ *p++ = '\\'; ++ *p++ = '\\'; ++ } else if (bcm_isprint((uchar)c)) { ++ *p++ = (char)c; ++ } else { ++ p += snprintf(p, (endp - p), "\\x%02X", c); ++ } ++ } ++ *p = '\0'; ++ ASSERT(p < endp); ++ ++ return (int)(p - buf); ++} ++#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */ ++ ++#endif /* BCMDRIVER */ ++ ++/* ++ * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. ++ * also accepts nvram files which are already in the format of =\0\=\0 ++ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. ++ * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. ++*/ ++ ++unsigned int ++process_nvram_vars(char *varbuf, unsigned int len) ++{ ++ char *dp; ++ bool findNewline; ++ int column; ++ unsigned int buf_len, n; ++ unsigned int pad = 0; ++ ++ dp = varbuf; ++ ++ findNewline = FALSE; ++ column = 0; ++ ++ for (n = 0; n < len; n++) { ++ if (varbuf[n] == '\r') ++ continue; ++ if (findNewline && varbuf[n] != '\n') ++ continue; ++ findNewline = FALSE; ++ if (varbuf[n] == '#') { ++ findNewline = TRUE; ++ continue; ++ } ++ if (varbuf[n] == '\n') { ++ if (column == 0) ++ continue; ++ *dp++ = 0; ++ column = 0; ++ continue; ++ } ++ *dp++ = varbuf[n]; ++ column++; ++ } ++ buf_len = (unsigned int)(dp - varbuf); ++ if (buf_len % 4) { ++ pad = 4 - buf_len % 4; ++ if (pad && (buf_len + pad <= len)) { ++ buf_len += pad; ++ } ++ } ++ ++ while (dp < varbuf + n) ++ *dp++ = 0; ++ ++ return buf_len; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/hnddma.c b/drivers/bcmdrivers/gmac/src/shared/hnddma.c +new file mode 100755 +index 0000000..2463d1f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hnddma.c +@@ -0,0 +1,3569 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Generic Broadcom Home Networking Division (HND) DMA module. ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * $Id: hnddma.c 328477 2012-04-19 10:57:54Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#include ++#endif ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_RWREG_OPT ++#ifdef R_REG ++#undef R_REG ++#define R_REG(osh, r) (\ ++ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r)) : \ ++ (*(volatile unsigned int __force *)(r)) \ ++) ++#endif /* R_REG */ ++ ++#ifdef W_REG ++#undef W_REG ++#define W_REG(osh, r, v) (\ ++ sizeof(*(r)) == sizeof(uint8) ? (*(volatile unsigned char __force *)(r) = (v)) : \ ++ sizeof(*(r)) == sizeof(uint16) ? (*(volatile unsigned short __force *)(r) = (v)) : \ ++ (*(volatile unsigned int __force *)(r) = (v)) \ ++) ++#endif /* W_REG */ ++#endif /* CONFIG_BCM_IPROC_GMAC_RWREG_OPT */ ++ ++/* debug/trace */ ++#ifdef BCMDBG ++#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args ++#define DMA_TRACE(args) if (!(*di->msg_level & 2)); else printf args ++#elif defined(BCMDBG_ERR) ++#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args ++#define DMA_TRACE(args) ++#else ++#define DMA_ERROR(args) ++#define DMA_TRACE(args) ++#endif /* BCMDBG */ ++ ++#define DMA_NONE(args) ++ ++ ++#define d32txregs dregs.d32_u.txregs_32 ++#define d32rxregs dregs.d32_u.rxregs_32 ++#define txd32 dregs.d32_u.txd_32 ++#define rxd32 dregs.d32_u.rxd_32 ++ ++#define d64txregs dregs.d64_u.txregs_64 ++#define d64rxregs dregs.d64_u.rxregs_64 ++#define txd64 dregs.d64_u.txd_64 ++#define rxd64 dregs.d64_u.rxd_64 ++ ++#define DBG(x...) printk(KERN_ERR x) ++ ++/* default dma message level (if input msg_level pointer is null in dma_attach()) */ ++static uint dma_msg_level = ++#ifdef BCMDBG_ERR ++ 1; ++#else ++ 0; ++#endif /* BCMDBG_ERR */ ++ ++#define MAXNAMEL 8 /* 8 char names */ ++ ++#define DI_INFO(dmah) ((dma_info_t *)dmah) ++ ++/* dma engine software state */ ++typedef struct dma_info { ++ struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t, ++ * which could be const ++ */ ++ uint *msg_level; /* message level pointer */ ++ char name[MAXNAMEL]; /* callers name for diag msgs */ ++ ++ void *osh; /* os handle */ ++ si_t *sih; /* sb handle */ ++ ++ bool dma64; /* this dma engine is operating in 64-bit mode */ ++ bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ ++ ++ union { ++ struct { ++ dma32regs_t *txregs_32; /* 32-bit dma tx engine registers */ ++ dma32regs_t *rxregs_32; /* 32-bit dma rx engine registers */ ++ dma32dd_t *txd_32; /* pointer to dma32 tx descriptor ring */ ++ dma32dd_t *rxd_32; /* pointer to dma32 rx descriptor ring */ ++ } d32_u; ++ struct { ++ dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */ ++ dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */ ++ dma64dd_t *txd_64; /* pointer to dma64 tx descriptor ring */ ++ dma64dd_t *rxd_64; /* pointer to dma64 rx descriptor ring */ ++ } d64_u; ++ } dregs; ++ ++ uint16 dmadesc_align; /* alignment requirement for dma descriptors */ ++ ++ uint16 ntxd; /* # tx descriptors tunable */ ++ uint16 txin; /* index of next descriptor to reclaim */ ++ uint16 txout; /* index of next descriptor to post */ ++ void **txp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *tx_dmah; /* DMA TX descriptor ring handle */ ++ hnddma_seg_map_t *txp_dmah; /* DMA MAP meta-data handle */ ++ dmaaddr_t txdpa; /* Aligned physical address of descriptor ring */ ++ dmaaddr_t txdpaorig; /* Original physical address of descriptor ring */ ++ uint16 txdalign; /* #bytes added to alloc'd mem to align txd */ ++ uint32 txdalloc; /* #bytes allocated for the ring */ ++ uint32 xmtptrbase; /* When using unaligned descriptors, the ptr register ++ * is not just an index, it needs all 13 bits to be ++ * an offset from the addr register. ++ */ ++ ++ uint16 nrxd; /* # rx descriptors tunable */ ++ uint16 rxin; /* index of next descriptor to reclaim */ ++ uint16 rxout; /* index of next descriptor to post */ ++ void **rxp; /* pointer to parallel array of pointers to packets */ ++ osldma_t *rx_dmah; /* DMA RX descriptor ring handle */ ++ hnddma_seg_map_t *rxp_dmah; /* DMA MAP meta-data handle */ ++ dmaaddr_t rxdpa; /* Aligned physical address of descriptor ring */ ++ dmaaddr_t rxdpaorig; /* Original physical address of descriptor ring */ ++ uint16 rxdalign; /* #bytes added to alloc'd mem to align rxd */ ++ uint32 rxdalloc; /* #bytes allocated for the ring */ ++ uint32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */ ++ ++ /* tunables */ ++ uint16 rxbufsize; /* rx buffer size in bytes, ++ * not including the extra headroom ++ */ ++ uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper stack ++ * e.g. some rx pkt buffers will be bridged to tx side ++ * without byte copying. The extra headroom needs to be ++ * large enough to fit txheader needs. ++ * Some dongle driver may not need it. ++ */ ++ uint nrxpost; /* # rx buffers to keep posted */ ++ uint rxoffset; /* rxcontrol offset */ ++ uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ ++ uint ddoffsethigh; /* high 32 bits */ ++ uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ ++ uint dataoffsethigh; /* high 32 bits */ ++ bool aligndesc_4k; /* descriptor base need to be aligned or not */ ++ uint8 rxburstlen; /* burstlen field for rx (for cores supporting burstlen) */ ++ uint8 txburstlen; /* burstlen field for tx (for cores supporting burstlen) */ ++ uint8 txmultioutstdrd; /* tx multiple outstanding reads */ ++ uint8 txprefetchctl; /* prefetch control for tx */ ++ uint8 txprefetchthresh; /* prefetch threshold for tx */ ++ uint8 rxprefetchctl; /* prefetch control for rx */ ++ uint8 rxprefetchthresh; /* prefetch threshold for rx */ ++ pktpool_t *pktpool; /* pktpool */ ++ uint dma_avoidance_cnt; ++ ++ uint32 d64_xs0_cd_mask; /* tx current descriptor pointer mask */ ++ uint32 d64_xs1_ad_mask; /* tx active descriptor mask */ ++ uint32 d64_rs0_cd_mask; /* rx current descriptor pointer mask */ ++ uint16 rs0cd; /* cached value of rcvstatus0 currdescr */ ++ uint16 xs0cd; /* cached value of xmtstatus0 currdescr */ ++ uint16 xs0cd_snapshot; /* snapshot of xmtstatus0 currdescr */ ++ spinlock_t des_lock; ++} dma_info_t; ++ ++/* ++ * If BCMDMA32 is defined, hnddma will support both 32-bit and 64-bit DMA engines. ++ * Otherwise it will support only 64-bit. ++ * ++ * DMA32_ENAB indicates whether hnddma is compiled with support for 32-bit DMA engines. ++ * DMA64_ENAB indicates whether hnddma is compiled with support for 64-bit DMA engines. ++ * ++ * DMA64_MODE indicates whether the current DMA engine is running as 64-bit. ++ */ ++#ifdef BCMDMA32 ++#define DMA32_ENAB(di) 1 ++#define DMA64_ENAB(di) 1 ++#define DMA64_MODE(di) ((di)->dma64) ++#else /* !BCMDMA32 */ ++#define DMA32_ENAB(di) 0 ++#define DMA64_ENAB(di) 1 ++#define DMA64_MODE(di) 1 ++#endif /* !BCMDMA32 */ ++ ++/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */ ++#ifdef BCMDMASGLISTOSL ++#define DMASGLIST_ENAB TRUE ++#else ++#define DMASGLIST_ENAB FALSE ++#endif /* BCMDMASGLISTOSL */ ++ ++/* descriptor bumping macros */ ++#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ ++#define TXD(x) XXD((x), di->ntxd) ++#define RXD(x) XXD((x), di->nrxd) ++#define NEXTTXD(i) TXD((i) + 1) ++#define PREVTXD(i) TXD((i) - 1) ++#define NEXTRXD(i) RXD((i) + 1) ++#define PREVRXD(i) RXD((i) - 1) ++ ++#define NTXDACTIVE(h, t) TXD((t) - (h)) ++#define NRXDACTIVE(h, t) RXD((t) - (h)) ++ ++/* macros to convert between byte offsets and indexes */ ++#define B2I(bytes, type) ((uint16)((bytes) / sizeof(type))) ++#define I2B(index, type) ((index) * sizeof(type)) ++ ++#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ ++#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ ++ ++#define PCI64ADDR_HIGH 0x80000000 /* address[63] */ ++#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */ ++ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++#define SKB_PREFETCH_LEN (128) ++#endif ++ ++/* Common prototypes */ ++static bool _dma_isaddrext(dma_info_t *di); ++static bool _dma_descriptor_align(dma_info_t *di); ++static bool _dma_alloc(dma_info_t *di, uint direction); ++static void _dma_detach(dma_info_t *di); ++static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa); ++static void _dma_rxinit(dma_info_t *di); ++static void *_dma_rx(dma_info_t *di); ++static bool _dma_rxfill(dma_info_t *di); ++static void _dma_rxreclaim(dma_info_t *di); ++static void _dma_rxenable(dma_info_t *di); ++static void *_dma_getnextrxp(dma_info_t *di, bool forceall); ++static void _dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize); ++ ++static void _dma_txblock(dma_info_t *di); ++static void _dma_txunblock(dma_info_t *di); ++static uint _dma_txactive(dma_info_t *di); ++static uint _dma_rxactive(dma_info_t *di); ++static uint _dma_activerxbuf(dma_info_t *di); ++static uint _dma_txpending(dma_info_t *di); ++static uint _dma_txcommitted(dma_info_t *di); ++ ++static void *_dma_peeknexttxp(dma_info_t *di); ++static int _dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range); ++static void *_dma_peeknextrxp(dma_info_t *di); ++static uintptr _dma_getvar(dma_info_t *di, const char *name); ++static void _dma_counterreset(dma_info_t *di); ++static void _dma_fifoloopbackenable(dma_info_t *di); ++static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags); ++static uint8 dma_align_sizetobits(uint size); ++static void *dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, ++ dmaaddr_t *descpa, osldma_t **dmah); ++static int _dma_pktpool_set(dma_info_t *di, pktpool_t *pool); ++static bool _dma_rxtx_error(dma_info_t *di, bool istx); ++static void _dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen); ++static uint _dma_avoidancecnt(dma_info_t *di); ++static void _dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval); ++static bool _dma_glom_enable(dma_info_t *di, uint32 val); ++ ++ ++/* Prototypes for 32-bit routines */ ++static bool dma32_alloc(dma_info_t *di, uint direction); ++static bool dma32_txreset(dma_info_t *di); ++static bool dma32_rxreset(dma_info_t *di); ++static bool dma32_txsuspendedidle(dma_info_t *di); ++static int dma32_txfast(dma_info_t *di, void *p0, bool commit); ++static void *dma32_getnexttxp(dma_info_t *di, txd_range_t range); ++static void *dma32_getnextrxp(dma_info_t *di, bool forceall); ++static void dma32_txrotate(dma_info_t *di); ++static bool dma32_rxidle(dma_info_t *di); ++static void dma32_txinit(dma_info_t *di); ++static bool dma32_txenabled(dma_info_t *di); ++static void dma32_txsuspend(dma_info_t *di); ++static void dma32_txresume(dma_info_t *di); ++static bool dma32_txsuspended(dma_info_t *di); ++#ifdef WL_MULTIQUEUE ++static void dma32_txflush(dma_info_t *di); ++static void dma32_txflush_clear(dma_info_t *di); ++#endif /* WL_MULTIQUEUE */ ++static void dma32_txreclaim(dma_info_t *di, txd_range_t range); ++static bool dma32_txstopped(dma_info_t *di); ++static bool dma32_rxstopped(dma_info_t *di); ++static bool dma32_rxenabled(dma_info_t *di); ++#if defined(BCMDBG) ++static void dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, ++ uint end, uint max_num); ++static void dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++#endif ++ ++static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs); ++ ++/* Prototypes for 64-bit routines */ ++static bool dma64_alloc(dma_info_t *di, uint direction); ++static bool dma64_txreset(dma_info_t *di); ++static bool dma64_rxreset(dma_info_t *di); ++static bool dma64_txsuspendedidle(dma_info_t *di); ++static int dma64_txfast(dma_info_t *di, void *p0, bool commit); ++static int dma64_txunframed(dma_info_t *di, void *p0, uint len, bool commit); ++static void *dma64_getpos(dma_info_t *di, bool direction); ++static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range); ++static void *dma64_getnextrxp(dma_info_t *di, bool forceall); ++static void dma64_txrotate(dma_info_t *di); ++ ++static bool dma64_rxidle(dma_info_t *di); ++static void dma64_txinit(dma_info_t *di); ++static bool dma64_txenabled(dma_info_t *di); ++static void dma64_txsuspend(dma_info_t *di); ++static void dma64_txresume(dma_info_t *di); ++static bool dma64_txsuspended(dma_info_t *di); ++#ifdef WL_MULTIQUEUE ++static void dma64_txflush(dma_info_t *di); ++static void dma64_txflush_clear(dma_info_t *di); ++#endif /* WL_MULTIQUEUE */ ++static void dma64_txreclaim(dma_info_t *di, txd_range_t range); ++static bool dma64_txstopped(dma_info_t *di); ++static bool dma64_rxstopped(dma_info_t *di); ++static bool dma64_rxenabled(dma_info_t *di); ++static bool _dma64_addrext(osl_t *osh, dma64regs_t *dma64regs); ++static int dma64_rxunframed(dma_info_t *di, void *p0, uint len, bool commit); ++ ++STATIC INLINE uint32 parity32(uint32 data); ++ ++#if defined(BCMDBG) ++static void dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, ++ uint end, uint max_num); ++static void dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++static void dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring); ++#endif ++ ++ ++const di_fcn_t dma64proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma64_txinit, ++ (di_txreset_t)dma64_txreset, ++ (di_txenabled_t)dma64_txenabled, ++ (di_txsuspend_t)dma64_txsuspend, ++ (di_txresume_t)dma64_txresume, ++ (di_txsuspended_t)dma64_txsuspended, ++ (di_txsuspendedidle_t)dma64_txsuspendedidle, ++#ifdef WL_MULTIQUEUE ++ (di_txflush_t)dma64_txflush, ++ (di_txflush_clear_t)dma64_txflush_clear, ++#endif /* WL_MULTIQUEUE */ ++ (di_txfast_t)dma64_txfast, ++ (di_txunframed_t)dma64_txunframed, ++ (di_getpos_t)dma64_getpos, ++ (di_txstopped_t)dma64_txstopped, ++ (di_txreclaim_t)dma64_txreclaim, ++ (di_getnexttxp_t)dma64_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_peekntxp_t)_dma_peekntxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma64_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma64_rxreset, ++ (di_rxidle_t)dma64_rxidle, ++ (di_rxstopped_t)dma64_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma64_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ (di_peeknextrxp_t)_dma_peeknextrxp, ++ (di_rxparam_get_t)_dma_rx_param_get, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ (di_ctrlflags_t)_dma_ctrlflags, ++ ++#if defined(BCMDBG) ++ (di_dump_t)dma64_dump, ++ (di_dumptx_t)dma64_dumptx, ++ (di_dumprx_t)dma64_dumprx, ++#else ++ NULL, ++ NULL, ++ NULL, ++#endif ++ (di_rxactive_t)_dma_rxactive, ++ (di_txpending_t)_dma_txpending, ++ (di_txcommitted_t)_dma_txcommitted, ++ (di_pktpool_set_t)_dma_pktpool_set, ++ (di_rxtxerror_t)_dma_rxtx_error, ++ (di_burstlen_set_t)_dma_burstlen_set, ++ (di_avoidancecnt_t)_dma_avoidancecnt, ++ (di_param_set_t)_dma_param_set, ++ (dma_glom_enable_t)_dma_glom_enable, ++ (di_rxunframed_t)dma64_rxunframed, ++ (dma_active_rxbuf_t)_dma_activerxbuf, ++ 40 ++}; ++ ++static const di_fcn_t dma32proc = { ++ (di_detach_t)_dma_detach, ++ (di_txinit_t)dma32_txinit, ++ (di_txreset_t)dma32_txreset, ++ (di_txenabled_t)dma32_txenabled, ++ (di_txsuspend_t)dma32_txsuspend, ++ (di_txresume_t)dma32_txresume, ++ (di_txsuspended_t)dma32_txsuspended, ++ (di_txsuspendedidle_t)dma32_txsuspendedidle, ++#ifdef WL_MULTIQUEUE ++ (di_txflush_t)dma32_txflush, ++ (di_txflush_clear_t)dma32_txflush_clear, ++#endif /* WL_MULTIQUEUE */ ++ (di_txfast_t)dma32_txfast, ++ NULL, ++ NULL, ++ (di_txstopped_t)dma32_txstopped, ++ (di_txreclaim_t)dma32_txreclaim, ++ (di_getnexttxp_t)dma32_getnexttxp, ++ (di_peeknexttxp_t)_dma_peeknexttxp, ++ (di_peekntxp_t)_dma_peekntxp, ++ (di_txblock_t)_dma_txblock, ++ (di_txunblock_t)_dma_txunblock, ++ (di_txactive_t)_dma_txactive, ++ (di_txrotate_t)dma32_txrotate, ++ ++ (di_rxinit_t)_dma_rxinit, ++ (di_rxreset_t)dma32_rxreset, ++ (di_rxidle_t)dma32_rxidle, ++ (di_rxstopped_t)dma32_rxstopped, ++ (di_rxenable_t)_dma_rxenable, ++ (di_rxenabled_t)dma32_rxenabled, ++ (di_rx_t)_dma_rx, ++ (di_rxfill_t)_dma_rxfill, ++ (di_rxreclaim_t)_dma_rxreclaim, ++ (di_getnextrxp_t)_dma_getnextrxp, ++ (di_peeknextrxp_t)_dma_peeknextrxp, ++ (di_rxparam_get_t)_dma_rx_param_get, ++ ++ (di_fifoloopbackenable_t)_dma_fifoloopbackenable, ++ (di_getvar_t)_dma_getvar, ++ (di_counterreset_t)_dma_counterreset, ++ (di_ctrlflags_t)_dma_ctrlflags, ++ ++#if defined(BCMDBG) ++ (di_dump_t)dma32_dump, ++ (di_dumptx_t)dma32_dumptx, ++ (di_dumprx_t)dma32_dumprx, ++#else ++ NULL, ++ NULL, ++ NULL, ++#endif ++ (di_rxactive_t)_dma_rxactive, ++ (di_txpending_t)_dma_txpending, ++ (di_txcommitted_t)_dma_txcommitted, ++ (di_pktpool_set_t)_dma_pktpool_set, ++ (di_rxtxerror_t)_dma_rxtx_error, ++ (di_burstlen_set_t)_dma_burstlen_set, ++ (di_avoidancecnt_t)_dma_avoidancecnt, ++ (di_param_set_t)_dma_param_set, ++ NULL, ++ NULL, ++ NULL, ++ 40 ++}; ++ ++EXPORT_SYMBOL(dma_attach); ++EXPORT_SYMBOL(dma64proc); ++ ++hnddma_t * ++dma_attach(osl_t *osh, const char *name, si_t *sih, ++ volatile void *dmaregstx, volatile void *dmaregsrx, ++ uint ntxd, uint nrxd, uint rxbufsize, int rxextheadroom, uint nrxpost, uint rxoffset, ++ uint *msg_level) ++{ ++ dma_info_t *di; ++ uint size; ++ uint32 mask; ++ ++ /* allocate private info structure */ ++ if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { ++#ifdef BCMDBG ++ DMA_ERROR(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); ++#endif ++ return (NULL); ++ } ++ ++ bzero(di, sizeof(dma_info_t)); ++ ++ di->msg_level = msg_level ? msg_level : &dma_msg_level; ++ spin_lock_init(&di->des_lock); ++ ++ /* old chips w/o sb is no longer supported */ ++ ASSERT(sih != NULL); ++ ++ if (DMA64_ENAB(di)) ++ di->dma64 = ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64); ++ else ++ di->dma64 = 0; ++ ++ /* check arguments */ ++ ASSERT(ISPOWEROF2(ntxd)); ++ ASSERT(ISPOWEROF2(nrxd)); ++ ++ if (nrxd == 0) ++ ASSERT(dmaregsrx == NULL); ++ if (ntxd == 0) ++ ASSERT(dmaregstx == NULL); ++ ++ /* init dma reg pointer */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ di->d64txregs = (dma64regs_t *)dmaregstx; ++ di->d64rxregs = (dma64regs_t *)dmaregsrx; ++ di->hnddma.di_fn = (const di_fcn_t *)&dma64proc; ++ } else if (DMA32_ENAB(di)) { ++ ASSERT(ntxd <= D32MAXDD); ++ ASSERT(nrxd <= D32MAXDD); ++ di->d32txregs = (dma32regs_t *)dmaregstx; ++ di->d32rxregs = (dma32regs_t *)dmaregsrx; ++ di->hnddma.di_fn = (const di_fcn_t *)&dma32proc; ++ } else { ++ DMA_ERROR(("%s: driver doesn't support 32-bit DMA\n", __FUNCTION__)); ++ ASSERT(0); ++ goto fail; ++ } ++ ++ /* Default flags (which can be changed by the driver calling dma_ctrlflags ++ * before enable): For backwards compatibility both Rx Overflow Continue ++ * and Parity are DISABLED. ++ * supports it. ++ */ ++ di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN, 0); ++ ++ DMA_TRACE(("%s: %s: %s osh %p flags 0x%x ntxd %d nrxd %d rxbufsize %d " ++ "rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n", ++ name, __FUNCTION__, (DMA64_MODE(di) ? "DMA64" : "DMA32"), ++ osh, di->hnddma.dmactrlflags, ntxd, nrxd, ++ rxbufsize, rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx)); ++ ++ /* make a private copy of our callers name */ ++ strncpy(di->name, name, MAXNAMEL); ++ di->name[MAXNAMEL-1] = '\0'; ++ ++ di->osh = osh; ++ di->sih = sih; ++ ++ /* save tunables */ ++ di->ntxd = (uint16)ntxd; ++ di->nrxd = (uint16)nrxd; ++ ++ /* the actual dma size doesn't include the extra headroom */ ++ di->rxextrahdrroom = (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom; ++ if (rxbufsize > BCMEXTRAHDROOM) ++ di->rxbufsize = (uint16)(rxbufsize - di->rxextrahdrroom); ++ else ++ di->rxbufsize = (uint16)rxbufsize; ++ ++ di->nrxpost = (uint16)nrxpost; ++ di->rxoffset = (uint8)rxoffset; ++ ++ /* Get the default values (POR) of the burstlen. This can be overridden by the modules ++ * if this has to be different. Otherwise this value will be used to program the control ++ * register after the reset or during the init. ++ */ ++ if (dmaregsrx) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ /* detect the dma descriptor address mask, ++ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 ++ */ ++ W_REG(di->osh, &di->d64rxregs->addrlow, 0xffffffff); ++ mask = R_REG(di->osh, &di->d64rxregs->addrlow); ++ ++ if (mask & 0xfff) ++ mask = R_REG(di->osh, &di->d64rxregs->ptr) | 0xf; ++ else ++ mask = 0x1fff; ++ ++ DMA_TRACE(("%s: dma_rx_mask: %08x\n", di->name, mask)); ++ di->d64_rs0_cd_mask = mask; ++ ++ if (mask == 0x1fff) ++ ASSERT(nrxd <= D64MAXDD); ++ else ++ ASSERT(nrxd <= D64MAXDD_LARGE); ++ ++ di->rxburstlen = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_BL_MASK) >> D64_RC_BL_SHIFT; ++ di->rxprefetchctl = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_PC_MASK) >> D64_RC_PC_SHIFT; ++ di->rxprefetchthresh = (R_REG(di->osh, ++ &di->d64rxregs->control) & D64_RC_PT_MASK) >> D64_RC_PT_SHIFT; ++ } else if (DMA32_ENAB(di)) { ++ di->rxburstlen = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_BL_MASK) >> RC_BL_SHIFT; ++ di->rxprefetchctl = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_PC_MASK) >> RC_PC_SHIFT; ++ di->rxprefetchthresh = (R_REG(di->osh, ++ &di->d32rxregs->control) & RC_PT_MASK) >> RC_PT_SHIFT; ++ } ++ } ++ if (dmaregstx) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ++ /* detect the dma descriptor address mask, ++ * should be 0x1fff before 4360B0, 0xffff start from 4360B0 ++ */ ++ W_REG(di->osh, &di->d64txregs->addrlow, 0xffffffff); ++ mask = R_REG(di->osh, &di->d64txregs->addrlow); ++ ++ if (mask & 0xfff) ++ mask = R_REG(di->osh, &di->d64txregs->ptr) | 0xf; ++ else ++ mask = 0x1fff; ++ ++ DMA_TRACE(("%s: dma_tx_mask: %08x\n", di->name, mask)); ++ di->d64_xs0_cd_mask = mask; ++ di->d64_xs1_ad_mask = mask; ++ ++ if (mask == 0x1fff) ++ ASSERT(ntxd <= D64MAXDD); ++ else ++ ASSERT(ntxd <= D64MAXDD_LARGE); ++ ++ di->txburstlen = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_BL_MASK) >> D64_XC_BL_SHIFT; ++ di->txmultioutstdrd = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_MR_MASK) >> D64_XC_MR_SHIFT; ++ di->txprefetchctl = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_PC_MASK) >> D64_XC_PC_SHIFT; ++ di->txprefetchthresh = (R_REG(di->osh, ++ &di->d64txregs->control) & D64_XC_PT_MASK) >> D64_XC_PT_SHIFT; ++ } else if (DMA32_ENAB(di)) { ++ di->txburstlen = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_BL_MASK) >> XC_BL_SHIFT; ++ di->txmultioutstdrd = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_MR_MASK) >> XC_MR_SHIFT; ++ di->txprefetchctl = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_PC_MASK) >> XC_PC_SHIFT; ++ di->txprefetchthresh = (R_REG(di->osh, ++ &di->d32txregs->control) & XC_PT_MASK) >> XC_PT_SHIFT; ++ } ++ } ++ ++ /* force burstlen to 3 */ ++ di->rxburstlen = 3; ++ di->txburstlen = 3; ++ /* ++ * figure out the DMA physical address offset for dd and data ++ * Other bus: use zero ++ */ ++ di->ddoffsetlow = 0; ++ di->dataoffsetlow = 0; ++ ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED; ++#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ ++ ++ /* set addr ext fields */ ++ di->addrext = _dma_isaddrext(di); ++ ++ /* does the descriptors need to be aligned and if yes, on 4K/8K or not */ ++ di->aligndesc_4k = _dma_descriptor_align(di); ++ if (di->aligndesc_4k) { ++ if (DMA64_MODE(di)) { ++ di->dmadesc_align = D64RINGALIGN_BITS; ++ if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { ++ /* for smaller dd table, HW relax the alignment requirement */ ++ di->dmadesc_align = D64RINGALIGN_BITS - 1; ++ } ++ } else ++ di->dmadesc_align = D32RINGALIGN_BITS; ++ } else { ++ /* The start address of descriptor table should be algined to cache line size, ++ * or other structure may share a cache line with it, which can lead to memory ++ * overlapping due to cache write-back operation. In the case of MIPS 74k, the ++ * cache line size is 32 bytes. ++ */ ++#ifdef __mips__ ++ di->dmadesc_align = 5; /* 32 byte alignment */ ++#else ++ di->dmadesc_align = 4; /* 16 byte alignment */ ++#endif ++ } ++ ++ DMA_NONE(("DMA descriptor align_needed %d, align %d\n", ++ di->aligndesc_4k, di->dmadesc_align)); ++ ++ /* allocate tx packet pointer vector */ ++ if (ntxd) { ++ size = ntxd * sizeof(void *); ++ if ((di->txp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: %s: out of tx memory, malloced %d bytes\n", ++ di->name, __FUNCTION__, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero(di->txp, size); ++ } ++ ++ /* allocate rx packet pointer vector */ ++ if (nrxd) { ++ size = nrxd * sizeof(void *); ++ if ((di->rxp = MALLOC(osh, size)) == NULL) { ++ DMA_ERROR(("%s: %s: out of rx memory, malloced %d bytes\n", ++ di->name, __FUNCTION__, MALLOCED(osh))); ++ goto fail; ++ } ++ bzero(di->rxp, size); ++ } ++ ++ /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ ++ if (ntxd) { ++ if (!_dma_alloc(di, DMA_TX)) ++ goto fail; ++ } ++ ++ /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ ++ if (nrxd) { ++ if (!_dma_alloc(di, DMA_RX)) ++ goto fail; ++ } ++ ++ if ((di->ddoffsetlow != 0) && !di->addrext) { ++ if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: %s: txdpa 0x%x: addrext not supported\n", ++ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->txdpa))); ++ goto fail; ++ } ++ if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) { ++ DMA_ERROR(("%s: %s: rxdpa 0x%x: addrext not supported\n", ++ di->name, __FUNCTION__, (uint32)PHYSADDRLO(di->rxdpa))); ++ goto fail; ++ } ++ } ++ ++ DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " ++ "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, ++ di->dataoffsethigh, di->addrext)); ++ ++ /* allocate DMA mapping vectors */ ++ if (DMASGLIST_ENAB) { ++ if (ntxd) { ++ size = ntxd * sizeof(hnddma_seg_map_t); ++ if ((di->txp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero(di->txp_dmah, size); ++ } ++ ++ if (nrxd) { ++ size = nrxd * sizeof(hnddma_seg_map_t); ++ if ((di->rxp_dmah = (hnddma_seg_map_t *)MALLOC(osh, size)) == NULL) ++ goto fail; ++ bzero(di->rxp_dmah, size); ++ } ++ } ++ ++ return ((hnddma_t *)di); ++ ++fail: ++ _dma_detach(di); ++ return (NULL); ++} ++ ++/* init the tx or rx descriptor */ ++static INLINE void ++dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, ++ uint32 bufcount) ++{ ++ /* dma32 uses 32-bit control to fit both flags and bufcounter */ ++ *flags = *flags | (bufcount & CTRL_BC_MASK); ++ ++ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } else { ++ /* address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ *flags |= (ae << CTRL_AE_SHIFT); ++ W_SM(&ddring[outidx].addr, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); ++ } ++} ++ ++/* Check for odd number of 1's */ ++STATIC INLINE uint32 parity32(uint32 data) ++{ ++ data ^= data >> 16; ++ data ^= data >> 8; ++ data ^= data >> 4; ++ data ^= data >> 2; ++ data ^= data >> 1; ++ ++ return (data & 1); ++} ++ ++#define DMA64_DD_PARITY(dd) parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2) ++ ++static INLINE void ++dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx, uint32 *flags, ++ uint32 bufcount) ++{ ++ uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; ++ ++ /* PCI bus with big(>1G) physical address, use address extension */ ++#if defined(__mips__) && defined(IL_BIGENDIAN) ++ if ((di->dataoffsetlow == SI_SDRAM_SWAPPED) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++#else ++ if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++#endif /* defined(__mips__) && defined(IL_BIGENDIAN) */ ++ ASSERT((PHYSADDRHI(pa) & PCI64ADDR_HIGH) == 0); ++ ++ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh)); ++ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); ++ } else { ++ /* address extension for 32-bit PCI */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; ++ W_SM(&ddring[outidx].addrlow, BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow)); ++ W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(0 + di->dataoffsethigh)); ++ W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); ++ } ++ if (di->hnddma.dmactrlflags & DMA_CTRL_PEN) { ++ if (DMA64_DD_PARITY(&ddring[outidx])) { ++ W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY)); ++ } ++ } ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++/* Test */ ++#if defined(__arm__) ++ if (IS_IPROC_CHIP_ID(CHIPID(di->sih->chip))) ++ OSL_CACHE_FLUSH((uint)OSL_CACHED(&ddring[outidx]), sizeof(dma64dd_t)); ++#endif ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++static bool ++_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) ++{ ++ uint32 w; ++ ++ OR_REG(osh, &dma32regs->control, XC_AE); ++ w = R_REG(osh, &dma32regs->control); ++ AND_REG(osh, &dma32regs->control, ~XC_AE); ++ return ((w & XC_AE) == XC_AE); ++} ++ ++static bool ++_dma_alloc(dma_info_t *di, uint direction) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ return dma64_alloc(di, direction); ++ } else if (DMA32_ENAB(di)) { ++ return dma32_alloc(di, direction); ++ } else ++ ASSERT(0); ++} ++ ++/* !! may be called with core in reset */ ++static void ++_dma_detach(dma_info_t *di) ++{ ++ ++ DMA_TRACE(("%s: dma_detach\n", di->name)); ++ ++ /* shouldn't be here if descriptors are unreclaimed */ ++ ASSERT(di->txin == di->txout); ++ ASSERT(di->rxin == di->rxout); ++ ++ /* free dma descriptor rings */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (di->txd64) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd64 - di->txdalign), ++ di->txdalloc, (di->txdpaorig), &di->tx_dmah); ++ if (di->rxd64) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd64 - di->rxdalign), ++ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); ++ } else if (DMA32_ENAB(di)) { ++ if (di->txd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->txd32 - di->txdalign), ++ di->txdalloc, (di->txdpaorig), &di->tx_dmah); ++ if (di->rxd32) ++ DMA_FREE_CONSISTENT(di->osh, ((int8 *)(uintptr)di->rxd32 - di->rxdalign), ++ di->rxdalloc, (di->rxdpaorig), &di->rx_dmah); ++ } else ++ ASSERT(0); ++ ++ /* free packet pointer vectors */ ++ if (di->txp) ++ MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *))); ++ if (di->rxp) ++ MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *))); ++ ++ /* free tx packet DMA handles */ ++ if (di->txp_dmah) ++ MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(hnddma_seg_map_t)); ++ ++ /* free rx packet DMA handles */ ++ if (di->rxp_dmah) ++ MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(hnddma_seg_map_t)); ++ ++ /* free our private info structure */ ++ MFREE(di->osh, (void *)di, sizeof(dma_info_t)); ++ ++} ++ ++static bool ++_dma_descriptor_align(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ uint32 addrl; ++ ++ /* Check to see if the descriptors need to be aligned on 4K/8K or not */ ++ if (di->d64txregs != NULL) { ++ W_REG(di->osh, &di->d64txregs->addrlow, 0xff0); ++ addrl = R_REG(di->osh, &di->d64txregs->addrlow); ++ if (addrl != 0) ++ return FALSE; ++ } else if (di->d64rxregs != NULL) { ++ W_REG(di->osh, &di->d64rxregs->addrlow, 0xff0); ++ addrl = R_REG(di->osh, &di->d64rxregs->addrlow); ++ if (addrl != 0) ++ return FALSE; ++ } ++ } ++ return TRUE; ++} ++ ++/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ ++static bool ++_dma_isaddrext(dma_info_t *di) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ /* DMA64 supports full 32- or 64-bit operation. AE is always valid */ ++ ++ /* not all tx or rx channel are available */ ++ if (di->d64txregs != NULL) { ++ if (!_dma64_addrext(di->osh, di->d64txregs)) { ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", ++ di->name)); ++ ASSERT(0); ++ } ++ return TRUE; ++ } else if (di->d64rxregs != NULL) { ++ if (!_dma64_addrext(di->osh, di->d64rxregs)) { ++ DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", ++ di->name)); ++ ASSERT(0); ++ } ++ return TRUE; ++ } ++ return FALSE; ++ } else if (DMA32_ENAB(di)) { ++ if (di->d32txregs) ++ return (_dma32_addrext(di->osh, di->d32txregs)); ++ else if (di->d32rxregs) ++ return (_dma32_addrext(di->osh, di->d32rxregs)); ++ } else ++ ASSERT(0); ++ ++ return FALSE; ++} ++ ++/* initialize descriptor table base address */ ++static void ++_dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa) ++{ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (!di->aligndesc_4k) { ++ if (direction == DMA_TX) ++ di->xmtptrbase = PHYSADDRLO(pa); ++ else ++ di->rcvptrbase = PHYSADDRLO(pa); ++ } ++ ++ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64txregs->addrhigh, (PHYSADDRHI(pa) + ++ di->ddoffsethigh)); ++ } else { ++ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64rxregs->addrhigh, (PHYSADDRHI(pa) + ++ di->ddoffsethigh)); ++ } ++ } else { ++ /* DMA64 32bits address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d64txregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); ++ SET_REG(di->osh, &di->d64txregs->control, D64_XC_AE, ++ (ae << D64_XC_AE_SHIFT)); ++ } else { ++ W_REG(di->osh, &di->d64rxregs->addrlow, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ W_REG(di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); ++ SET_REG(di->osh, &di->d64rxregs->control, D64_RC_AE, ++ (ae << D64_RC_AE_SHIFT)); ++ } ++ } ++ ++ } else if (DMA32_ENAB(di)) { ++ ASSERT(PHYSADDRHI(pa) == 0); ++ if ((di->ddoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) { ++ if (direction == DMA_TX) ++ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ else ++ W_REG(di->osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ } else { ++ /* dma32 address extension */ ++ uint32 ae; ++ ASSERT(di->addrext); ++ ++ /* shift the high bit(s) from pa to ae */ ++ ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; ++ PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH; ++ ++ if (direction == DMA_TX) { ++ W_REG(di->osh, &di->d32txregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <osh, &di->d32rxregs->addr, (PHYSADDRLO(pa) + ++ di->ddoffsetlow)); ++ SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <name)); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_LE); ++ else if (DMA32_ENAB(di)) ++ OR_REG(di->osh, &di->d32txregs->control, XC_LE); ++ else ++ ASSERT(0); ++} ++ ++static void ++_dma_rxinit(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxinit\n", di->name)); ++ ++ if (di->nrxd == 0) { ++ return; ++ } ++ ++ /* During the reset procedure, the active rxd may not be zero if pktpool is ++ * enabled, we need to reclaim active rxd to avoid rxd being leaked. ++ */ ++ if ((POOL_ENAB(di->pktpool)) && (NRXDACTIVE(di->rxin, di->rxout))) { ++ _dma_rxreclaim(di); ++ } ++ ++ ASSERT(di->rxin == di->rxout); ++ di->rxin = di->rxout = di->rs0cd = 0; ++ ++ /* clear rx descriptor ring */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ BZERO_SM((void *)(uintptr)di->rxd64, (di->nrxd * sizeof(dma64dd_t))); ++ ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) { ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } ++ ++ _dma_rxenable(di); ++ ++ if (di->aligndesc_4k) { ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } ++ } else if (DMA32_ENAB(di)) { ++ BZERO_SM((void *)(uintptr)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); ++ _dma_rxenable(di); ++ _dma_ddtable_init(di, DMA_RX, di->rxdpa); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_rxenable(dma_info_t *di) ++{ ++ uint dmactrlflags = di->hnddma.dmactrlflags; ++ ++ DMA_TRACE(("%s: dma_rxenable\n", di->name)); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ uint32 control = (R_REG(di->osh, &di->d64rxregs->control) & D64_RC_AE) | D64_RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= D64_RC_OC; ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control &= ~D64_RC_BL_MASK; ++ control |= (di->rxburstlen << D64_RC_BL_SHIFT); ++ ++ control &= ~D64_RC_PC_MASK; ++ control |= (di->rxprefetchctl << D64_RC_PC_SHIFT); ++ ++ control &= ~D64_RC_PT_MASK; ++ control |= (di->rxprefetchthresh << D64_RC_PT_SHIFT); ++ ++ W_REG(di->osh, &di->d64rxregs->control, ++ ((di->rxoffset << D64_RC_RO_SHIFT) | control)); ++ } else if (DMA32_ENAB(di)) { ++ uint32 control = (R_REG(di->osh, &di->d32rxregs->control) & RC_AE) | RC_RE; ++ ++ if ((dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= RC_PD; ++ ++ if (dmactrlflags & DMA_CTRL_ROC) ++ control |= RC_OC; ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control &= ~RC_BL_MASK; ++ control |= (di->rxburstlen << RC_BL_SHIFT); ++ ++ control &= ~RC_PC_MASK; ++ control |= (di->rxprefetchctl << RC_PC_SHIFT); ++ ++ control &= ~RC_PT_MASK; ++ control |= (di->rxprefetchthresh << RC_PT_SHIFT); ++ ++ W_REG(di->osh, &di->d32rxregs->control, ++ ((di->rxoffset << RC_RO_SHIFT) | control)); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_rx_param_get(dma_info_t *di, uint16 *rxoffset, uint16 *rxbufsize) ++{ ++ /* the normal values fit into 16 bits */ ++ *rxoffset = (uint16)di->rxoffset; ++ *rxbufsize = (uint16)di->rxbufsize; ++} ++ ++/* !! rx entry routine ++ * returns a pointer to the next frame received, or NULL if there are no more ++ * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported ++ * with pkts chain ++ * otherwise, it's treated as giant pkt and will be tossed. ++ * The DMA scattering starts with normal DMA header, followed by first buffer data. ++ * After it reaches the max size of buffer, the data continues in next DMA descriptor ++ * buffer WITHOUT DMA header ++ */ ++static void * BCMFASTPATH ++_dma_rx(dma_info_t *di) ++{ ++ void *p, *head, *tail; ++ uint len; ++ uint pkt_len; ++ int resid = 0; ++#ifdef BCM4335 ++ dma64regs_t *dregs = di->d64rxregs; ++#endif ++ ++next_frame: ++ head = _dma_getnextrxp(di, FALSE); ++ if (head == NULL) ++ return (NULL); ++ ++ len = ltoh16(*(uint16 *)(PKTDATA(di->osh, head))); ++ DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); ++ ++ /* set actual length */ ++ pkt_len = MIN((di->rxoffset + len), di->rxbufsize); ++ PKTSETLEN(di->osh, head, pkt_len); ++ resid = len - (di->rxbufsize - di->rxoffset); ++ ++ /* check for single or multi-buffer rx */ ++ if (resid <= 0) { ++ /* Single frame, all good */ ++ } else if (di->hnddma.dmactrlflags & DMA_CTRL_RXSINGLE) { ++ DMA_TRACE(("%s: dma_rx: corrupted length (%d)\n", di->name, len)); ++ PKTFREE(di->osh, head, FALSE); ++ di->hnddma.rxgiants++; ++ goto next_frame; ++ } else { ++ /* multi-buffer rx */ ++#ifdef BCMDBG ++ p = NULL; /* get rid of compiler warning */ ++#endif /* BCMDBG */ ++ tail = head; ++ while ((resid > 0) && (p = _dma_getnextrxp(di, FALSE))) { ++ PKTSETNEXT(di->osh, tail, p); ++ pkt_len = MIN(resid, (int)di->rxbufsize); ++ PKTSETLEN(di->osh, p, pkt_len); ++ ++ tail = p; ++ resid -= di->rxbufsize; ++ } ++ ++#ifdef BCMDBG ++ if (resid > 0) { ++ uint16 cur; ++ ASSERT(p == NULL); ++ cur = (DMA64_ENAB(di) && DMA64_MODE(di)) ? ++ B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t) : ++ B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, ++ dma32dd_t); ++ DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n", ++ di->rxin, di->rxout, cur)); ++ } ++#endif /* BCMDBG */ ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { ++ DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); ++ PKTFREE(di->osh, head, FALSE); ++ di->hnddma.rxgiants++; ++ goto next_frame; ++ } ++ } ++ ++ return (head); ++} ++ ++/* post receive buffers ++ * return FALSE is refill failed completely and ring is empty ++ * this will stall the rx dma and user might want to call rxfill again asap ++ * This unlikely happens on memory-rich NIC, but often on memory-constrained dongle ++ */ ++static bool BCMFASTPATH ++_dma_rxfill(dma_info_t *di) ++{ ++ void *p; ++ uint16 rxin, rxout; ++ uint32 flags = 0; ++ uint n; ++ uint i; ++ dmaaddr_t pa; ++ uint extra_offset = 0, extra_pad; ++ bool ring_empty; ++ uint alignment_req = (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) ? ++ 16 : 1; /* MUST BE POWER of 2 */ ++ ++ ring_empty = FALSE; ++ ++ /* ++ * Determine how many receive buffers we're lacking ++ * from the full complement, allocate, initialize, ++ * and post them, then update the chip rx lastdscr. ++ */ ++ ++ rxin = di->rxin; ++ rxout = di->rxout; ++ ++ n = di->nrxpost - NRXDACTIVE(rxin, rxout); ++ ++ if (di->rxbufsize > BCMEXTRAHDROOM) ++ extra_offset = di->rxextrahdrroom; ++ ++ DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); ++ ++ for (i = 0; i < n; i++) { ++ /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the ++ size to be allocated ++ */ ++ if (POOL_ENAB(di->pktpool)) { ++ ASSERT(di->pktpool); ++ p = pktpool_get(di->pktpool); ++#ifdef BCMDBG_POOL ++ if (p) ++ PKTPOOLSETSTATE(p, POOL_RXFILL); ++#endif /* BCMDBG_POOL */ ++ } ++ else { ++ p = PKTGET(di->osh, (di->rxbufsize + extra_offset + alignment_req - 1), ++ FALSE); ++ } ++ if (p == NULL) { ++ DMA_TRACE(("%s: dma_rxfill: out of rxbufs\n", di->name)); ++ if (i == 0) { ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (dma64_rxidle(di)) { ++ DMA_TRACE(("%s: rxfill64: ring is empty !\n", ++ di->name)); ++ ring_empty = TRUE; ++ } ++ } else if (DMA32_ENAB(di)) { ++ if (dma32_rxidle(di)) { ++ DMA_TRACE(("%s: rxfill32: ring is empty !\n", ++ di->name)); ++ ring_empty = TRUE; ++ } ++ } else ++ ASSERT(0); ++ } ++ di->hnddma.rxnobuf++; ++ break; ++ } ++ /* reserve an extra headroom, if applicable */ ++ if (di->hnddma.dmactrlflags & DMA_CTRL_USB_BOUNDRY4KB_WAR) { ++ extra_pad = ((alignment_req - (uint)(((unsigned long)PKTDATA(di->osh, p) - ++ (unsigned long)(uchar *)0))) & (alignment_req - 1)); ++ } else ++ extra_pad = 0; ++ ++ if (extra_offset + extra_pad) ++ PKTPULL(di->osh, p, extra_offset + extra_pad); ++ ++#ifdef CTFMAP ++ /* mark as ctf buffer for fast mapping */ ++ if (CTF_ENAB(kcih)) { ++ ASSERT((((uint32)PKTDATA(di->osh, p)) & 31) == 0); ++ PKTSETCTF(di->osh, p); ++ } ++#endif /* CTFMAP */ ++ ++ /* Do a cached write instead of uncached write since DMA_MAP ++ * will flush the cache. ++ */ ++ *(uint16 *)(PKTDATA(di->osh, p)) = 0; ++ ++ if (DMASGLIST_ENAB) ++ bzero(&di->rxp_dmah[rxout], sizeof(hnddma_seg_map_t)); ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(PKTDATA(di->osh, p)); ++#else ++ pa = DMA_MAP(di->osh, PKTDATA(di->osh, p), ++ di->rxbufsize, DMA_RX, p, ++ &di->rxp_dmah[rxout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ ASSERT(ISALIGNED(PHYSADDRLO(pa), 4)); ++ ++ /* save the free packet pointer */ ++ ASSERT(di->rxp[rxout] == NULL); ++ di->rxp[rxout] = p; ++ ++ /* reset flags for each descriptor */ ++ flags = 0; ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ if (rxout == (di->nrxd - 1)) ++ flags = D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, di->rxbufsize); ++ } else if (DMA32_ENAB(di)) { ++ if (rxout == (di->nrxd - 1)) ++ flags = CTRL_EOT; ++ ++ ASSERT(PHYSADDRHI(pa) == 0); ++ dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); ++ } else ++ ASSERT(0); ++ rxout = NEXTRXD(rxout); ++ } ++ ++ di->rxout = rxout; ++ ++ /* update the chip lastdscr pointer */ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ } else if (DMA32_ENAB(di)) { ++ W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); ++ } else ++ ASSERT(0); ++ ++ return ring_empty; ++} ++ ++/* like getnexttxp but no reclaim */ ++static void * ++_dma_peeknexttxp(dma_info_t *di) ++{ ++ uint16 end, i; ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ end = (uint16)B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ di->xs0cd = end; ++ } else if (DMA32_ENAB(di)) { ++ end = (uint16)B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = end; ++ } else ++ ASSERT(0); ++ ++ for (i = di->txin; i != end; i = NEXTTXD(i)) ++ if (di->txp[i]) ++ return (di->txp[i]); ++ ++ return (NULL); ++} ++ ++int ++_dma_peekntxp(dma_info_t *di, int *len, void *txps[], txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint act; ++ void *txp = NULL; ++ int k, len_max; ++ ++ DMA_TRACE(("%s: dma_peekntxp\n", di->name)); ++ ++ ASSERT(len); ++ ASSERT(txps); ++ ASSERT(di); ++ if (di->ntxd == 0) { ++ *len = 0; ++ return BCME_ERROR; ++ } ++ ++ len_max = *len; ++ *len = 0; ++ ++ start = di->txin; ++ ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ if (DMA64_ENAB(di)) { ++ end = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ ++ act = (uint)(R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK); ++ act = (act - di->xmtptrbase) & D64_XS0_CD_MASK; ++ act = (uint)B2I(act, dma64dd_t); ++ } else { ++ end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ ++ act = (uint)((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> ++ XS_AD_SHIFT); ++ act = (uint)B2I(act, dma32dd_t); ++ } ++ ++ di->xs0cd = end; ++ if (end != act) ++ end = PREVTXD(act); ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ return BCME_ERROR; ++ ++ k = 0; ++ for (i = start; i != end; i = NEXTTXD(i)) { ++ txp = di->txp[i]; ++ if (txp != NULL) { ++ if (k < len_max) ++ txps[k++] = txp; ++ else ++ break; ++ } ++ } ++ *len = k; ++ ++ return BCME_OK; ++} ++ ++/* like getnextrxp but not take off the ring */ ++static void * ++_dma_peeknextrxp(dma_info_t *di) ++{ ++ uint16 end, i; ++ ++ if (di->nrxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ end = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ di->rs0cd = end; ++ } else if (DMA32_ENAB(di)) { ++ end = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); ++ di->rs0cd = end; ++ } else ++ ASSERT(0); ++ ++ for (i = di->rxin; i != end; i = NEXTRXD(i)) ++ if (di->rxp[i]) ++ return (di->rxp[i]); ++ ++ return (NULL); ++} ++ ++static void ++_dma_rxreclaim(dma_info_t *di) ++{ ++ void *p; ++ bool origcb = TRUE; ++ ++#ifndef EFI ++ /* "unused local" warning suppression for OSLs that ++ * define PKTFREE() without using the di->osh arg ++ */ ++ di = di; ++#endif /* EFI */ ++ ++ DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); ++ ++ if (POOL_ENAB(di->pktpool) && ++ ((origcb = pktpool_emptycb_disabled(di->pktpool)) == FALSE)) ++ pktpool_emptycb_disable(di->pktpool, TRUE); ++ ++ while ((p = _dma_getnextrxp(di, TRUE))) ++ PKTFREE(di->osh, p, FALSE); ++ ++ if (origcb == FALSE) ++ pktpool_emptycb_disable(di->pktpool, FALSE); ++} ++ ++static void * BCMFASTPATH ++_dma_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ if (di->nrxd == 0) ++ return (NULL); ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ return dma64_getnextrxp(di, forceall); ++ } else if (DMA32_ENAB(di)) { ++ return dma32_getnextrxp(di, forceall); ++ } else ++ ASSERT(0); ++} ++ ++static void ++_dma_txblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = 0; ++} ++ ++static void ++_dma_txunblock(dma_info_t *di) ++{ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++} ++ ++static uint ++_dma_txactive(dma_info_t *di) ++{ ++ return NTXDACTIVE(di->txin, di->txout); ++} ++ ++static uint ++_dma_txpending(dma_info_t *di) ++{ ++ uint16 curr; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ curr = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ di->xs0cd = curr; ++ } else if (DMA32_ENAB(di)) { ++ curr = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = curr; ++ } else ++ ASSERT(0); ++ ++ return NTXDACTIVE(curr, di->txout); ++} ++ ++static uint ++_dma_txcommitted(dma_info_t *di) ++{ ++ uint16 ptr; ++ uint txin = di->txin; ++ ++ if (txin == di->txout) ++ return 0; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ptr = B2I(R_REG(di->osh, &di->d64txregs->ptr), dma64dd_t); ++ } else if (DMA32_ENAB(di)) { ++ ptr = B2I(R_REG(di->osh, &di->d32txregs->ptr), dma32dd_t); ++ } else ++ ASSERT(0); ++ ++ return NTXDACTIVE(di->txin, ptr); ++} ++ ++static uint ++_dma_rxactive(dma_info_t *di) ++{ ++ return NRXDACTIVE(di->rxin, di->rxout); ++} ++ ++static uint ++_dma_activerxbuf(dma_info_t *di) ++{ ++ uint16 curr, ptr; ++ curr = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ ptr = B2I(((R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ return NRXDACTIVE(curr, ptr); ++} ++ ++ ++static void ++_dma_counterreset(dma_info_t *di) ++{ ++ /* reset all software counter */ ++ di->hnddma.rxgiants = 0; ++ di->hnddma.rxnobuf = 0; ++ di->hnddma.txnobuf = 0; ++} ++ ++static uint ++_dma_ctrlflags(dma_info_t *di, uint mask, uint flags) ++{ ++ uint dmactrlflags; ++ ++ if (!di) { ++ DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n")); ++ return (0); ++ } ++ ++ dmactrlflags = di->hnddma.dmactrlflags; ++ ASSERT((flags & ~mask) == 0); ++ ++ dmactrlflags &= ~mask; ++ dmactrlflags |= flags; ++ ++ /* If trying to enable parity, check if parity is actually supported */ ++ if (dmactrlflags & DMA_CTRL_PEN) { ++ uint32 control; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ control = R_REG(di->osh, &di->d64txregs->control); ++ W_REG(di->osh, &di->d64txregs->control, control | D64_XC_PD); ++ if (R_REG(di->osh, &di->d64txregs->control) & D64_XC_PD) { ++ /* We *can* disable it so it is supported, ++ * restore control register ++ */ ++ W_REG(di->osh, &di->d64txregs->control, control); ++ } else { ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ } else if (DMA32_ENAB(di)) { ++ control = R_REG(di->osh, &di->d32txregs->control); ++ W_REG(di->osh, &di->d32txregs->control, control | XC_PD); ++ if (R_REG(di->osh, &di->d32txregs->control) & XC_PD) { ++ W_REG(di->osh, &di->d32txregs->control, control); ++ } else { ++ /* Not supported, don't allow it to be enabled */ ++ dmactrlflags &= ~DMA_CTRL_PEN; ++ } ++ } else ++ ASSERT(0); ++ } ++ ++ di->hnddma.dmactrlflags = dmactrlflags; ++ ++ return (dmactrlflags); ++} ++ ++/* get the address of the var in order to change later */ ++static uintptr ++_dma_getvar(dma_info_t *di, const char *name) ++{ ++ if (!strcmp(name, "&txavail")) ++ return ((uintptr) &(di->hnddma.txavail)); ++ else { ++ ASSERT(0); ++ } ++ return (0); ++} ++ ++static uint ++_dma_avoidancecnt(dma_info_t *di) ++{ ++ return (di->dma_avoidance_cnt); ++} ++ ++void ++dma_txpioloopback(osl_t *osh, dma32regs_t *regs) ++{ ++ OR_REG(osh, ®s->control, XC_LE); ++} ++ ++static ++uint8 dma_align_sizetobits(uint size) ++{ ++ uint8 bitpos = 0; ++ ASSERT(size); ++ ASSERT(!(size & (size-1))); ++ while (size >>= 1) { ++ bitpos ++; ++ } ++ return (bitpos); ++} ++ ++/* This function ensures that the DMA descriptor ring will not get allocated ++ * across Page boundary. If the allocation is done across the page boundary ++ * at the first time, then it is freed and the allocation is done at ++ * descriptor ring size aligned location. This will ensure that the ring will ++ * not cross page boundary ++ */ ++static void * ++dma_ringalloc(osl_t *osh, uint32 boundary, uint size, uint16 *alignbits, uint* alloced, ++ dmaaddr_t *descpa, osldma_t **dmah) ++{ ++ void * va; ++ uint32 desc_strtaddr; ++ uint32 alignbytes = 1 << *alignbits; ++ ++ if ((va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah)) == NULL) ++ return NULL; ++ ++ /* printk("%s va(0x%x)\n", __FUNCTION__, va); */ ++ desc_strtaddr = (uint32)ROUNDUP((uint)PHYSADDRLO(*descpa), alignbytes); ++ if (((desc_strtaddr + size - 1) & boundary) != ++ (desc_strtaddr & boundary)) { ++ *alignbits = dma_align_sizetobits(size); ++ DMA_FREE_CONSISTENT(osh, va, ++ size, *descpa, dmah); ++ va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa, dmah); ++ } ++ return va; ++} ++ ++#if defined(BCMDBG) ++static void ++dma32_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma32dd_t *ring, uint start, uint end, ++ uint max_num) ++{ ++ uint i; ++ ++ for (i = start; i != end; i = XXD((i + 1), max_num)) { ++ /* in the format of high->low 8 bytes */ ++ bcm_bprintf(b, "ring index %d: 0x%x %x\n", ++ i, R_SM(&ring[i].addr), R_SM(&ring[i].ctrl)); ++ } ++} ++ ++static void ++dma32_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->ntxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA32: txd32 %p txdpa 0x%lx txp %p txin %d txout %d " ++ "txavail %d txnodesc %d\n", di->txd32, PHYSADDRLO(di->txdpa), di->txp, di->txin, ++ di->txout, di->hnddma.txavail, di->hnddma.txnodesc); ++ ++ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%x\n", ++ R_REG(di->osh, &di->d32txregs->control), ++ R_REG(di->osh, &di->d32txregs->addr), ++ R_REG(di->osh, &di->d32txregs->ptr), ++ R_REG(di->osh, &di->d32txregs->status)); ++ ++ if (dumpring && di->txd32) ++ dma32_dumpring(di, b, di->txd32, di->txin, di->txout, di->ntxd); ++} ++ ++static void ++dma32_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->nrxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA32: rxd32 %p rxdpa 0x%lx rxp %p rxin %d rxout %d\n", ++ di->rxd32, PHYSADDRLO(di->rxdpa), di->rxp, di->rxin, di->rxout); ++ ++ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%x\n", ++ R_REG(di->osh, &di->d32rxregs->control), ++ R_REG(di->osh, &di->d32rxregs->addr), ++ R_REG(di->osh, &di->d32rxregs->ptr), ++ R_REG(di->osh, &di->d32rxregs->status)); ++ if (di->rxd32 && dumpring) ++ dma32_dumpring(di, b, di->rxd32, di->rxin, di->rxout, di->nrxd); ++} ++ ++static void ++dma32_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ dma32_dumptx(di, b, dumpring); ++ dma32_dumprx(di, b, dumpring); ++} ++ ++static void ++dma64_dumpring(dma_info_t *di, struct bcmstrbuf *b, dma64dd_t *ring, uint start, uint end, ++ uint max_num) ++{ ++ uint i; ++ ++ for (i = start; i != end; i = XXD((i + 1), max_num)) { ++ /* in the format of high->low 16 bytes */ ++ bcm_bprintf(b, "ring index %d: 0x%x %x %x %x\n", ++ i, R_SM(&ring[i].addrhigh), R_SM(&ring[i].addrlow), ++ R_SM(&ring[i].ctrl2), R_SM(&ring[i].ctrl1)); ++ } ++} ++ ++static void ++dma64_dumptx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->ntxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA64: txd64 %p txdpa 0x%lx txdpahi 0x%lx txp %p txin %d txout %d " ++ "txavail %d txnodesc %d\n", di->txd64, PHYSADDRLO(di->txdpa), ++ PHYSADDRHI(di->txdpaorig), di->txp, di->txin, di->txout, di->hnddma.txavail, ++ di->hnddma.txnodesc); ++ ++ bcm_bprintf(b, "xmtcontrol 0x%x xmtaddrlow 0x%x xmtaddrhigh 0x%x " ++ "xmtptr 0x%x xmtstatus0 0x%x xmtstatus1 0x%x\n", ++ R_REG(di->osh, &di->d64txregs->control), ++ R_REG(di->osh, &di->d64txregs->addrlow), ++ R_REG(di->osh, &di->d64txregs->addrhigh), ++ R_REG(di->osh, &di->d64txregs->ptr), ++ R_REG(di->osh, &di->d64txregs->status0), ++ R_REG(di->osh, &di->d64txregs->status1)); ++ ++ bcm_bprintf(b, "DMA64: DMA avoidance applied %d\n", di->dma_avoidance_cnt); ++ ++ if (dumpring && di->txd64) { ++ dma64_dumpring(di, b, di->txd64, di->txin, di->txout, di->ntxd); ++ } ++} ++ ++static void ++dma64_dumprx(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ if (di->nrxd == 0) ++ return; ++ ++ bcm_bprintf(b, "DMA64: rxd64 %p rxdpa 0x%lx rxdpahi 0x%lx rxp %p rxin %d rxout %d\n", ++ di->rxd64, PHYSADDRLO(di->rxdpa), PHYSADDRHI(di->rxdpaorig), di->rxp, ++ di->rxin, di->rxout); ++ ++ bcm_bprintf(b, "rcvcontrol 0x%x rcvaddrlow 0x%x rcvaddrhigh 0x%x rcvptr " ++ "0x%x rcvstatus0 0x%x rcvstatus1 0x%x\n", ++ R_REG(di->osh, &di->d64rxregs->control), ++ R_REG(di->osh, &di->d64rxregs->addrlow), ++ R_REG(di->osh, &di->d64rxregs->addrhigh), ++ R_REG(di->osh, &di->d64rxregs->ptr), ++ R_REG(di->osh, &di->d64rxregs->status0), ++ R_REG(di->osh, &di->d64rxregs->status1)); ++ if (di->rxd64 && dumpring) { ++ dma64_dumpring(di, b, di->rxd64, di->rxin, di->rxout, di->nrxd); ++ } ++} ++ ++static void ++dma64_dump(dma_info_t *di, struct bcmstrbuf *b, bool dumpring) ++{ ++ dma64_dumptx(di, b, dumpring); ++ dma64_dumprx(di, b, dumpring); ++} ++ ++#endif ++ ++ ++/* 32-bit DMA functions */ ++ ++static void ++dma32_txinit(dma_info_t *di) ++{ ++ uint32 control = XC_XE; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = di->xs0cd = 0; ++ di->hnddma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ BZERO_SM(DISCARD_QUAL(di->txd32, void), (di->ntxd * sizeof(dma32dd_t))); ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control |= (di->txburstlen << XC_BL_SHIFT); ++ control |= (di->txmultioutstdrd << XC_MR_SHIFT); ++ control |= (di->txprefetchctl << XC_PC_SHIFT); ++ control |= (di->txprefetchthresh << XC_PT_SHIFT); ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= XC_PD; ++ W_REG(di->osh, &di->d32txregs->control, control); ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++static bool ++dma32_txenabled(dma_info_t *di) ++{ ++ uint32 xc; ++ ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d32txregs->control); ++ return ((xc != 0xffffffff) && (xc & XC_XE)); ++} ++ ++static void ++dma32_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE); ++} ++ ++static void ++dma32_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); ++} ++ ++static bool ++dma32_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); ++} ++ ++#ifdef WL_MULTIQUEUE ++static void ++dma32_txflush(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txflush\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d32txregs->control, XC_SE | XC_FL); ++} ++ ++static void ++dma32_txflush_clear(dma_info_t *di) ++{ ++ uint32 status; ++ ++ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ AND_REG(di->osh, &di->d32txregs->control, ~XC_FL); ++} ++#endif /* WL_MULTIQUEUE */ ++ ++static void ++dma32_txreclaim(dma_info_t *di, txd_range_t range) ++{ ++ void *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma32_getnexttxp(di, range))) ++ PKTFREE(di->osh, p, TRUE); ++} ++ ++static bool ++dma32_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); ++} ++ ++static bool ++dma32_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); ++} ++ ++static bool ++dma32_alloc(dma_info_t *di, uint direction) ++{ ++ uint size; ++ uint ddlen; ++ void *va; ++ uint alloced; ++ uint16 align; ++ uint16 align_bits; ++ ++ ddlen = sizeof(dma32dd_t); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ ++ alloced = 0; ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, ++ &di->txdpaorig, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ ++ PHYSADDRHISET(di->txdpa, 0); ++ ASSERT(PHYSADDRHI(di->txdpaorig) == 0); ++ di->txd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); ++ di->txdalign = (uint)((int8 *)(uintptr)di->txd32 - (int8 *)va); ++ ++ PHYSADDRLOSET(di->txdpa, PHYSADDRLO(di->txdpaorig) + di->txdalign); ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); ++ ++ di->txdalloc = alloced; ++ ASSERT(ISALIGNED(di->txd32, align)); ++ } else { ++ if ((va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits, &alloced, ++ &di->rxdpaorig, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ ++ PHYSADDRHISET(di->rxdpa, 0); ++ ASSERT(PHYSADDRHI(di->rxdpaorig) == 0); ++ di->rxd32 = (dma32dd_t *)ROUNDUP((uintptr)va, align); ++ di->rxdalign = (uint)((int8 *)(uintptr)di->rxd32 - (int8 *)va); ++ ++ PHYSADDRLOSET(di->rxdpa, PHYSADDRLO(di->rxdpaorig) + di->rxdalign); ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); ++ di->rxdalloc = alloced; ++ ASSERT(ISALIGNED(di->rxd32, align)); ++ } ++ ++ return TRUE; ++} ++ ++static bool ++dma32_txreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d32txregs->control, XC_SE); ++ SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) ++ != XS_XS_DISABLED) && ++ (status != XS_XS_IDLE) && ++ (status != XS_XS_STOPPED), ++ (10000)); ++ ++ W_REG(di->osh, &di->d32txregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED), ++ 10000); ++ ++ /* We should be disabled at this point */ ++ if (status != XS_XS_DISABLED) { ++ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); ++ ASSERT(status == XS_XS_DISABLED); ++ OSL_DELAY(300); ++ } ++ ++ return (status == XS_XS_DISABLED); ++} ++ ++static bool ++dma32_rxidle(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == ++ R_REG(di->osh, &di->d32rxregs->ptr)); ++} ++ ++static bool ++dma32_rxreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d32rxregs->control, 0); ++ SPINWAIT(((status = (R_REG(di->osh, ++ &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED), ++ 10000); ++ ++ return (status == RS_RS_DISABLED); ++} ++ ++static bool ++dma32_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d32rxregs->control); ++ return ((rc != 0xffffffff) && (rc & RC_RE)); ++} ++ ++static bool ++dma32_txsuspendedidle(dma_info_t *di) ++{ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) ++ return 0; ++ ++ OSL_DELAY(2); ++ return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); ++} ++ ++/* !! tx entry routine ++ * supports full 32bit dma engine buffer addressing so ++ * dma buffers can cross 4 Kbyte page boundaries. ++ * ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems ++ */ ++static int ++dma32_txfast(dma_info_t *di, void *p0, bool commit) ++{ ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ uint nsegs, j; ++ hnddma_seg_map_t *map; ++ ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++#ifdef BCM_DMAPAD ++ len += PKTDMAPAD(di->osh, p); ++#endif ++ next = PKTNEXT(di->osh, p); ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ if (DMASGLIST_ENAB) ++ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); ++ ++ /* get physical address of buffer start */ ++ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[txout]; ++ ++ /* See if all the segments can be accounted for */ ++ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) ++ goto outoftxd; ++ ++ nsegs = map->nsegs; ++ } else ++ nsegs = 1; ++ ++ for (j = 1; j <= nsegs; j++) { ++ flags = 0; ++ if (p == p0 && j == 1) ++ flags |= CTRL_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when ++ * end of segment list is reached. ++ */ ++ if ((!DMASGLIST_ENAB && next == NULL) || ++ (DMASGLIST_ENAB && j == nsegs)) ++ flags |= (CTRL_IOC | CTRL_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= CTRL_EOT; ++ ++ if (DMASGLIST_ENAB) { ++ len = map->segs[j - 1].length; ++ pa = map->segs[j - 1].addr; ++ } ++ ASSERT(PHYSADDRHI(pa) == 0); ++ ++ dma32_dd_upd(di, di->txd32, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); ++ } ++ ++ /* See above. No need to loop over individual buffers */ ++ if (DMASGLIST_ENAB) ++ break; ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & CTRL_EOF)) ++ W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF)); ++ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ di->hnddma.txnodesc++; ++ return (-1); ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++static void * ++dma32_getnexttxp(dma_info_t *di, txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint16 active_desc; ++ void *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ dma32regs_t *dregs = di->d32txregs; ++ ++ if (di->txin == di->xs0cd) { ++ end = (uint16)B2I(R_REG(di->osh, &dregs->status) & XS_CD_MASK, dma32dd_t); ++ di->xs0cd = end; ++ } else ++ end = di->xs0cd; ++ ++ if (range == HNDDMA_RANGE_TRANSFERED) { ++ active_desc = (uint16)((R_REG(di->osh, &dregs->status) & XS_AD_MASK) >> ++ XS_AD_SHIFT); ++ active_desc = (uint16)B2I(active_desc, dma32dd_t); ++ if (end != active_desc) ++ end = PREVTXD(active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ dmaaddr_t pa; ++ hnddma_seg_map_t *map = NULL; ++ uint size, j, nsegs; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, 0); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[i]; ++ size = map->origsize; ++ nsegs = map->nsegs; ++ } else { ++ size = (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK); ++ nsegs = 1; ++ } ++ ++ for (j = nsegs; j > 0; j--) { ++ W_SM(&di->txd32[i].addr, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ if (j > 1) ++ i = NEXTTXD(i); ++ } ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (txp); ++ ++bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++ return (NULL); ++} ++ ++static void * ++dma32_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ uint16 i, curr; ++ void *rxp; ++ dmaaddr_t pa; ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma32_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++ if (di->rxin == di->rs0cd) { ++ curr = (uint16)B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t); ++ di->rs0cd = curr; ++ } else ++ curr = di->rs0cd; ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, 0); ++ ++ /* clear this packet from the descriptor ring */ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, ++ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ W_SM(&di->rxd32[i].addr, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); ++} ++ ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma32_txrotate(dma_info_t *di) ++{ ++ uint16 ad; ++ uint nactive; ++ uint rot; ++ uint16 old, new; ++ uint32 w; ++ uint16 first, last; ++ ++ ASSERT(dma32_txsuspendedidle(di)); ++ ++ nactive = _dma_txactive(di); ++ ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); ++ rot = TXD(ad - di->txin); ++ ++ ASSERT(rot < di->ntxd); ++ ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } ++ ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= CTRL_EOT; ++ W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w)); ++ W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); ++ ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef)); ++ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ ++ /* Move the segment map as well */ ++ if (DMASGLIST_ENAB) { ++ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); ++ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); ++ } ++ ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); ++} ++ ++/* 64-bit DMA functions */ ++ ++static void ++dma64_txinit(dma_info_t *di) ++{ ++ uint32 control; ++ ++ DMA_TRACE(("%s: dma_txinit\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ di->txin = di->txout = di->xs0cd = di->xs0cd_snapshot = 0; ++ di->hnddma.txavail = di->ntxd - 1; ++ ++ /* clear tx descriptor ring */ ++ BZERO_SM((void *)(uintptr)di->txd64, (di->ntxd * sizeof(dma64dd_t))); ++ ++ /* These bits 20:18 (burstLen) of control register can be written but will take ++ * effect only if these bits are valid. So this will not affect previous versions ++ * of the DMA. They will continue to have those bits set to 0. ++ */ ++ control = R_REG(di->osh, &di->d64txregs->control); ++ control = (control & ~D64_XC_BL_MASK) | (di->txburstlen << D64_XC_BL_SHIFT); ++ control = (control & ~D64_XC_MR_MASK) | (di->txmultioutstdrd << D64_XC_MR_SHIFT); ++ control = (control & ~D64_XC_PC_MASK) | (di->txprefetchctl << D64_XC_PC_SHIFT); ++ control = (control & ~D64_XC_PT_MASK) | (di->txprefetchthresh << D64_XC_PT_SHIFT); ++ W_REG(di->osh, &di->d64txregs->control, control); ++ ++ control = D64_XC_XE; ++ /* DMA engine with out alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (!di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++ ++ if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0) ++ control |= D64_XC_PD; ++ OR_REG(di->osh, &di->d64txregs->control, control); ++ ++ /* DMA engine with alignment requirement requires table to be inited ++ * before enabling the engine ++ */ ++ if (di->aligndesc_4k) ++ _dma_ddtable_init(di, DMA_TX, di->txdpa); ++} ++ ++static bool ++dma64_txenabled(dma_info_t *di) ++{ ++ uint32 xc; ++ ++ /* If the chip is dead, it is not enabled :-) */ ++ xc = R_REG(di->osh, &di->d64txregs->control); ++ return ((xc != 0xffffffff) && (xc & D64_XC_XE)); ++} ++ ++static void ++dma64_txsuspend(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txsuspend\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE); ++} ++ ++static void ++dma64_txresume(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txresume\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_SE); ++} ++ ++static bool ++dma64_txsuspended(dma_info_t *di) ++{ ++ return (di->ntxd == 0) || ++ ((R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); ++} ++ ++#ifdef WL_MULTIQUEUE ++static void ++dma64_txflush(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_txflush\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE | D64_XC_FL); ++} ++ ++static void ++dma64_txflush_clear(dma_info_t *di) ++{ ++ uint32 status; ++ ++ DMA_TRACE(("%s: dma_txflush_clear\n", di->name)); ++ ++ if (di->ntxd == 0) ++ return; ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED) && ++ (status != D64_XS0_XS_IDLE) && ++ (status != D64_XS0_XS_STOPPED), ++ 10000); ++ AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_FL); ++} ++#endif /* WL_MULTIQUEUE */ ++ ++static void BCMFASTPATH ++dma64_txreclaim(dma_info_t *di, txd_range_t range) ++{ ++ void *p; ++ ++ DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->txin == di->txout) ++ return; ++ ++ while ((p = dma64_getnexttxp(di, range))) { ++ /* For unframed data, we don't have any packets to free */ ++ if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED)) ++ PKTFREE(di->osh, p, TRUE); ++ } ++} ++ ++static bool ++dma64_txstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); ++} ++ ++static bool ++dma64_rxstopped(dma_info_t *di) ++{ ++ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); ++} ++ ++static bool ++dma64_alloc(dma_info_t *di, uint direction) ++{ ++ uint32 size; ++ uint ddlen; ++ void *va; ++ uint alloced = 0; ++ uint32 align; ++ uint16 align_bits; ++ ++ ddlen = sizeof(dma64dd_t); ++ ++ size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); ++ align_bits = di->dmadesc_align; ++ align = (1 << align_bits); ++ ++ if (direction == DMA_TX) { ++ if ((va = dma_ringalloc(di->osh, ++ (di->d64_xs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, ++ size, &align_bits, &alloced, ++ &di->txdpaorig, &di->tx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ align = (1 << align_bits); ++ ++ /* adjust the pa by rounding up to the alignment */ ++ PHYSADDRLOSET(di->txdpa, ROUNDUP(PHYSADDRLO(di->txdpaorig), align)); ++ PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig)); ++ ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig)); ++ ++ /* find the alignment offset that was used */ ++ di->txdalign = (uint)(PHYSADDRLO(di->txdpa) - PHYSADDRLO(di->txdpaorig)); ++ ++ /* adjust the va by the same offset */ ++ di->txd64 = (dma64dd_t *)((uintptr)va + di->txdalign); ++ ++ /* printk("%s di->txd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txd64), PHYSADDRLO(di->txd64)); */ ++ /* printk("%s di->txdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->txdpa), PHYSADDRLO(di->txdpa)); */ ++ di->txdalloc = alloced; ++ ASSERT(ISALIGNED(PHYSADDRLO(di->txdpa), align)); ++ } else { ++ if ((va = dma_ringalloc(di->osh, ++ (di->d64_rs0_cd_mask == 0x1fff) ? D64RINGBOUNDARY : D64RINGBOUNDARY_LARGE, ++ size, &align_bits, &alloced, ++ &di->rxdpaorig, &di->rx_dmah)) == NULL) { ++ DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", ++ di->name)); ++ return FALSE; ++ } ++ align = (1 << align_bits); ++ ++ /* adjust the pa by rounding up to the alignment */ ++ PHYSADDRLOSET(di->rxdpa, ROUNDUP(PHYSADDRLO(di->rxdpaorig), align)); ++ PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig)); ++ ++ /* Make sure that alignment didn't overflow */ ++ ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig)); ++ ++ /* find the alignment offset that was used */ ++ di->rxdalign = (uint)(PHYSADDRLO(di->rxdpa) - PHYSADDRLO(di->rxdpaorig)); ++ ++ /* adjust the va by the same offset */ ++ di->rxd64 = (dma64dd_t *)((uintptr)va + di->rxdalign); ++ ++ /* printk("%s di->rxd64(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxd64), PHYSADDRLO(di->rxd64)); */ ++ /* printk("%s di->rxdpa(0x%x-0x%x) \n", __FUNCTION__, PHYSADDRHI(di->rxdpa), PHYSADDRLO(di->rxdpa)); */ ++ di->rxdalloc = alloced; ++ ASSERT(ISALIGNED(PHYSADDRLO(di->rxdpa), align)); ++ } ++ ++ return TRUE; ++} ++ ++static bool ++dma64_txreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ /* suspend tx DMA first */ ++ W_REG(di->osh, &di->d64txregs->control, D64_XC_SE); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED) && ++ (status != D64_XS0_XS_IDLE) && ++ (status != D64_XS0_XS_STOPPED), ++ 10000); ++ ++ W_REG(di->osh, &di->d64txregs->control, 0); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != ++ D64_XS0_XS_DISABLED), ++ 10000); ++ ++ /* We should be disabled at this point */ ++ if (status != D64_XS0_XS_DISABLED) { ++ DMA_ERROR(("%s: status != D64_XS0_XS_DISABLED 0x%x\n", __FUNCTION__, status)); ++ ASSERT(status == D64_XS0_XS_DISABLED); ++ OSL_DELAY(300); ++ } ++ ++ return (status == D64_XS0_XS_DISABLED); ++} ++ ++static bool ++dma64_rxidle(dma_info_t *di) ++{ ++ DMA_TRACE(("%s: dma_rxidle\n", di->name)); ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) == ++ (R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK)); ++} ++ ++static bool ++dma64_rxreset(dma_info_t *di) ++{ ++ uint32 status; ++ ++ if (di->nrxd == 0) ++ return TRUE; ++ ++ W_REG(di->osh, &di->d64rxregs->control, 0); ++ ++ SPINWAIT(((status = (R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK)) != ++ D64_RS0_RS_DISABLED), 10000); ++ ++ return (status == D64_RS0_RS_DISABLED); ++} ++ ++static bool ++dma64_rxenabled(dma_info_t *di) ++{ ++ uint32 rc; ++ ++ rc = R_REG(di->osh, &di->d64rxregs->control); ++ return ((rc != 0xffffffff) && (rc & D64_RC_RE)); ++} ++ ++static bool ++dma64_txsuspendedidle(dma_info_t *di) ++{ ++ ++ if (di->ntxd == 0) ++ return TRUE; ++ ++ if (!(R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE)) ++ return 0; ++ ++ if ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) ++ return 1; ++ ++ return 0; ++} ++ ++/* Useful when sending unframed data. This allows us to get a progress report from the DMA. ++ * We return a pointer to the beginning of the data buffer of the current descriptor. ++ * If DMA is idle, we return NULL. ++ */ ++static void* ++dma64_getpos(dma_info_t *di, bool direction) ++{ ++ void *va; ++ bool idle; ++ uint16 cur_idx; ++ ++ if (direction == DMA_TX) { ++ cur_idx = B2I(((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t); ++ idle = !NTXDACTIVE(di->txin, di->txout); ++ va = di->txp[cur_idx]; ++ } else { ++ cur_idx = B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ idle = !NRXDACTIVE(di->rxin, di->rxout); ++ va = di->rxp[cur_idx]; ++ } ++ ++ /* If DMA is IDLE, return NULL */ ++ if (idle) { ++ DMA_TRACE(("%s: DMA idle, return NULL\n", __FUNCTION__)); ++ va = NULL; ++ } ++ ++ return va; ++} ++ ++/* TX of unframed data ++ * ++ * Adds a DMA ring descriptor for the data pointed to by "buf". ++ * This is for DMA of a buffer of data and is unlike other hnddma TX functions ++ * that take a pointer to a "packet" ++ * Each call to this is results in a single descriptor being added for "len" bytes of ++ * data starting at "buf", it doesn't handle chained buffers. ++ */ ++static int ++dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit) ++{ ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; /* phys addr */ ++ ++ txout = di->txout; ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ return 0; ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(buf); ++#else ++ pa = DMA_MAP(di->osh, buf, len, DMA_TX, NULL, &di->txp_dmah[txout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ /* save the buffer pointer - used by dma_getpos */ ++ di->txp[txout] = buf; ++ ++ txout = NEXTTXD(txout); ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* kick the chip */ ++ if (commit) { ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); ++ } ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __FUNCTION__)); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); ++} ++ ++/* RX of unframed data ++ * ++ * Adds a DMA ring descriptor for the data pointed to by "buf". ++ * This is for DMA of a buffer of data and is unlike other hnddma TX functions ++ * that take a pointer to a "packet" ++ * Each call to this is results in a single descriptor being added for "len" bytes of ++ * data starting at "buf", it doesn't handle chained buffers. ++ */ ++static int ++dma64_rxunframed(dma_info_t *di, void *buf, uint len, bool commit) ++{ ++ uint16 rxout; ++ uint32 flags = 0; ++ dmaaddr_t pa; /* phys addr */ ++ ++ rxout = di->rxout; ++ ++ /* return nonzero if out of rx descriptors */ ++ if (NEXTRXD(rxout) == di->rxin) ++ goto outofrxd; ++ ++ if (len == 0) ++ return 0; ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(buf); ++#else ++ pa = DMA_MAP(di->osh, buf, len, DMA_RX, NULL, &di->rxp_dmah[rxout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF); ++ ++ if (rxout == (di->nrxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, len); ++ ASSERT(di->rxp[rxout] == NULL); ++ ++ /* save the buffer pointer - used by dma_getpos */ ++ di->rxp[rxout] = buf; ++ ++ rxout = NEXTRXD(rxout); ++ /* bump the tx descriptor index */ ++ di->rxout = rxout; ++ ++ /* kick the chip */ ++ if (commit) { ++ W_REG(di->osh, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ //DBG("%s (Control Reg)W_REG: 0x%x Value: 0x%x\n", __FUNCTION__, &di->d64rxregs->ptr, di->rcvptrbase + I2B(rxout, dma64dd_t)); ++ } ++ ++ /* tx flow control */ ++ //di->hnddma.rxavail = di->nrxd - NRXDACTIVE(di->rxin, di->rxout) - 1; ++ ++ return (0); ++ ++outofrxd: ++ DMA_ERROR(("%s: %s: out of rxds !!!\n", di->name, __FUNCTION__)); ++ //di->hnddma.rxavail = 0; ++ di->hnddma.rxnobuf++; ++ return (-1); ++} ++ ++/* !! tx entry routine ++ * WARNING: call must check the return value for error. ++ * the error(toss frames) could be fatal and cause many subsequent hard to debug problems ++ */ ++static int BCMFASTPATH ++dma64_txfast(dma_info_t *di, void *p0, bool commit) ++{ ++ void *p, *next; ++ uchar *data; ++ uint len; ++ uint16 txout; ++ uint32 flags = 0; ++ dmaaddr_t pa; ++ bool war; ++ ++ DMA_TRACE(("%s: dma_txfast\n", di->name)); ++ ++ txout = di->txout; ++ war = (di->hnddma.dmactrlflags & DMA_CTRL_DMA_AVOIDANCE_WAR) ? TRUE : FALSE; ++ ++ /* ++ * Walk the chain of packet buffers ++ * allocating and initializing transmit descriptor entries. ++ */ ++ for (p = p0; p; p = next) { ++ uint nsegs, j, segsadd; ++ hnddma_seg_map_t *map = NULL; ++ ++ data = PKTDATA(di->osh, p); ++ len = PKTLEN(di->osh, p); ++#ifdef BCM_DMAPAD ++ len += PKTDMAPAD(di->osh, p); ++#endif /* BCM_DMAPAD */ ++ next = PKTNEXT(di->osh, p); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(next, SKB_PREFETCH_LEN); ++#endif ++ ++ /* return nonzero if out of tx descriptors */ ++ if (NEXTTXD(txout) == di->txin) ++ goto outoftxd; ++ ++ if (len == 0) ++ continue; ++ ++ /* get physical address of buffer start */ ++ if (DMASGLIST_ENAB) ++ bzero(&di->txp_dmah[txout], sizeof(hnddma_seg_map_t)); ++ ++#if defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) ++ pa = virt_to_phys(data); ++#else ++ pa = DMA_MAP(di->osh, data, len, DMA_TX, p, &di->txp_dmah[txout]); ++#endif /* defined(CONFIG_BCM_IPROC_GMAC_ACP) && !defined(BCMDMASGLISTOSL) */ ++ ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[txout]; ++ ++ /* See if all the segments can be accounted for */ ++ if (map->nsegs > (uint)(di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1)) ++ goto outoftxd; ++ ++ nsegs = map->nsegs; ++ } else ++ nsegs = 1; ++ ++ segsadd = 0; ++ for (j = 1; j <= nsegs; j++) { ++ flags = 0; ++ if (p == p0 && j == 1) ++ flags |= D64_CTRL1_SOF; ++ ++ /* With a DMA segment list, Descriptor table is filled ++ * using the segment list instead of looping over ++ * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when ++ * end of segment list is reached. ++ */ ++ if ((!DMASGLIST_ENAB && next == NULL) || ++ (DMASGLIST_ENAB && j == nsegs)) ++ flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ ++ if (DMASGLIST_ENAB) { ++ len = map->segs[j - 1].length; ++ pa = map->segs[j - 1].addr; ++ if (len > 128 && war) { ++ uint remain, new_len, align64; ++ /* check for 64B aligned of pa */ ++ align64 = (uint)(PHYSADDRLO(pa) & 0x3f); ++ align64 = (64 - align64) & 0x3f; ++ new_len = len - align64; ++ remain = new_len % 128; ++ if (remain > 0 && remain <= 4) { ++ uint32 buf_addr_lo; ++ uint32 tmp_flags = ++ flags & (~(D64_CTRL1_EOF | D64_CTRL1_IOC)); ++ flags &= ~(D64_CTRL1_SOF | D64_CTRL1_EOT); ++ remain += 64; ++ dma64_dd_upd(di, di->txd64, pa, txout, ++ &tmp_flags, len-remain); ++ ASSERT(di->txp[txout] == NULL); ++ txout = NEXTTXD(txout); ++ /* return nonzero if out of tx descriptors */ ++ if (txout == di->txin) { ++ DMA_ERROR(("%s: dma_txfast: Out-of-DMA" ++ " descriptors (txin %d txout %d" ++ " nsegs %d)\n", __FUNCTION__, ++ di->txin, di->txout, nsegs)); ++ goto outoftxd; ++ } ++ if (txout == (di->ntxd - 1)) ++ flags |= D64_CTRL1_EOT; ++ buf_addr_lo = PHYSADDRLO(pa); ++ PHYSADDRLOSET(pa, (PHYSADDRLO(pa) + (len-remain))); ++ if (PHYSADDRLO(pa) < buf_addr_lo) { ++ PHYSADDRHISET(pa, (PHYSADDRHI(pa) + 1)); ++ } ++ len = remain; ++ segsadd++; ++ di->dma_avoidance_cnt++; ++ } ++ } ++ } ++ dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); ++ ASSERT(di->txp[txout] == NULL); ++ ++ txout = NEXTTXD(txout); ++ /* return nonzero if out of tx descriptors */ ++ if (txout == di->txin) { ++ DMA_ERROR(("%s: dma_txfast: Out-of-DMA descriptors" ++ " (txin %d txout %d nsegs %d)\n", __FUNCTION__, ++ di->txin, di->txout, nsegs)); ++ goto outoftxd; ++ } ++ } ++ if (segsadd && DMASGLIST_ENAB) ++ map->nsegs += segsadd; ++ ++ /* See above. No need to loop over individual buffers */ ++ if (DMASGLIST_ENAB) ++ break; ++ } ++ ++ /* if last txd eof not set, fix it */ ++ if (!(flags & D64_CTRL1_EOF)) { ++ W_SM(&di->txd64[PREVTXD(txout)].ctrl1, ++ BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); ++ } ++ ++ /* save the packet */ ++ di->txp[PREVTXD(txout)] = p0; ++ ++ /* bump the tx descriptor index */ ++ di->txout = txout; ++ ++ /* Spin lock to prevent TX discriptor protocol errors when using SG lists */ ++ spin_lock(&di->des_lock); ++ spin_unlock(&di->des_lock); ++ ++ /* kick the chip */ ++ if (commit) ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(txout, dma64dd_t)); ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (0); ++ ++outoftxd: ++ DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name)); ++ PKTFREE(di->osh, p0, TRUE); ++ di->hnddma.txavail = 0; ++ di->hnddma.txnobuf++; ++ return (-1); ++} ++ ++/* ++ * Reclaim next completed txd (txds if using chained buffers) in the range ++ * specified and return associated packet. ++ * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be ++ * transmitted as noted by the hardware "CurrDescr" pointer. ++ * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be ++ * transfered by the DMA as noted by the hardware "ActiveDescr" pointer. ++ * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and ++ * return associated packet regardless of the value of hardware pointers. ++ */ ++static void * BCMFASTPATH ++dma64_getnexttxp(dma_info_t *di, txd_range_t range) ++{ ++ uint16 start, end, i; ++ uint16 active_desc; ++ void *txp; ++ ++ DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, ++ (range == HNDDMA_RANGE_ALL) ? "all" : ++ ((range == HNDDMA_RANGE_TRANSMITTED) ? "transmitted" : "transfered"))); ++ ++ if (di->ntxd == 0) ++ return (NULL); ++ ++ txp = NULL; ++ ++ start = di->txin; ++ if (range == HNDDMA_RANGE_ALL) ++ end = di->txout; ++ else { ++ dma64regs_t *dregs = di->d64txregs; ++ ++ if (di->txin == di->xs0cd) { ++ end = (uint16)(B2I(((R_REG(di->osh, &dregs->status0) & D64_XS0_CD_MASK) - ++ di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t)); ++ di->xs0cd = end; ++ } else ++ end = di->xs0cd; ++ ++ if (range == HNDDMA_RANGE_TRANSFERED) { ++ active_desc = (uint16)(R_REG(di->osh, &dregs->status1) & D64_XS1_AD_MASK); ++ active_desc = (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK; ++ active_desc = B2I(active_desc, dma64dd_t); ++ if (end != active_desc) ++ end = PREVTXD(active_desc); ++ } ++ } ++ ++ if ((start == 0) && (end > di->txout)) ++ goto bogus; ++ ++ for (i = start; i != end && !txp; i = NEXTTXD(i)) { ++ dmaaddr_t pa; ++ hnddma_seg_map_t *map = NULL; ++ uint size, j, nsegs; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(di->txp[NEXTTXD(i)], SKB_PREFETCH_LEN); ++#endif ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) - di->dataoffsethigh)); ++ ++ if (DMASGLIST_ENAB) { ++ map = &di->txp_dmah[i]; ++ size = map->origsize; ++ nsegs = map->nsegs; ++ if (nsegs > (uint)NTXDACTIVE(i, end)) { ++ di->xs0cd = i; ++ break; ++ } ++ } else { ++ size = (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK); ++ nsegs = 1; ++ } ++ ++ for (j = nsegs; j > 0; j--) { ++ W_SM(&di->txd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); ++ ++ txp = di->txp[i]; ++ di->txp[i] = NULL; ++ if (j > 1) ++ i = NEXTTXD(i); ++ } ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ ++ di->txin = i; ++ ++ /* tx flow control */ ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ return (txp); ++ ++bogus: ++ DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", ++ start, end, di->txout, forceall)); ++ return (NULL); ++} ++ ++static void * BCMFASTPATH ++dma64_getnextrxp(dma_info_t *di, bool forceall) ++{ ++ uint16 i, curr; ++ void *rxp; ++ dmaaddr_t pa; ++ ++ /* if forcing, dma engine must be disabled */ ++ ASSERT(!forceall || !dma64_rxenabled(di)); ++ ++ i = di->rxin; ++ ++ /* return if no packets posted */ ++ if (i == di->rxout) ++ return (NULL); ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_PREFETCH ++ prefetch_range(di->rxp[NEXTRXD(i)], SKB_PREFETCH_LEN); ++#endif ++ ++ if (di->rxin == di->rs0cd) { ++ curr = (uint16)B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) - ++ di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t); ++ di->rs0cd = curr; ++ } else ++ curr = di->rs0cd; ++ ++ /* ignore curr if forceall */ ++ if (!forceall && (i == curr)) ++ return (NULL); ++ ++ /* get the packet pointer that corresponds to the rx descriptor */ ++ rxp = di->rxp[i]; ++ ASSERT(rxp); ++ di->rxp[i] = NULL; ++ ++ PHYSADDRLOSET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) - di->dataoffsetlow)); ++ PHYSADDRHISET(pa, (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) - di->dataoffsethigh)); ++ ++ /* clear this packet from the descriptor ring */ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ DMA_UNMAP(di->osh, pa, ++ di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++ ++ W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); ++ W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); ++ ++ di->rxin = NEXTRXD(i); ++ ++ return (rxp); ++} ++ ++static bool ++_dma64_addrext(osl_t *osh, dma64regs_t *dma64regs) ++{ ++ uint32 w; ++ OR_REG(osh, &dma64regs->control, D64_XC_AE); ++ w = R_REG(osh, &dma64regs->control); ++ AND_REG(osh, &dma64regs->control, ~D64_XC_AE); ++ return ((w & D64_XC_AE) == D64_XC_AE); ++} ++ ++/* ++ * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). ++ */ ++static void ++dma64_txrotate(dma_info_t *di) ++{ ++ uint16 ad; ++ uint nactive; ++ uint rot; ++ uint16 old, new; ++ uint32 w; ++ uint16 first, last; ++ ++ ASSERT(dma64_txsuspendedidle(di)); ++ ++ nactive = _dma_txactive(di); ++ ad = B2I((((R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK) ++ - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t); ++ rot = TXD(ad - di->txin); ++ ++ ASSERT(rot < di->ntxd); ++ ++ /* full-ring case is a lot harder - don't worry about this */ ++ if (rot >= (di->ntxd - nactive)) { ++ DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); ++ return; ++ } ++ ++ first = di->txin; ++ last = PREVTXD(di->txout); ++ ++ /* move entries starting at last and moving backwards to first */ ++ for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { ++ new = TXD(old + rot); ++ ++ /* ++ * Move the tx dma descriptor. ++ * EOT is set only in the last entry in the ring. ++ */ ++ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; ++ if (new == (di->ntxd - 1)) ++ w |= D64_CTRL1_EOT; ++ W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w)); ++ ++ w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2)); ++ W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w)); ++ ++ W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); ++ W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); ++ ++ /* zap the old tx dma descriptor address field */ ++ W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef)); ++ W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef)); ++ ++ /* move the corresponding txp[] entry */ ++ ASSERT(di->txp[new] == NULL); ++ di->txp[new] = di->txp[old]; ++ ++ /* Move the map */ ++ if (DMASGLIST_ENAB) { ++ bcopy(&di->txp_dmah[old], &di->txp_dmah[new], sizeof(hnddma_seg_map_t)); ++ bzero(&di->txp_dmah[old], sizeof(hnddma_seg_map_t)); ++ } ++ ++ di->txp[old] = NULL; ++ } ++ ++ /* update txin and txout */ ++ di->txin = ad; ++ di->txout = TXD(di->txout + rot); ++ di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; ++ ++ /* kick the chip */ ++ W_REG(di->osh, &di->d64txregs->ptr, di->xmtptrbase + I2B(di->txout, dma64dd_t)); ++} ++ ++uint ++BCMATTACHFN(dma_addrwidth)(si_t *sih, void *dmaregs) ++{ ++ dma32regs_t *dma32regs; ++ osl_t *osh; ++ ++ osh = si_osh(sih); ++ ++ /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */ ++ /* DMA engine is 64-bit capable */ ++ if ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) { ++ /* backplane are 64-bit capable */ ++ if (si_backplane64(sih)) ++ /* If bus is System Backplane or PCIE then we can access 64-bits */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) || ++ ((BUSTYPE(sih->bustype) == PCI_BUS) && ++ ((sih->buscoretype == PCIE_CORE_ID) || ++ (sih->buscoretype == PCIE2_CORE_ID)))) ++ return (DMADDRWIDTH_64); ++ ++ /* DMA64 is always 32-bit capable, AE is always TRUE */ ++ ASSERT(_dma64_addrext(osh, (dma64regs_t *)dmaregs)); ++ ++ return (DMADDRWIDTH_32); ++ } ++ ++ /* Start checking for 32-bit / 30-bit addressing */ ++ dma32regs = (dma32regs_t *)dmaregs; ++ ++ /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) || ++ ((BUSTYPE(sih->bustype) == PCI_BUS) && ++ ((sih->buscoretype == PCIE_CORE_ID) || ++ (sih->buscoretype == PCIE2_CORE_ID))) || ++ (_dma32_addrext(osh, dma32regs))) ++ return (DMADDRWIDTH_32); ++ ++ /* Fallthru */ ++ return (DMADDRWIDTH_30); ++} ++ ++static int ++_dma_pktpool_set(dma_info_t *di, pktpool_t *pool) ++{ ++ ASSERT(di); ++ ASSERT(di->pktpool == NULL); ++ di->pktpool = pool; ++ return 0; ++} ++ ++static bool ++_dma_rxtx_error(dma_info_t *di, bool istx) ++{ ++ uint32 status1 = 0; ++ uint16 curr; ++ ++ if (DMA64_ENAB(di) && DMA64_MODE(di)) { ++ ++ if (istx) { ++ ++ status1 = R_REG(di->osh, &di->d64txregs->status1); ++ ++ if ((status1 & D64_XS1_XE_MASK) != D64_XS1_XE_NOERR) ++ return TRUE; ++ else if (si_coreid(di->sih) == GMAC_CORE_ID && si_corerev(di->sih) >= 4) { ++ curr = (uint16)(B2I(((R_REG(di->osh, &di->d64txregs->status0) & ++ D64_XS0_CD_MASK) - di->xmtptrbase) & ++ D64_XS0_CD_MASK, dma64dd_t)); ++ ++ if (NTXDACTIVE(di->txin, di->txout) != 0 && ++ curr == di->xs0cd_snapshot) { ++ ++ /* suspicious */ ++ return TRUE; ++ } ++ di->xs0cd_snapshot = di->xs0cd = curr; ++ ++ return FALSE; ++ } ++ else ++ return FALSE; ++ } ++ else { ++ ++ status1 = R_REG(di->osh, &di->d64rxregs->status1); ++ ++ if ((status1 & D64_RS1_RE_MASK) != D64_RS1_RE_NOERR) ++ return TRUE; ++ else ++ return FALSE; ++ } ++ ++ } else if (DMA32_ENAB(di)) { ++ return FALSE; ++ ++ } else { ++ ASSERT(0); ++ return FALSE; ++ } ++ ++} ++ ++void ++_dma_burstlen_set(dma_info_t *di, uint8 rxburstlen, uint8 txburstlen) ++{ ++ di->rxburstlen = rxburstlen; ++ di->txburstlen = txburstlen; ++} ++ ++void ++_dma_param_set(dma_info_t *di, uint16 paramid, uint16 paramval) ++{ ++ switch (paramid) { ++ case HNDDMA_PID_TX_MULTI_OUTSTD_RD: ++ di->txmultioutstdrd = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_PREFETCH_CTL: ++ di->txprefetchctl = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_PREFETCH_THRESH: ++ di->txprefetchthresh = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_TX_BURSTLEN: ++ di->txburstlen = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_PREFETCH_CTL: ++ di->rxprefetchctl = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_PREFETCH_THRESH: ++ di->rxprefetchthresh = (uint8)paramval; ++ break; ++ ++ case HNDDMA_PID_RX_BURSTLEN: ++ di->rxburstlen = (uint8)paramval; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static bool ++_dma_glom_enable(dma_info_t *di, uint32 val) ++{ ++ dma64regs_t *dregs = di->d64rxregs; ++ bool ret = TRUE; ++ if (val) { ++ OR_REG(di->osh, &dregs->control, D64_RC_GE); ++ if (!(R_REG(di->osh, &dregs->control) & D64_RC_GE)) ++ ret = FALSE; ++ } else { ++ AND_REG(di->osh, &dregs->control, ~D64_RC_GE); ++ } ++ return ret; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/hndfwd.c b/drivers/bcmdrivers/gmac/src/shared/hndfwd.c +new file mode 100755 +index 0000000..5dddaf6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hndfwd.c +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * HND GMAC Forwarder ++ * ++ * $Id$ ++ */ ++ ++#if defined(GMAC3) ++ ++#include ++#include ++#include ++ ++#if defined(CONFIG_SMP) ++#define _FWDER_GET(fwder_instance, unit) &per_cpu(fwder_instance, unit) ++#else /* !CONFIG_SMP */ ++#define _FWDER_GET(fwder_instance, unit) &fwder_instance[unit] ++#endif /* !CONFIG_SMP */ ++ ++ ++static int /* default dummy xmit handler when tx device is down */ ++_fwder_default(struct sk_buff * skb, struct net_device * dev, int cnt) ++{ ++ return FWDER_FAILURE; ++} ++ ++#if defined(CONFIG_SMP) ++DEFINE_PER_CPU(struct fwder, fwd_upstream) = { ++ .lock = __SPIN_LOCK_UNLOCKED(.lock), /* static init */ ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .error = 0U ++}; ++ ++DEFINE_PER_CPU(struct fwder, fwd_dnstream) = { ++ .lock = __SPIN_LOCK_UNLOCKED(.lock), ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .error = 0U ++}; ++#else /* !CONFIG_SMP */ ++struct fwder fwd_upstream[FWDER_MAX_UNITS] = { ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 0, ++ .error = 0U ++ }, ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 1, ++ .error = 0U ++ } ++}; ++struct fwder fwd_dnstream[FWDER_MAX_UNITS] = { ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 0, ++ .error = 0U ++ }, ++ { ++ .dev = (struct net_device *)NULL, ++ .forward = (fwder_start_t)NULL, ++ .unit = 1, ++ .error = 0U ++ } ++}; ++#endif /* !CONFIG_SMP */ ++ ++static inline ++struct fwder * _get_other(struct fwder * fwder_p) ++{ ++ struct fwder * other_p; ++ ++ other_p = _FWDER_GET(fwd_upstream, fwder_p->unit); ++ if (other_p == fwder_p) ++ return _FWDER_GET(fwd_dnstream, fwder_p->unit); ++ else ++ return other_p; ++} ++ ++int /* Initialization of fwder in et_module_init */ ++fwder_init(void) ++{ ++ int dir; ++ fwder_t * fwder_p; ++ int unit; ++ ++#if defined(CONFIG_SMP) ++ for_each_online_cpu(unit) ++#else /* !CONFIG_SMP */ ++ for (unit = 0; unit < FWDER_MAX_UNITS; unit++) ++#endif /* !CONFIG_SMP */ ++ { ++ for (dir = (int)FWD_UPSTREAM; dir < (int)FWD_MAX_DIRS; dir++) { ++ if (dir == (int)FWD_UPSTREAM) ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ else ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ fwder_p->dev = (struct net_device *)fwder_p; ++ fwder_p->forward = (fwder_start_t)_fwder_default; ++ fwder_p->unit = unit; ++ fwder_p->error = 0U; ++ } ++ ++ } /* for_each_online_cpu / for unit = 0 .. FWDER_MAX_UNITS */ ++ ++printk("===FWD: fwder_init\n"); // DELETE ME ++ return 0; ++} ++ ++struct fwder * /* Driver registers its xx_start_xmit() handler on netdev open */ ++fwder_attach(fwder_start_t forward, const struct net_device * dev, ++ const int unit, const enum fwder_dir dir) ++{ ++ fwder_t * fwder_p; ++ fwder_t * other_p; /* reverse direction forwarder */ ++ ++ printk("fwder_attach forward<%p> dev<%p> unit<%d> dir<%d>\n", ++ forward, dev, unit, dir); ++ ++ ASSERT((dir < (int)FWD_MAX_DIRS) && (dev != (struct net_device *)NULL) ++ && (forward != (fwder_start_t)NULL)); ++ ++#if defined(CONFIG_SMP) ++ ASSERT(unit < NR_CPUS); ++#else /* !CONFIG_SMP */ ++ ASSERT(unit < FWDER_MAX_UNITS); ++#endif /* !CONFIG_SMP */ ++ ++ if (dir == (int)FWD_UPSTREAM) { ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ other_p = _FWDER_GET(fwd_dnstream, unit); ++ } else { ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ other_p = _FWDER_GET(fwd_upstream, unit); ++ } ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ fwder_p->dev = (struct net_device *)dev; ++ fwder_p->forward = forward; ++ ++ _FWDER_UNLOCK(fwder_p); /* ++LOCK */ ++ ++printk("===FWD: ATTACH<%d,%d>: <%p> unit<%d> dir<%d> dev<%p> xmit<%p>\n", unit, (int)dir, fwder_p, fwder_p->unit, dir, fwder_p->dev, fwder_p->forward); // DELETE ME ++printk("===FWD: RETURN<%d,%d>: <%p> unit<%d> dir<%d> dev<%p> xmit<%p>\n", unit, (int)dir, other_p, other_p->unit, dir^1, other_p->dev, other_p->forward); // DELETE ME ++ ++ return other_p; ++} ++ ++struct fwder * /* A driver deregisters itself on netdev close */ ++fwder_dettach(struct fwder * fwder_p) ++{ ++ ++ if (fwder_p == (fwder_t *)NULL) ++ return (fwder_t *)NULL; ++ ++ printk("fwder_dettach <%p>\n", fwder_p); ++ ++ fwder_p = _get_other(fwder_p); ++ ++ _FWDER_LOCK(fwder_p); /* ++LOCK */ ++ ++ fwder_p->dev = (struct net_device *)NULL; ++ fwder_p->forward = (fwder_start_t)_fwder_default; ++ ++ _FWDER_UNLOCK(fwder_p); /* ++LOCK */ ++ ++ return (fwder_t *)NULL; ++} ++ ++void ++fwder_dump(const struct fwder * fwder_p) ++{ ++ if (fwder_p == (fwder_t *)NULL) ++ return; ++ ++ printk("FWD<%p>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++} ++ ++void ++fwder_dump_all(void) ++{ ++ int unit; ++ struct fwder * fwder_p; ++ ++ printk("FWDER DUMP ALL default<%p>\n", _fwder_default); ++#if defined(CONFIG_SMP) ++ for_each_online_cpu(unit) ++#else /* !CONFIG_SMP */ ++ for (unit = 0; unit < FWDER_MAX_UNITS; unit++) ++#endif /* !CONFIG_SMP */ ++ { ++ fwder_p = _FWDER_GET(fwd_upstream, unit); ++ printk("FWD[UP]<%p> CPU<%d>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, unit, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++ ++ fwder_p = _FWDER_GET(fwd_dnstream, unit); ++ printk("FWD[DN]<%p> CPU<%d>: dev<%p> forward<%p> unit<%d> error<%u>\n", ++ fwder_p, unit, fwder_p->dev, fwder_p->forward, ++ fwder_p->unit, fwder_p->error); ++ ++ } /* for_each_online_cpu / for unit = 0 .. FWDER_MAX_UNITS */ ++} ++ ++#endif /* GMAC3 */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c +new file mode 100755 +index 0000000..4c93c3a +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.c +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 hr2_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h +new file mode 100755 +index 0000000..f7354c6 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hr2_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _hr2_erom_h_ ++#define _hr2_erom_h_ ++ ++extern uint32 hr2_erom[]; ++ ++#endif //_hr2_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c +new file mode 100755 +index 0000000..0f83e7f +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 hx4_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h +new file mode 100755 +index 0000000..4170fb4 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/hx4_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _hx4_erom_h_ ++#define _hx4_erom_h_ ++ ++extern uint32 hx4_erom[]; ++ ++#endif //_hx4_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c +new file mode 100755 +index 0000000..ddd9494 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++#include ++ ++uint32 kt2_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h +new file mode 100755 +index 0000000..b2b6095 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/kt2_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _kt2_erom_h_ ++#define _kt2_erom_h_ ++ ++extern uint32 kt2_erom[]; ++ ++#endif //_kt2_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/linux_osl.c b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c +new file mode 100755 +index 0000000..aa06749 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/linux_osl.c +@@ -0,0 +1,1713 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Linux OS Independent Layer ++ * ++ * $Id: linux_osl.c 322208 2012-03-20 01:53:23Z $ ++ */ ++ ++#define LINUX_PORT ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef mips ++#include ++#endif /* mips */ ++#include ++ ++ ++ ++#include ++#include ++ ++#define PCI_CFG_RETRY 10 ++ ++#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ ++#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ ++ ++#ifdef DHD_USE_STATIC_BUF ++#define STATIC_BUF_MAX_NUM 16 ++#define STATIC_BUF_SIZE (PAGE_SIZE*2) ++#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) ++ ++typedef struct bcm_static_buf { ++ struct semaphore static_sem; ++ unsigned char *buf_ptr; ++ unsigned char buf_use[STATIC_BUF_MAX_NUM]; ++} bcm_static_buf_t; ++ ++static bcm_static_buf_t *bcm_static_buf = 0; ++ ++#define STATIC_PKT_MAX_NUM 8 ++ ++typedef struct bcm_static_pkt { ++ struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; ++ struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM]; ++ struct semaphore osl_pkt_sem; ++ unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2]; ++} bcm_static_pkt_t; ++ ++static bcm_static_pkt_t *bcm_static_skb = 0; ++#endif /* DHD_USE_STATIC_BUF */ ++ ++typedef struct bcm_mem_link { ++ struct bcm_mem_link *prev; ++ struct bcm_mem_link *next; ++ uint size; ++ int line; ++ void *osh; ++ char file[BCM_MEM_FILENAME_LEN]; ++} bcm_mem_link_t; ++ ++struct osl_info { ++ osl_pubinfo_t pub; ++#ifdef CTFPOOL ++ ctfpool_t *ctfpool; ++#endif /* CTFPOOL */ ++ uint magic; ++ void *pdev; ++ atomic_t malloced; ++ atomic_t pktalloced; /* Number of allocated packet buffers */ ++ uint failed; ++ uint bustype; ++ bcm_mem_link_t *dbgmem_list; ++#if defined(DSLCPE_DELAY) ++ shared_osl_t *oshsh; /* osh shared */ ++#endif ++ spinlock_t dbgmem_lock; ++ spinlock_t pktalloc_lock; ++}; ++ ++#define OSL_PKTTAG_CLEAR(p) \ ++do { \ ++ struct sk_buff *s = (struct sk_buff *)(p); \ ++ ASSERT(OSL_PKTTAG_SZ == 32); \ ++ *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ ++ *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ ++ *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ ++ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ ++} while (0) ++ ++/* PCMCIA attribute space access macros */ ++#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) ++struct pcmcia_dev { ++ dev_link_t link; /* PCMCIA device pointer */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ++ dev_node_t node; /* PCMCIA node structure */ ++#endif ++ void *base; /* Mapped attribute memory window */ ++ size_t size; /* Size of window */ ++ void *drv; /* Driver data */ ++}; ++#endif /* defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) */ ++ ++/* Global ASSERT type flag */ ++uint32 g_assert_type = FALSE; ++ ++static int16 linuxbcmerrormap[] = ++{ 0, /* 0 */ ++ -EINVAL, /* BCME_ERROR */ ++ -EINVAL, /* BCME_BADARG */ ++ -EINVAL, /* BCME_BADOPTION */ ++ -EINVAL, /* BCME_NOTUP */ ++ -EINVAL, /* BCME_NOTDOWN */ ++ -EINVAL, /* BCME_NOTAP */ ++ -EINVAL, /* BCME_NOTSTA */ ++ -EINVAL, /* BCME_BADKEYIDX */ ++ -EINVAL, /* BCME_RADIOOFF */ ++ -EINVAL, /* BCME_NOTBANDLOCKED */ ++ -EINVAL, /* BCME_NOCLK */ ++ -EINVAL, /* BCME_BADRATESET */ ++ -EINVAL, /* BCME_BADBAND */ ++ -E2BIG, /* BCME_BUFTOOSHORT */ ++ -E2BIG, /* BCME_BUFTOOLONG */ ++ -EBUSY, /* BCME_BUSY */ ++ -EINVAL, /* BCME_NOTASSOCIATED */ ++ -EINVAL, /* BCME_BADSSIDLEN */ ++ -EINVAL, /* BCME_OUTOFRANGECHAN */ ++ -EINVAL, /* BCME_BADCHAN */ ++ -EFAULT, /* BCME_BADADDR */ ++ -ENOMEM, /* BCME_NORESOURCE */ ++ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ ++ -EMSGSIZE, /* BCME_BADLENGTH */ ++ -EINVAL, /* BCME_NOTREADY */ ++ -EPERM, /* BCME_EPERM */ ++ -ENOMEM, /* BCME_NOMEM */ ++ -EINVAL, /* BCME_ASSOCIATED */ ++ -ERANGE, /* BCME_RANGE */ ++ -EINVAL, /* BCME_NOTFOUND */ ++ -EINVAL, /* BCME_WME_NOT_ENABLED */ ++ -EINVAL, /* BCME_TSPEC_NOTFOUND */ ++ -EINVAL, /* BCME_ACM_NOTSUPPORTED */ ++ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ ++ -EIO, /* BCME_SDIO_ERROR */ ++ -ENODEV, /* BCME_DONGLE_DOWN */ ++ -EINVAL, /* BCME_VERSION */ ++ -EIO, /* BCME_TXFAIL */ ++ -EIO, /* BCME_RXFAIL */ ++ -ENODEV, /* BCME_NODEVICE */ ++ -EINVAL, /* BCME_NMODE_DISABLED */ ++ -ENODATA, /* BCME_NONRESIDENT */ ++ ++/* When an new error code is added to bcmutils.h, add os ++ * specific error translation here as well ++ */ ++/* check if BCME_LAST changed since the last time this function was updated */ ++#if BCME_LAST != -42 ++#error "You need to add a OS error translation in the linuxbcmerrormap \ ++ for new error code defined in bcmutils.h" ++#endif ++}; ++ ++/* translate bcmerrors into linux errors */ ++int ++osl_error(int bcmerror) ++{ ++ if (bcmerror > 0) ++ bcmerror = 0; ++ else if (bcmerror < BCME_LAST) ++ bcmerror = BCME_ERROR; ++ ++ /* Array bounds covered by ASSERT in osl_attach */ ++ return linuxbcmerrormap[-bcmerror]; ++} ++ ++extern uint8* dhd_os_prealloc(void *osh, int section, int size); ++ ++EXPORT_SYMBOL(osl_attach); ++osl_t * ++osl_attach(void *pdev, uint bustype, bool pkttag) ++{ ++ osl_t *osh; ++ ++ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); ++ ASSERT(osh); ++ ++ bzero(osh, sizeof(osl_t)); ++ ++ /* Check that error map has the right number of entries in it */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); ++ ++ osh->magic = OS_HANDLE_MAGIC; ++ atomic_set(&osh->malloced, 0); ++ osh->failed = 0; ++ osh->dbgmem_list = NULL; ++ spin_lock_init(&(osh->dbgmem_lock)); ++ osh->pdev = pdev; ++ osh->pub.pkttag = pkttag; ++ osh->bustype = bustype; ++ ++ switch (bustype) { ++ case PCI_BUS: ++ case SI_BUS: ++ case PCMCIA_BUS: ++ osh->pub.mmbus = TRUE; ++ break; ++ case JTAG_BUS: ++ case SDIO_BUS: ++ case USB_BUS: ++ case SPI_BUS: ++ case RPC_BUS: ++ osh->pub.mmbus = FALSE; ++ break; ++ default: ++ ASSERT(FALSE); ++ break; ++ } ++ ++#if defined(DHD_USE_STATIC_BUF) ++ if (!bcm_static_buf) { ++ if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ ++ STATIC_BUF_TOTAL_LEN))) { ++ printk("can not alloc static buf!\n"); ++ } ++ else ++ printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); ++ ++ ++ sema_init(&bcm_static_buf->static_sem, 1); ++ ++ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; ++ } ++ ++ if (!bcm_static_skb) { ++ int i; ++ void *skb_buff_ptr = 0; ++ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); ++ skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); ++ ++ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); ++ for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) ++ bcm_static_skb->pkt_use[i] = 0; ++ ++ sema_init(&bcm_static_skb->osl_pkt_sem, 1); ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ spin_lock_init(&(osh->pktalloc_lock)); ++ ++#ifdef BCMDBG ++ if (pkttag) { ++ struct sk_buff *skb; ++ ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb)); ++ } ++#endif ++ return osh; ++} ++ ++void ++osl_detach(osl_t *osh) ++{ ++ if (osh == NULL) ++ return; ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif ++ ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ kfree(osh); ++} ++ ++static struct sk_buff *osl_alloc_skb(unsigned int len) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) ++ gfp_t flags = GFP_ATOMIC; ++ ++ return __dev_alloc_skb(len, flags); ++#else ++ return dev_alloc_skb(len); ++#endif ++} ++ ++#ifdef CTFPOOL ++ ++#ifdef CTFPOOL_SPINLOCK ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_irqsave(&(ctfpool)->lock, flags) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_irqrestore(&(ctfpool)->lock, flags) ++#else ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_bh(&(ctfpool)->lock) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_bh(&(ctfpool)->lock) ++#endif /* CTFPOOL_SPINLOCK */ ++/* ++ * Allocate and add an object to packet pool. ++ */ ++void * ++osl_ctfpool_add(osl_t *osh) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj); ++ ++ /* No need to allocate more objects */ ++ if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Allocate a new skb and add it to the ctfpool */ ++ skb = osl_alloc_skb(osh->ctfpool->obj_size); ++ if (skb == NULL) { ++ printk("%s: skb alloc of len %d failed\n", __FUNCTION__, ++ osh->ctfpool->obj_size); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Add to ctfpool */ ++ skb->next = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = skb; ++ osh->ctfpool->fast_frees++; ++ osh->ctfpool->curr_obj++; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#ifdef SKB_RECYCLING_DEBUG ++ if ((osh->ctfpool->unit == 2)) { ++ static int count = 0; ++ printk("<%d>allocated skb=%p\n", count, skb); ++ count++; ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ /* Fot reset during release to pool */ ++ skb->reset_size = skb->truesize; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ /* Hijack a skb member to store ptr to ctfpool */ ++ CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool; ++ ++ /* Use bit flag to indicate skb from fast ctfpool */ ++ PKTFAST(osh, skb) = FASTBUF; ++ ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ return skb; ++} ++ ++/* ++ * Add new objects to the pool. ++ */ ++void ++osl_ctfpool_replenish(osl_t *osh, uint thresh) ++{ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ /* Do nothing if no refills are required */ ++ while ((osh->ctfpool->refills > 0) && (thresh--)) { ++ osl_ctfpool_add(osh); ++ osh->ctfpool->refills--; ++ } ++} ++ ++/* ++ * Initialize the packet pool with specified number of objects. ++ */ ++int32 ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++osl_ctfpool_init(int unit, osl_t *osh, uint numobj, uint size) ++#else ++osl_ctfpool_init(osl_t *osh, uint numobj, uint size) ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++{ ++ osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); ++ ASSERT(osh->ctfpool); ++ bzero(osh->ctfpool, sizeof(ctfpool_t)); ++ ++ osh->ctfpool->max_obj = numobj; ++ osh->ctfpool->obj_size = size; ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ osh->ctfpool->unit = unit; ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ spin_lock_init(&osh->ctfpool->lock); ++ ++ while (numobj--) { ++ if (!osl_ctfpool_add(osh)) ++ return -1; ++ osh->ctfpool->fast_frees--; ++ } ++ ++#ifdef SKB_RECYCLING_DEBUG ++ printk("ctfpool = %p\n", osh->ctfpool); ++#endif /* SKB_RECYCLING_DEBUG */ ++ return 0; ++} ++ ++/* ++ * Cleanup the packet pool objects. ++ */ ++void ++osl_ctfpool_cleanup(osl_t *osh) ++{ ++ struct sk_buff *skb, *nskb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ++ skb = osh->ctfpool->head; ++ ++ while (skb != NULL) { ++ nskb = skb->next; ++ dev_kfree_skb(skb); ++ skb = nskb; ++ osh->ctfpool->curr_obj--; ++ } ++ ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->head = NULL; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ kfree(osh->ctfpool); ++ osh->ctfpool = NULL; ++} ++ ++void ++osl_ctfpool_stats(osl_t *osh, void *b) ++{ ++ struct bcmstrbuf *bb; ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ bb = b; ++ ++ ASSERT((osh != NULL) && (bb != NULL)); ++ ++ bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n", ++ osh->ctfpool->max_obj, osh->ctfpool->obj_size, ++ osh->ctfpool->curr_obj, osh->ctfpool->refills); ++ bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n", ++ osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees, ++ osh->ctfpool->slow_allocs); ++} ++ ++static inline struct sk_buff * ++osl_pktfastget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ /* Try to do fast allocate. Return null if ctfpool is not in use ++ * or if there are no items in the ctfpool. ++ */ ++ if (osh->ctfpool == NULL) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ if (osh->ctfpool->head == NULL) { ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->slow_allocs++; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++#ifdef SKB_RECYCLING_DEBUG ++ WARN_ON_ONCE(1); ++#endif /* SKB_RECYCLING_DEBUG */ ++ return NULL; ++ } ++ ++ ASSERT(len <= osh->ctfpool->obj_size); ++ if (len > osh->ctfpool->obj_size) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Get an object from ctfpool */ ++ skb = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = (void *)skb->next; ++ ++#ifdef SKB_RECYCLING_DEBUG ++ { ++ if (skb->next == NULL) { ++ printk("Get a skb whose next is empty: osh->ctfpool=%p, \ ++ skb=%p, skb->next=%p, osh->ctfpool->head=%p\n", ++ osh->ctfpool, skb, skb->next, osh->ctfpool->head); ++ } ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ ++ ++ osh->ctfpool->fast_allocs++; ++ osh->ctfpool->curr_obj--; ++ ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ /* Init skb struct */ ++ skb->next = skb->prev = NULL; ++ skb->data = skb->head + 16; ++ skb->tail = skb->head + 16; ++ ++ skb->len = 0; ++ skb->cloned = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) ++ skb->list = NULL; ++#endif ++ atomic_set(&skb->users, 1); ++ ++ PKTSETCLINK(skb, NULL); ++ PKTCCLRATTR(skb); ++#ifdef HNDCTF ++ PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED); ++#endif ++ return skb; ++} ++#endif /* CTFPOOL */ ++/* Convert a driver packet to native(OS) packet ++ * In the process, packettag is zeroed out before sending up ++ * IP code depends on skb->cb to be setup correctly with various options ++ * In our case, that means it should be 0 ++ */ ++struct sk_buff * BCMFASTPATH ++osl_pkt_tonative(osl_t *osh, void *pkt) ++{ ++ struct sk_buff *nskb; ++ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(pkt); ++ ++ /* Decrement the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); ++ } ++ return (struct sk_buff *)pkt; ++} ++ ++/* Convert a native(OS) packet to driver packet. ++ * In the process, native packet is destroyed, there is no copying ++ * Also, a packettag is zeroed out ++ */ ++void * BCMFASTPATH ++osl_pkt_frmnative(osl_t *osh, void *pkt) ++{ ++ struct sk_buff *nskb; ++ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(pkt); ++ ++ /* Increment the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); ++ } ++ return (void *)pkt; ++} ++ ++/* Return a new packet. zero out pkttag */ ++void * BCMFASTPATH ++osl_pktget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++ ++#ifdef CTFPOOL ++ /* Allocate from local pool */ ++ skb = osl_pktfastget(osh, len); ++ ++#ifdef SKB_RECYCLING_DEBUG ++ if (skb == NULL) { ++ printk("<%s> osl_pktfastget fail! ctfpool=%p, ctfpool->head=%p, \ ++ ctfpool->curr_obj=%u, ctfpool->fast_allocs=%u, \ ++ ctfpool->fast_frees=%u, ctfpool->slow_allocs=%u\n", ++ __FUNCTION__, osh->ctfpool, osh->ctfpool->head, ++ osh->ctfpool->curr_obj, osh->ctfpool->fast_allocs, ++ osh->ctfpool->fast_frees, osh->ctfpool->slow_allocs); ++ } ++#endif /* SKB_RECYCLING_DEBUG */ ++ ++ if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { ++#else /* CTFPOOL */ ++ if ((skb = osl_alloc_skb(len))) { ++#endif /* CTFPOOL */ ++ skb_put(skb, len); ++ skb->priority = 0; ++ ++ atomic_inc(&osh->pktalloced); ++ } ++ ++ PKTSETCLINK(skb, NULL); ++ ++ return ((void*) skb); ++} ++ ++#ifdef CTFPOOL ++static inline void ++osl_pktfastfree(osl_t *osh, struct sk_buff *skb) ++{ ++ ctfpool_t *ctfpool; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++ ++ if (skb->destructor) { ++ WARN_ON(in_irq()); ++ skb->destructor(skb); ++ } ++ ++ skb->data_len = 0; ++ skb->truesize = skb->reset_size; ++ ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR) ++ skb->tstamp.tv.sec = 0; /*ING*/ ++#else ++ skb->tstamp.tv64 = 0; ++#endif ++#else ++ skb->stamp.tv_sec = 0; ++#endif ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++ /* We only need to init the fields that we change */ ++ skb->dev = NULL; ++ ++#ifndef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ skb->dst = NULL; ++#endif ++#endif /* !CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ OSL_PKTTAG_CLEAR(skb); ++ skb->ip_summed = 0; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) ++ skb_orphan(skb); ++#else ++ skb->destructor = NULL; ++#endif ++ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ ++ /* Add object to the ctfpool */ ++ CTFPOOL_LOCK(ctfpool, flags); ++ skb->next = (struct sk_buff *)ctfpool->head; ++ ctfpool->head = (void *)skb; ++ ++ ctfpool->fast_frees++; ++ ctfpool->curr_obj++; ++ ++ ASSERT(ctfpool->curr_obj <= ctfpool->max_obj); ++ CTFPOOL_UNLOCK(ctfpool, flags); ++} ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING ++bool pktfastfree_wrapper(struct sk_buff *skb) ++{ ++ int rval = FALSE; ++ ++ if (PKTISFAST(NULL, skb)) { ++ osl_pktfastfree(NULL, skb); ++ rval = TRUE; ++ } ++ ++ return rval; ++} ++#endif /* CONFIG_BCM_IPROC_GMAC_SKB_RECYCLING */ ++ ++#endif /* CTFPOOL */ ++ ++/* Free the driver packet. Free the tag if present */ ++void BCMFASTPATH ++osl_pktfree(osl_t *osh, void *p, bool send) ++{ ++ struct sk_buff *skb, *nskb; ++ ++ skb = (struct sk_buff*) p; ++ ++ if (send && osh->pub.tx_fn) ++ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); ++ ++ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); ++ ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; ++ ++ ++#ifdef CTFMAP ++ /* Clear the map ptr before freeing */ ++ PKTCLRCTF(osh, skb); ++ CTFMAPPTR(osh, skb) = NULL; ++#endif /* CTFMAP */ ++ ++#ifdef CTFPOOL ++ if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1)) ++ osl_pktfastfree(osh, skb); ++ else { ++#else /* CTFPOOL */ ++ { ++#endif /* CTFPOOL */ ++ ++ if (skb->destructor) ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if ++ * destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ else ++ /* can free immediately (even in_irq()) if destructor ++ * does not exist ++ */ ++ dev_kfree_skb(skb); ++ } ++ atomic_dec(&osh->pktalloced); ++ skb = nskb; ++ } ++} ++ ++#ifdef DHD_USE_STATIC_BUF ++void* ++osl_pktget_static(osl_t *osh, uint len) ++{ ++ int i = 0; ++ struct sk_buff *skb; ++ ++ if (len > (PAGE_SIZE*2)) { ++ printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); ++ return osl_pktget(osh, len); ++ } ++ ++ down(&bcm_static_skb->osl_pkt_sem); ++ ++ if (len <= PAGE_SIZE) { ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i] = 1; ++ up(&bcm_static_skb->osl_pkt_sem); ++ skb = bcm_static_skb->skb_4k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ return skb; ++ } ++ } ++ ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; ++ up(&bcm_static_skb->osl_pkt_sem); ++ skb = bcm_static_skb->skb_8k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ return skb; ++ } ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ printk("%s: all static pkt in use!\n", __FUNCTION__); ++ return osl_pktget(osh, len); ++} ++ ++void ++osl_pktfree_static(osl_t *osh, void *p, bool send) ++{ ++ int i; ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_4k[i]) { ++ down(&bcm_static_skb->osl_pkt_sem); ++ bcm_static_skb->pkt_use[i] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_8k[i]) { ++ down(&bcm_static_skb->osl_pkt_sem); ++ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ return osl_pktfree(osh, p, send); ++} ++#endif /* DHD_USE_STATIC_BUF */ ++ ++uint32 ++osl_pci_read_config(osl_t *osh, uint offset, uint size) ++{ ++ uint val = 0; ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_read_config_dword(osh->pdev, offset, &val); ++ if (val != 0xffffffff) ++ break; ++ } while (retry--); ++ ++#ifdef BCMDBG ++ if (retry < PCI_CFG_RETRY) ++ printk("PCI CONFIG READ access to %d required %d retries\n", offset, ++ (PCI_CFG_RETRY - retry)); ++#endif /* BCMDBG */ ++ ++ return (val); ++} ++ ++void ++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++{ ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_write_config_dword(osh->pdev, offset, val); ++ if (offset != PCI_BAR0_WIN) ++ break; ++ if (osl_pci_read_config(osh, offset, size) == val) ++ break; ++ } while (retry--); ++ ++#ifdef BCMDBG ++ if (retry < PCI_CFG_RETRY) ++ printk("PCI CONFIG WRITE access to %d required %d retries\n", offset, ++ (PCI_CFG_RETRY - retry)); ++#endif /* BCMDBG */ ++} ++ ++/* return bus # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_bus(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return ((struct pci_dev *)osh->pdev)->bus->number; ++} ++ ++/* return slot # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_slot(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++} ++ ++/* return the pci device pointed by osh->pdev */ ++struct pci_dev * ++osl_pci_device(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return osh->pdev; ++} ++ ++static void ++osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) ++{ ++} ++ ++void ++osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); ++} ++ ++void ++osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); ++} ++ ++void * ++osl_malloc(osl_t *osh, uint size) ++{ ++ void *addr; ++ ++ /* only ASSERT if osh is defined */ ++ if (osh) ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ int i = 0; ++ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) ++ { ++ down(&bcm_static_buf->static_sem); ++ ++ for (i = 0; i < STATIC_BUF_MAX_NUM; i++) ++ { ++ if (bcm_static_buf->buf_use[i] == 0) ++ break; ++ } ++ ++ if (i == STATIC_BUF_MAX_NUM) ++ { ++ up(&bcm_static_buf->static_sem); ++ printk("all static buff in use!\n"); ++ goto original; ++ } ++ ++ bcm_static_buf->buf_use[i] = 1; ++ up(&bcm_static_buf->static_sem); ++ ++ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); ++ } ++ } ++original: ++#endif /* DHD_USE_STATIC_BUF */ ++ ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { ++ if (osh) ++ osh->failed++; ++ return (NULL); ++ } ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return (addr); ++} ++ ++void ++osl_mfree(osl_t *osh, void *addr, uint size) ++{ ++#ifdef DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr ++ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) ++ { ++ int buf_idx = 0; ++ ++ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; ++ ++ down(&bcm_static_buf->static_sem); ++ bcm_static_buf->buf_use[buf_idx] = 0; ++ up(&bcm_static_buf->static_sem); ++ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ return; ++ } ++ } ++#endif /* DHD_USE_STATIC_BUF */ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ kfree(addr); ++} ++ ++uint ++osl_malloced(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (atomic_read(&osh->malloced)); ++} ++ ++uint ++osl_malloc_failed(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->failed); ++} ++ ++ ++uint ++osl_dma_consistent_align(void) ++{ ++ return (PAGE_SIZE); ++} ++ ++void* ++osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) ++{ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ void *va; ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++ va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO); ++ if (va) ++ *pap = (ulong)__virt_to_phys((ulong)va); ++ return va; ++ ++#else ++ void *ret; ++// int gfp = GFP_KERNEL; //GFP_ATOMIC | GFP_DMA; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++// ret = (void *)__get_free_pages(gfp, get_order(size)); ++// if (ret != NULL) { ++// memset(ret, 0, size); ++// *pap = virt_to_phys(ret); ++// } ++ pdev = (struct platform_device *)osh->pdev; ++ ret = dma_alloc_coherent(&pdev->dev, size, (dma_addr_t*)pap, GFP_KERNEL); ++ return ret; ++ ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++void ++osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++{ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ kfree(va); ++#else ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++// free_pages((unsigned long)va, get_order(size)); ++ pdev = (struct platform_device *)osh->pdev; ++ dma_free_coherent(&pdev->dev, size, va, (dma_addr_t)pa); ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++uint BCMFASTPATH ++osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) ++{ ++ int dir; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ pdev = (struct platform_device *)osh->pdev; ++ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; ++ ++#if defined(BCMDMASGLISTOSL) ++ if (dmah != NULL) { ++ int32 nsegs, i, totsegs = 0, totlen = 0; ++ struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2]; ++ struct sk_buff *skb; ++ for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { ++ sg = &_sg[totsegs]; ++ if (skb_is_nonlinear(skb)) { ++ nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); ++ ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS)); ++ #ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ dma_map_sg(&pdev->dev, sg, nsegs, dir); ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } else { ++ nsegs = 1; ++ ASSERT(totsegs + nsegs <= MAX_DMA_SEGS); ++ sg->page_link = 0; ++ sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); ++ #ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ dma_map_single(&pdev->dev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir); ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++ totsegs += nsegs; ++ totlen += PKTLEN(osh, skb); ++ } ++ dmah->nsegs = totsegs; ++ dmah->origsize = totlen; ++ for (i = 0, sg = _sg; i < totsegs; i++, sg++) { ++ dmah->segs[i].addr = sg_phys(sg); ++ dmah->segs[i].length = sg->length; ++ } ++ #ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ return virt_to_phys(va); ++ #else ++ return dmah->segs[0].addr; ++ #endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++ } ++#endif /* defined(BCMDMASGLISTOSL) */ ++ ++#ifdef CONFIG_BCM_IPROC_GMAC_ACP ++ return virt_to_phys(va); ++#else ++ return dma_map_single(&pdev->dev, va, size, dir); ++#endif /* CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++void BCMFASTPATH ++osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) ++{ ++#ifndef CONFIG_BCM_IPROC_GMAC_ACP ++ int dir; ++ /* platform device reference */ ++ struct platform_device *pdev; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ pdev = (struct platform_device *)osh->pdev; ++ dir = (direction == DMA_TX)? DMA_TO_DEVICE: DMA_FROM_DEVICE; ++ dma_unmap_single(&pdev->dev, (uint32)pa, size, dir); ++#endif /* ! CONFIG_BCM_IPROC_GMAC_ACP */ ++} ++ ++ ++void ++osl_delay(uint usec) ++{ ++ uint d; ++ ++ while (usec > 0) { ++ d = MIN(usec, 1000); ++ udelay(d); ++ usec -= d; ++ } ++} ++ ++#if defined(DSLCPE_DELAY) ++ ++void ++osl_oshsh_init(osl_t *osh, shared_osl_t* oshsh) ++{ ++ extern unsigned long loops_per_jiffy; ++ osh->oshsh = oshsh; ++ osh->oshsh->MIPS = loops_per_jiffy / (500000/HZ); ++} ++ ++int ++in_long_delay(osl_t *osh) ++{ ++ return osh->oshsh->long_delay; ++} ++ ++void ++osl_long_delay(osl_t *osh, uint usec, bool yield) ++{ ++ uint d; ++ bool yielded = TRUE; ++ int usec_to_delay = usec; ++ unsigned long tick1, tick2, tick_diff = 0; ++ ++ /* delay at least requested usec */ ++ while (usec_to_delay > 0) { ++ if (!yield || !yielded) { ++ d = MIN(usec_to_delay, 10); ++ udelay(d); ++ usec_to_delay -= d; ++ } ++ if (usec_to_delay > 0) { ++ osh->oshsh->long_delay++; ++ OSL_GETCYCLES(tick1); ++ spin_unlock_bh(osh->oshsh->lock); ++ if (usec_to_delay > 0 && !in_irq() && !in_softirq() && !in_interrupt()) { ++ schedule(); ++ yielded = TRUE; ++ } else { ++ yielded = FALSE; ++ } ++ spin_lock_bh(osh->oshsh->lock); ++ OSL_GETCYCLES(tick2); ++ ++ if (yielded) { ++ tick_diff = TICKDIFF(tick2, tick1); ++ tick_diff = (tick_diff * 2)/(osh->oshsh->MIPS); ++ if (tick_diff) { ++ usec_to_delay -= tick_diff; ++ } else ++ yielded = 0; ++ } ++ osh->oshsh->long_delay--; ++ ASSERT(osh->oshsh->long_delay >= 0); ++ } ++ } ++} ++#endif /* DSLCPE_DELAY */ ++ ++/* Clone a packet. ++ * The pkttag contents are NOT cloned. ++ */ ++void * ++osl_pktdup(osl_t *osh, void *skb) ++{ ++ void * p; ++ ++ /* clear the CTFBUF flag if set and map the rest of the buffer ++ * before cloning. ++ */ ++ PKTCTFMAP(osh, skb); ++ ++ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) ++ return NULL; ++ ++#ifdef CTFPOOL ++ if (PKTISFAST(osh, skb)) { ++ ctfpool_t *ctfpool; ++ ++ /* if the buffer allocated from ctfpool is cloned then ++ * we can't be sure when it will be freed. since there ++ * is a chance that we will be losing a buffer ++ * from our pool, we increment the refill count for the ++ * object to be alloced later. ++ */ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ PKTCLRFAST(osh, p); ++ PKTCLRFAST(osh, skb); ++ ctfpool->refills++; ++ } ++#endif /* CTFPOOL */ ++ ++ /* skb_clone copies skb->cb.. we don't want that */ ++ if (osh->pub.pkttag) ++ OSL_PKTTAG_CLEAR(p); ++ ++ /* Increment the packet counter */ ++ atomic_inc(&osh->pktalloced); ++ return (p); ++} ++ ++ ++/* ++ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access ++ */ ++#ifdef OSLREGOPS ++uint8 ++osl_readb(osl_t *osh, volatile uint8 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint8)((rreg)(ctx, (void*)r, sizeof(uint8))); ++} ++ ++ ++uint16 ++osl_readw(osl_t *osh, volatile uint16 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint16)((rreg)(ctx, (void*)r, sizeof(uint16))); ++} ++ ++uint32 ++osl_readl(osl_t *osh, volatile uint32 *r) ++{ ++ osl_rreg_fn_t rreg = ((osl_pubinfo_t*)osh)->rreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ return (uint32)((rreg)(ctx, (void*)r, sizeof(uint32))); ++} ++ ++void ++osl_writeb(osl_t *osh, volatile uint8 *r, uint8 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint8))); ++} ++ ++ ++void ++osl_writew(osl_t *osh, volatile uint16 *r, uint16 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint16))); ++} ++ ++void ++osl_writel(osl_t *osh, volatile uint32 *r, uint32 v) ++{ ++ osl_wreg_fn_t wreg = ((osl_pubinfo_t*)osh)->wreg_fn; ++ void *ctx = ((osl_pubinfo_t*)osh)->reg_ctx; ++ ++ ((wreg)(ctx, (void*)r, v, sizeof(uint32))); ++} ++#endif /* OSLREGOPS */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ */ ++#ifdef BINOSL ++ ++uint32 ++osl_sysuptime(void) ++{ ++ return ((uint32)jiffies * (1000 / HZ)); ++} ++ ++int ++osl_printf(const char *format, ...) ++{ ++ va_list args; ++ static char printbuf[1024]; ++ int len; ++ ++ /* sprintf into a local buffer because there *is* no "vprintk()".. */ ++ va_start(args, format); ++ len = vsnprintf(printbuf, 1024, format, args); ++ va_end(args); ++ ++ if (len > sizeof(printbuf)) { ++ printk("osl_printf: buffer overrun\n"); ++ return (0); ++ } ++ ++ return (printk("%s", printbuf)); ++} ++ ++int ++osl_sprintf(char *buf, const char *format, ...) ++{ ++ va_list args; ++ int rc; ++ ++ va_start(args, format); ++ rc = vsprintf(buf, format, args); ++ va_end(args); ++ return (rc); ++} ++ ++int ++osl_snprintf(char *buf, size_t n, const char *format, ...) ++{ ++ va_list args; ++ int rc; ++ ++ va_start(args, format); ++ rc = vsnprintf(buf, n, format, args); ++ va_end(args); ++ return (rc); ++} ++ ++int ++osl_vsprintf(char *buf, const char *format, va_list ap) ++{ ++ return (vsprintf(buf, format, ap)); ++} ++ ++int ++osl_vsnprintf(char *buf, size_t n, const char *format, va_list ap) ++{ ++ return (vsnprintf(buf, n, format, ap)); ++} ++ ++int ++osl_strcmp(const char *s1, const char *s2) ++{ ++ return (strcmp(s1, s2)); ++} ++ ++int ++osl_strncmp(const char *s1, const char *s2, uint n) ++{ ++ return (strncmp(s1, s2, n)); ++} ++ ++int ++osl_strlen(const char *s) ++{ ++ return (strlen(s)); ++} ++ ++char* ++osl_strcpy(char *d, const char *s) ++{ ++ return (strcpy(d, s)); ++} ++ ++char* ++osl_strncpy(char *d, const char *s, uint n) ++{ ++ return (strncpy(d, s, n)); ++} ++ ++char* ++osl_strchr(const char *s, int c) ++{ ++ return (strchr(s, c)); ++} ++ ++char* ++osl_strrchr(const char *s, int c) ++{ ++ return (strrchr(s, c)); ++} ++ ++void* ++osl_memset(void *d, int c, size_t n) ++{ ++ return memset(d, c, n); ++} ++ ++void* ++osl_memcpy(void *d, const void *s, size_t n) ++{ ++ return memcpy(d, s, n); ++} ++ ++void* ++osl_memmove(void *d, const void *s, size_t n) ++{ ++ return memmove(d, s, n); ++} ++ ++int ++osl_memcmp(const void *s1, const void *s2, size_t n) ++{ ++ return memcmp(s1, s2, n); ++} ++ ++uint32 ++osl_readl(volatile uint32 *r) ++{ ++ return (readl(r)); ++} ++ ++uint16 ++osl_readw(volatile uint16 *r) ++{ ++ return (readw(r)); ++} ++ ++uint8 ++osl_readb(volatile uint8 *r) ++{ ++ return (readb(r)); ++} ++ ++void ++osl_writel(uint32 v, volatile uint32 *r) ++{ ++ writel(v, r); ++} ++ ++void ++osl_writew(uint16 v, volatile uint16 *r) ++{ ++ writew(v, r); ++} ++ ++void ++osl_writeb(uint8 v, volatile uint8 *r) ++{ ++ writeb(v, r); ++} ++ ++void * ++osl_uncached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG1ADDR(va)); ++#else ++ return ((void*)va); ++#endif /* mips */ ++} ++ ++void * ++osl_cached(void *va) ++{ ++#ifdef mips ++ return ((void*)KSEG0ADDR(va)); ++#else ++ return ((void*)va); ++#endif /* mips */ ++} ++ ++uint ++osl_getcycles(void) ++{ ++ uint cycles; ++ ++#if defined(mips) ++ cycles = read_c0_count() * 2; ++#elif defined(__i386__) ++ rdtscl(cycles); ++#else ++ cycles = 0; ++#endif /* defined(mips) */ ++ return cycles; ++} ++ ++void * ++osl_reg_map(uint32 pa, uint size) ++{ ++ return (ioremap_nocache((unsigned long)pa, (unsigned long)size)); ++} ++ ++void ++osl_reg_unmap(void *va) ++{ ++ iounmap(va); ++} ++ ++int ++osl_busprobe(uint32 *val, uint32 addr) ++{ ++#ifdef mips ++ return get_dbe(*val, (uint32 *)addr); ++#else ++ *val = readl((uint32 *)(uintptr)addr); ++ return 0; ++#endif /* mips */ ++} ++ ++bool ++osl_pktshared(void *skb) ++{ ++ return (((struct sk_buff*)skb)->cloned); ++} ++ ++uchar* ++osl_pktdata(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->data); ++} ++ ++uint ++osl_pktlen(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->len); ++} ++ ++uint ++osl_pktheadroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_headroom((struct sk_buff *) skb); ++} ++ ++uint ++osl_pkttailroom(osl_t *osh, void *skb) ++{ ++ return (uint) skb_tailroom((struct sk_buff *) skb); ++} ++ ++void* ++osl_pktnext(osl_t *osh, void *skb) ++{ ++ return (((struct sk_buff*)skb)->next); ++} ++ ++void ++osl_pktsetnext(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->next = (struct sk_buff*)x; ++} ++ ++void ++osl_pktsetlen(osl_t *osh, void *skb, uint len) ++{ ++ __pskb_trim((struct sk_buff*)skb, len); ++} ++ ++uchar* ++osl_pktpush(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_push((struct sk_buff*)skb, bytes)); ++} ++ ++uchar* ++osl_pktpull(osl_t *osh, void *skb, int bytes) ++{ ++ return (skb_pull((struct sk_buff*)skb, bytes)); ++} ++ ++void* ++osl_pkttag(void *skb) ++{ ++ return ((void*)(((struct sk_buff*)skb)->cb)); ++} ++ ++void* ++osl_pktlink(void *skb) ++{ ++ return (((struct sk_buff*)skb)->prev); ++} ++ ++void ++osl_pktsetlink(void *skb, void *x) ++{ ++ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x; ++} ++ ++uint ++osl_pktprio(void *skb) ++{ ++ return (((struct sk_buff*)skb)->priority); ++} ++ ++void ++osl_pktsetprio(void *skb, uint x) ++{ ++ ((struct sk_buff*)skb)->priority = x; ++} ++#endif /* BINOSL */ ++ ++uint ++osl_pktalloced(osl_t *osh) ++{ ++ return (atomic_read(&osh->pktalloced)); ++} ++ ++/* Linux Kernel: File Operations: start */ ++void * ++osl_os_open_image(char *filename) ++{ ++ struct file *fp; ++ ++ fp = filp_open(filename, O_RDONLY, 0); ++ /* ++ * 2.6.11 (FC4) supports filp_open() but later revs don't? ++ * Alternative: ++ * fp = open_namei(AT_FDCWD, filename, O_RD, 0); ++ * ??? ++ */ ++ if (IS_ERR(fp)) ++ fp = NULL; ++ ++ return fp; ++} ++ ++int ++osl_os_get_image_block(char *buf, int len, void *image) ++{ ++ struct file *fp = (struct file *)image; ++ int rdlen; ++ ++ if (!image) ++ return 0; ++ ++ rdlen = kernel_read(fp, fp->f_pos, buf, len); ++ if (rdlen > 0) ++ fp->f_pos += rdlen; ++ ++ return rdlen; ++} ++ ++void ++osl_os_close_image(void *image) ++{ ++ if (image) ++ filp_close((struct file *)image, NULL); ++} ++/* Linux Kernel: File Operations: end */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c +new file mode 100755 +index 0000000..9ad67a0 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.c +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Northstar+ sudo EROM ++ * ++ */ ++#include ++ ++uint32 nsp_erom[] = { ++ //#define CC_CORE_ID 0x800 /* chipcommon core */ ++ 0x4bf80001, 0x2a004201, 0x18000005, 0x181200c5, ++ //#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ ++ 0x4bf50b01, 0x01000201, 0x18001005, 0x18002005, 0x18003005, 0x18004005, 0x18005005, 0x18006005, 0x18007005, 0x18008005, 0x18009005, ++ //#define NS_DMA_CORE_ID 0x502 /* DMA core */ ++ 0x4bf50201, 0x01004211, 0x00000003, 0x1802c005, 0x181140c5, ++ //#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++ 0x4bf82d01, 0x04004211, 0x00000103, 0x18022005, 0x181100c5, ++ 0x4bf82d01, 0x04004211, 0x00000203, 0x18023005, 0x181110c5, ++ 0x4bf82d01, 0x04004211, 0x00000303, 0x18024005, 0x181120c5, ++ 0x4bf82d01, 0x04004211, 0x00000403, 0x18025005, 0x181130c5, ++ //#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ ++ 0x4bf50101, 0x01084411, 0x00000503, 0x18012005, 0x08000135, 0x08000000, 0x181010c5, 0x1810a185, ++ 0x4bf50101, 0x01084411, 0x00000603, 0x18013005, 0x40000135, 0x08000000, 0x181020c5, 0x1810b185, ++ 0x4bf50101, 0x01084411, 0x00000703, 0x18014005, 0x48000135, 0x08000000, 0x181030c5, 0x1810c185, ++ //#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ ++ 0x4bf51001, 0x01104611, 0x00000803, 0x1800b005, 0x1800c005, 0x19000135, 0x00020000, 0x19020235, 0x00003000, 0x181000c5, 0x18106185, 0x18107285, ++ //#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ ++ 0x4bf50401, 0x01004211, 0x00000903, 0x18021005, 0x18022005, 0x181150c5, ++ //#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ ++ 0x4bf50501, 0x01004211, 0x00000a03, 0x18023005, 0x181050c5, ++ //#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ ++ 0x4bf50301, 0x01004211, 0x00000b03, 0x18020005, 0x181160c5, ++ //#define I2S_CORE_ID 0x834 /* I2S core */ ++ 0x4bf83401, 0x03004211, 0x00000c03, 0x1802a005, 0x181170c5, ++ //#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ ++ 0x4bf50601, 0x01084211, 0x00000d03, 0x18210035, 0x00010000, 0x181180c5, 0x1811c085, ++ //#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ ++ 0x4bf50701, 0x01100601, 0x18010005, 0x00000135, 0x08000000, 0x80000135, 0x30000000, 0xb0000235, 0x10000000, 0x18108185, 0x18109285, ++ //#define NS_ROM_CORE_ID 0x508 /* ROM core */ ++ 0x4bf50801, 0x01080201, 0xfffd0035, 0x00030000, 0x1810d085, ++ //#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ ++ 0x4bf50901, 0x01080401, 0x18028005, 0x1c000135, 0x02000000, 0x1811a185, ++ //#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ ++ 0x4bf50a01, 0x01080401, 0x18029005, 0x1e000135, 0x02000000, 0x1811b185, ++ //#define EROM_CORE_ID 0x366 /* EROM core ID */ ++ 0x43b36601, 0x00000201, 0x18130005, ++ 0x43b13501, 0x00080201, 0x18000075, 0x00010000, 0x18121085, ++ 0x43b30101, 0x01000201, 0x1a000035, 0x00100000, ++ 0x43bfff01, 0x00280a01, 0x10000035, 0x08000000, 0x18011005, 0x18015035, 0x0000b000, 0x1802b105, 0x1802d135, 0x000d3000, 0x18104105, 0x1810e215, ++ 0x18119205, 0x1811d235, 0x00003000, 0x18122335, 0x0000e000, 0x18131305, 0x18137335, 0x000d9000, 0x18220335, 0x000de000, 0x19023335, ++ 0x00fdd000, 0x1a100335, 0x01f00000, 0x20000435, 0x20000000, 0x50000435, 0x30000000, 0xc0000435, 0x3ffd0000, 0x18132085, 0x18133185, ++ 0x18134285, 0x18135385, 0x18136485, ++ 0x0000000f ++}; +diff --git a/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h +new file mode 100755 +index 0000000..98cf29e +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nsp_erom.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Broadcom Home Networking Division 10/100 Mbit/s Ethernet ++ * Helix4 sudo EROM ++ * ++ */ ++ ++#ifndef _nsp_erom_h_ ++#define _snp_erom_h_ ++ ++extern uint32 nsp_erom[]; ++ ++#endif //_nsp_erom_h_ +diff --git a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c +new file mode 100755 +index 0000000..d5b400d +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c +@@ -0,0 +1,365 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Stubs for NVRAM functions for platforms without flash ++ * ++ * $Id: nvramstubs.c 325991 2012-04-05 10:16:42Z $ ++ */ ++ ++#include ++#include ++#include ++#undef strcmp ++#define strcmp(s1,s2) 0 /* always match */ ++#include ++#include ++#include ++ ++int brcm_get_hx4_model(void); ++ ++int ++nvram_init(void *sih) ++{ ++ return 0; ++} ++ ++int ++nvram_append(void *sb, char *vars, uint varsz) ++{ ++ return 0; ++} ++ ++void ++nvram_exit(void *sih) ++{ ++} ++ ++/* fake nvram tuples */ ++typedef struct { ++ char *name; ++ char *value; ++} nvram_t; ++ ++static nvram_t fake_nvram[] = { ++ {"boardtype", "0x058d"}, ++ {"boardnum", "0x010"}, ++ {"boardrev", "0x1100"}, ++ {"boardflags", "0x710"}, ++ {"boardflags2", "0"}, ++ {"sromrev", "8"}, ++ {"clkfreq", "133,133,133"}, ++ {"xtalfreq", "125000"}, ++ {"et_txq_thresh", "1024"}, ++ {"et_rx_rate_limit","1"}, ++ {"sdram_config", "0x103"}, ++ {"swgmacet", "et2"}, ++ {"brcmtag", "1"}, ++ //{"ethaddr", "00:90:4c:06:a5:72"}, ++#ifdef FOUR_PORT_CONFIG ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 8*"}, ++ {"vlan2hwname", "et2"}, ++ {"vlan2ports", "3 8*"}, ++ {"wanport", "3"}, ++#else ++#if (defined(CONFIG_ROOT_NFS) && defined(CONFIG_MACH_NSP)) ++ ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 3 8u"}, ++ {"wanport", "4"}, ++#else ++ {"vlan1hwname", "et2"}, ++ {"vlan1ports", "0 1 2 3 8*"}, ++ {"vlan2hwname", "et2"}, ++ {"vlan2ports", "4 8*"}, ++ {"wanport", "4"}, ++#endif //(defined(CONFIG_ROOT_NFS) && defined(CONFIG_MACH_NSP)) ++#endif ++ {"landevs", "vlan1"}, ++ {"wandevs", "et0"}, ++ {"lan_ipaddr", "192.168.1.1"}, ++ {"lan_netmask", "255.255.255.0"}, ++ {"boot_wait", "on"}, ++ {"wait_time", "3"}, ++ {"watchdog", "0"}, ++ {"et_msglevel", "0xFFFFFFFF"} ++}; ++ ++#define fake_nvram_size sizeof(fake_nvram)/sizeof(fake_nvram[0]) ++ ++#ifndef FAKE_NVRAM ++ ++#define CONFIG_SPI_BASE 0x1e000000 ++#define CONFIG_NAND_BASE 0x1c000000 ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++#define CONFIG_ENV_OFFSET 0xa0000 /* 30000-b0000 - use last 10000 for env */ ++#else ++#define CONFIG_ENV_OFFSET 0xc0000 /* 30000-b0000 - use last 10000 for env */ ++#endif ++#define CONFIG_ENV_SIZE 0x20000 /* 128K */ ++#define CONFIG_ENV_MAX_ENTRIES 512 ++ ++#define UBOOT_ENV_ADDR CONFIG_SPI_BASE+CONFIG_ENV_OFFSET ++#define UBOOT_ENV_SIZE CONFIG_ENV_SIZE ++#define UBOOT_ENV_MAX_NUM CONFIG_ENV_MAX_ENTRIES ++ ++static uint8 u_boot_env[UBOOT_ENV_SIZE]; ++static bool u_boot_env_loaded=false; ++static nvram_t env_list[UBOOT_ENV_MAX_NUM]; ++static int uboot_vars_start = UBOOT_ENV_ADDR; ++static int uboot_nvram_max = UBOOT_ENV_SIZE; ++ ++/* pass envaddr= in bootargs */ ++static int __init envaddr_setup(char *str) ++{ ++ int ret =0; ++ unsigned long ul=0; ++ ++ //printk("NVRAM: %s\n", str); ++ ++ ret = strict_strtoul(str, 16, &ul); ++ ++ if (!ret) { ++ uboot_vars_start = ul; ++ printk("NVRAM: assign 0x%08x\n", uboot_vars_start); ++ } ++ ++ return !ret; ++} ++__setup("envaddr=", envaddr_setup); ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++static void ++setup_uboot_vars(void) { ++ int modelnum; ++ int env_offset; ++ ++ modelnum = brcm_get_hx4_model(); ++ if (modelnum == HX4_DNI_3448P) { ++ env_offset = 0x00100000; ++ uboot_vars_start = CONFIG_NAND_BASE + env_offset; ++ } else if (modelnum == HX4_ACCTON_AS4610_54) { ++ env_offset = 0x000f0000; ++ uboot_vars_start = CONFIG_SPI_BASE + env_offset; ++ } ++} ++ ++/* ++APIs for access into uboot env vars ++*/ ++ ++int ++nvram_env_init(void) ++{ ++ volatile void *envbuf; ++ char *dp, *sp, *name, *value, *dp_end; ++ char sep = '\0'; ++ int idx=0; ++ ++ setup_uboot_vars(); ++ ++ printk("NVRAM: map 0x%08x\n", uboot_vars_start); ++ ++ /* map uboot env */ ++ if ((envbuf = (uint8*)ioremap(uboot_vars_start, UBOOT_ENV_SIZE)) == NULL) { ++ printk("%s: ioremap() failed\n", __FUNCTION__); ++ return -ENOMEM; ++ } ++ ++ /* copy memory into buffer */ ++ memcpy((void*)u_boot_env, (void *) envbuf, uboot_nvram_max); ++ ++ /* clear fake entry set */ ++ memset(env_list, 0, sizeof(env_list)); ++ ++ /* load uboot fake nvram buffer */ ++ /* point to first data */ ++ dp = (char*)u_boot_env; ++ /* point to data buffer */ ++ dp += 4; ++ dp_end = (char*)((uint32)u_boot_env+UBOOT_ENV_SIZE); ++ ++ /* point to first data */ ++ do { ++ ++ /* skip leading white space */ ++ while ((*dp == ' ') || (*dp == '\t')) ++ ++dp; ++ ++ /* skip comment lines */ ++ if (*dp == '#') { ++ while (*dp && (*dp != sep)) ++ ++dp; ++ ++dp; ++ continue; ++ } ++ ++ /* parse name */ ++ for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp) ++ ; ++ ++ *dp++ = '\0'; /* terminate name */ ++ ++ /* parse value; deal with escapes */ ++ for (value = sp = dp; *dp && (*dp != sep); ++dp) { ++ if ((*dp == '\\') && *(dp + 1)) ++ ++dp; ++ *sp++ = *dp; ++ } ++ *sp++ = '\0'; /* terminate value */ ++ ++dp; ++ ++ /* enter into hash table */ ++ env_list[idx].name = name; ++ env_list[idx].value = value; ++ //printk("entry%d %s=%s\n", idx, name, value); ++ idx++; ++ ++ /* check if table is full */ ++ if (idx >= UBOOT_ENV_MAX_NUM ) { ++ printk("%s: WARNING - UBoot environment table is full\n", __FUNCTION__); ++ break; ++ } ++ ++ /* check if end of table */ ++ } while ((dp < dp_end) && *dp); /* size check needed for text */ ++ ++ u_boot_env_loaded = true; ++ ++ /* unmap uboot env */ ++ iounmap(envbuf); ++ ++ return 0; ++} ++#endif ++ ++int ++nvram_env_gmac_name(int gmac, char *name) ++{ ++ int ret=0; ++ switch (gmac) ++ { ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ case 0: ++ case 1: ++ sprintf(name, "eth%daddr", gmac+1); ++ break; ++ case 2: ++ strcpy(name, "ethaddr"); ++ break; ++ case 3: ++ sprintf(name, "eth%daddr", gmac); ++ break; ++#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ case 0: ++ strcpy(name, "ethaddr"); ++ break; ++ case 1: ++ sprintf(name, "eth1addr"); ++ break; ++#elif defined(CONFIG_MACH_HR2) ++ case 0: ++ strcpy(name, "ethaddr"); ++ break; ++#endif ++ default: ++ strcpy(name, "unknown"); ++ ret = -1; ++ break; ++ } ++ return ret; ++ ++} ++ ++char * ++nvram_get(const char *name) ++{ ++ int i, len; ++ nvram_t *tuple; ++ int num_entries; ++ ++ if (!name) ++ return (char *) 0; ++ ++ len = strlen(name); ++ if (len == 0) ++ return (char *) 0; ++ ++#ifndef FAKE_NVRAM ++ tuple = &env_list[0]; ++ num_entries = sizeof(env_list)/sizeof(nvram_t); ++ ++ if (!u_boot_env_loaded) ++ nvram_env_init(); ++ ++ /* first check the uboot NVRAM variables */ ++ for (i = 0; i < num_entries; i++) { ++ ++ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { ++ /*printf("%s (NVRAM) %s: %s\n", __FUNCTION__, name, tuple->value);*/ ++ return tuple->value; ++ } ++ tuple++; ++ } ++#endif ++ ++ /* if cant find then check fake table above */ ++ tuple = &fake_nvram[0]; ++ num_entries = fake_nvram_size; ++ for (i = 0; i < num_entries; i++) { ++ ++ if (tuple->name && (bcmp(tuple->name, name, len) == 0) && (strlen(tuple->name)==len)) { ++ /*printf("%s (STUBS) %s: %s\n", __FUNCTION__, name, tuple->value);*/ ++ return tuple->value; ++ } ++ tuple++; ++ } ++ ++ return (char *) 0; ++} ++ ++int ++nvram_set(const char *name, const char *value) ++{ ++ return 0; ++} ++ ++int ++nvram_unset(const char *name) ++{ ++ return 0; ++} ++ ++int ++nvram_commit(void) ++{ ++ return 0; ++} ++ ++int ++nvram_getall(char *buf, int count) ++{ ++ /* add null string as terminator */ ++ if (count < 1) ++ return BCME_BUFTOOSHORT; ++ *buf = '\0'; ++ return 0; ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/siutils.c b/drivers/bcmdrivers/gmac/src/shared/siutils.c +new file mode 100755 +index 0000000..23f84ac +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/siutils.c +@@ -0,0 +1,1536 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * $Id: siutils.c 328955 2012-04-23 09:06:12Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) ++#include ++#endif /* !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) */ ++ ++#include "siutils_priv.h" ++ ++/* local prototypes */ ++static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz); ++static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); ++static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs); ++ ++static void si_nvram_process(si_info_t *sii, char *pvars); ++/* dev path concatenation util */ ++static char *si_devpathvar(si_t *sih, char *var, int len, const char *name); ++static bool _si_clkctl_cc(si_info_t *sii, uint mode); ++ ++ ++/* global variable to indicate reservation/release of gpio's */ ++static uint32 si_gpioreservation = 0; ++ ++/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ ++ ++EXPORT_SYMBOL(si_attach); ++EXPORT_SYMBOL(si_setcore); ++ ++/* ++ * Allocate a si handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ * bustype - pci/pcmcia/sb/sdio/etc ++ * vars - pointer to a pointer area for "environment" variables ++ * varsz - pointer to int to return the size of the vars ++ */ ++si_t * ++BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ si_info_t *sii; ++ si_t *sih; ++ ++ /* alloc si_info_t */ ++ if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { ++ SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); ++ return (NULL); ++ } ++ ++ if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { ++ MFREE(osh, sii, sizeof(si_info_t)); ++ SI_ERROR(("%s si_doattach() failed\n", __FUNCTION__)); ++ return (NULL); ++ } ++ sii->vars = vars ? *vars : NULL; ++ sii->varsz = varsz ? *varsz : 0; ++ ++ sih = (si_t*)sii; ++ printk("%s socitype(0x%x) chip(0x%x) chiprev(0x%x) chippkg(0x%x)\n", ++ __FUNCTION__, sih->socitype, sih->chip, sih->chiprev, sih->chippkg); ++ ++ return (si_t *)sii; ++} ++ ++/* global kernel resource */ ++static si_info_t ksii; ++ ++static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ ++ ++/* generic kernel variant of si_attach() */ ++si_t * ++BCMATTACHFN(si_kattach)(osl_t *osh) ++{ ++ static bool ksii_attached = FALSE; ++ ++ if (!ksii_attached) { ++ void *regs; ++#ifndef SI_ENUM_BASE_VARIABLE ++ regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++#endif ++ ++ if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, ++ SI_BUS, NULL, ++ osh != SI_OSH ? &ksii.vars : NULL, ++ osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { ++ SI_ERROR(("si_kattach: si_doattach failed\n")); ++ REG_UNMAP(regs); ++ return NULL; ++ } ++ REG_UNMAP(regs); ++ ++ /* save ticks normalized to ms for si_watchdog_ms() */ ++ if (PMUCTL_ENAB(&ksii.pub)) { ++ /* based on 32KHz ILP clock */ ++ wd_msticks = 32; ++ } else { ++ if (ksii.pub.ccrev < 18) ++ wd_msticks = si_clock(&ksii.pub) / 1000; ++ else ++ wd_msticks = si_alp_clock(&ksii.pub) / 1000; ++ } ++ ++ ksii_attached = TRUE; ++ SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", ++ ksii.pub.ccrev, wd_msticks)); ++ } ++ ++ return &ksii.pub; ++} ++ ++static bool ++BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh) ++{ ++ return TRUE; ++} ++ ++static bool ++BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs) ++{ ++ bool pci, pcie; ++ uint i; ++ uint pciidx, pcieidx, pcirev, pcierev; ++ ++ cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ++ ASSERT((uintptr)cc); ++ ++ /* get chipcommon rev */ ++ sii->pub.ccrev = (int)si_corerev(&sii->pub); ++ ++ /* get chipcommon chipstatus */ ++ if (sii->pub.ccrev >= 11) ++ sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); ++ ++ /* get chipcommon capabilites */ ++ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); ++ /* get chipcommon extended capabilities */ ++ ++ if (sii->pub.ccrev >= 35) ++ sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); ++ ++ /* get pmu rev and caps */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); ++ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; ++ } ++ ++ SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", ++ sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, ++ sii->pub.pmucaps)); ++ ++ /* figure out bus/orignal core idx */ ++ sii->pub.buscoretype = NODEV_CORE_ID; ++ sii->pub.buscorerev = (uint)NOREV; ++ sii->pub.buscoreidx = BADIDX; ++ ++ pci = pcie = FALSE; ++ pcirev = pcierev = (uint)NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ uint cid, crev; ++ ++ si_setcoreidx(&sii->pub, i); ++ cid = si_coreid(&sii->pub); ++ crev = si_corerev(&sii->pub); ++ ++ /* Display cores found */ ++ SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", ++ i, cid, crev, sii->coresba[i], sii->regs[i])); ++ ++ /* find the core idx before entering this func. */ ++ if ((savewin && (savewin == sii->coresba[i])) || ++ (regs == sii->regs[i])) ++ *origidx = i; ++ } ++ ++ SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, ++ sii->pub.buscorerev)); ++ ++ /* return to the original core */ ++ si_setcoreidx(&sii->pub, *origidx); ++ ++ return TRUE; ++} ++ ++static void ++BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars) ++{ ++ /* get boardtype and boardrev */ ++ switch (BUSTYPE(sii->pub.bustype)) { ++ case SI_BUS: ++ sii->pub.boardvendor = VENDOR_BROADCOM; ++ if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0)) ++ if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0) ++ sii->pub.boardtype = 0xffff; ++ break; ++ } ++ ++ if (sii->pub.boardtype == 0) { ++ SI_ERROR(("si_doattach: unknown board type\n")); ++ ASSERT(sii->pub.boardtype); ++ } ++ ++ sii->pub.boardrev = getintvar(pvars, "boardrev"); ++ sii->pub.boardflags = getintvar(pvars, "boardflags"); ++} ++ ++ ++static si_info_t * ++BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ struct si_pub *sih = &sii->pub; ++ uint32 w, savewin; ++ chipcregs_t *cc; ++ char *pvars = NULL; ++ uint origidx; ++ ASSERT(GOODREGS(regs)); ++ ++ bzero((uchar*)sii, sizeof(si_info_t)); ++ ++ savewin = 0; ++ ++ sih->buscoreidx = BADIDX; ++ ++ sii->curmap = regs; ++ sii->sdh = sdh; ++ sii->osh = osh; ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++ si_enum_base_init(sih, bustype); ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++ /* check to see if we are a si core mimic'ing a pci core */ ++ if ((bustype == PCI_BUS)) { ++ SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI " ++ "devid:0x%x\n", __FUNCTION__, devid)); ++ bustype = SI_BUS; ++ } ++ ++ /* find Chipcommon address */ ++ cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++ ++ sih->bustype = bustype; ++ if (bustype != BUSTYPE(bustype)) { ++ SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", ++ bustype, BUSTYPE(bustype))); ++ return NULL; ++ } ++ ++ /* bus/core/clk setup for register access */ ++ if (!si_buscore_prep(sii, bustype, devid, sdh)) { ++ SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); ++ return NULL; ++ } ++ ++ /* ChipID recognition. ++ * We assume we can read chipid at offset 0 from the regs arg. ++ * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), ++ * some way of recognizing them needs to be added here. ++ */ ++ if (!cc) { ++ SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__)); ++ return NULL; ++ } ++ w = R_REG(osh, &cc->chipid); ++ printk("%s chipid: 0x%x\n", __FUNCTION__, w); ++ sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; ++ /* Might as wll fill in chip id rev & pkg */ ++ sih->chip = w & CID_ID_MASK; ++ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; ++ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ /* printk("%s chip: 0x%x; chiprev: 0x%x; chippkg: 0x%x\n", __FUNCTION__, sih->chip, sih->chiprev, sih->chippkg); */ ++ ++ sih->issim = IS_SIM(sih->chippkg); ++ ++ /* scan for cores */ ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { ++ SI_MSG(("Found chip type SB (0x%08x)\n", w)); ++ sb_scan(&sii->pub, regs, devid); ++ } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || (CHIPTYPE(sii->pub.socitype) == SOCI_NS)) { ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) ++ SI_MSG(("Found chip type AI (0x%08x)\n", w)); ++ else ++ SI_MSG(("Found chip type NS (0x%08x)\n", w)); ++ /* pass chipc address instead of original core base */ ++ ai_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { ++ SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip)); ++ /* pass chipc address instead of original core base */ ++ ub_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else { ++ SI_ERROR(("Found chip of unknown type (0x%08x)\n", w)); ++ return NULL; ++ } ++ /* no cores found, bail out */ ++ if (sii->numcores == 0) { ++ SI_ERROR(("si_doattach: could not find any cores\n")); ++ return NULL; ++ } ++ /* bus/core/clk setup */ ++ origidx = SI_CC_IDX; ++ if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { ++ SI_ERROR(("si_doattach: si_buscore_setup failed\n")); ++ goto exit; ++ } ++ ++#ifdef SI_SPROM_PROBE ++ si_sprom_init(sih); ++#endif /* SI_SPROM_PROBE */ ++ ++#if !defined(BCMHIGHSDIO) ++ /* Init nvram from flash if it exists */ ++ nvram_init((void *)&(sii->pub)); ++ ++ pvars = vars ? *vars : NULL; ++ ++ si_nvram_process(sii, pvars); ++ ++ /* === NVRAM, clock is ready === */ ++#else ++ pvars = NULL; ++ BCM_REFERENCE(pvars); ++#endif ++ ++ ++ /* bootloader should retain default pulls */ ++#ifndef BCM_BOOTLOADER ++ if (sii->pub.ccrev >= 20) { ++ uint32 gpiopullup = 0, gpiopulldown = 0; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ /* 4314/43142 has pin muxing, don't clear gpio bits */ ++ if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { ++ gpiopullup |= 0x402e0; ++ gpiopulldown |= 0x20500; ++ } ++ ++ W_REG(osh, &cc->gpiopullup, gpiopullup); ++ W_REG(osh, &cc->gpiopulldown, gpiopulldown); ++ si_setcoreidx(sih, origidx); ++ } ++#endif /* !BCM_BOOTLOADER */ ++ ++ ++ /* setup the GPIO based LED powersave register */ ++ if (sii->pub.ccrev >= 16) { ++ if ((w = getintvar(pvars, "leddc")) == 0) ++ w = DEFAULT_GPIOTIMERVAL; ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w); ++ } ++ ++ if (PCI_FORCEHT(sii)) { ++ SI_MSG(("si_doattach: force HT\n")); ++ sih->pci_pr32414 = TRUE; ++ si_clkctl_init(sih); ++ _si_clkctl_cc(sii, CLK_FAST); ++ } ++ ++#if !defined(_CFE_) || defined(CFG_WL) ++ /* enable GPIO interrupts when clocks are off */ ++ if (sii->pub.ccrev >= 21) { ++ uint32 corecontrol; ++ corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), ++ 0, 0); ++ corecontrol |= CC_ASYNCGPIO; ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol), ++ corecontrol, corecontrol); ++ } ++ ++#endif /* !_CFE_ || CFG_WL */ ++ ++#if defined(SAVERESTORE) ++ sr_save_restore_init(sih); ++#endif ++ ++ ++ return (sii); ++ ++exit: ++ ++ return NULL; ++} ++ ++/* may be called with core in reset */ ++void ++BCMATTACHFN(si_detach)(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ ++#if defined(STA) ++ struct si_pub *si_local = NULL; ++ bcopy(&sih, &si_local, sizeof(si_t*)); ++#endif ++ ++ sii = SI_INFO(sih); ++ ++ if (sii == NULL) ++ return; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) ++ for (idx = 0; idx < SI_MAXCORES; idx++) ++ if (sii->regs[idx]) { ++ REG_UNMAP(sii->regs[idx]); ++ sii->regs[idx] = NULL; ++ } ++ ++#if defined(STA) ++#if !defined(BCMHIGHSDIO) ++ srom_var_deinit((void *)si_local); ++#endif ++ nvram_exit((void *)si_local); /* free up nvram buffers */ ++#endif ++ ++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) ++ if (sii != &ksii) ++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ ++ MFREE(sii->osh, sii, sizeof(si_info_t)); ++} ++ ++void * ++si_osh(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->osh; ++} ++ ++void ++si_setosh(si_t *sih, osl_t *osh) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (sii->osh != NULL) { ++ SI_ERROR(("osh is already set....\n")); ++ ASSERT(!sii->osh); ++ } ++ sii->osh = osh; ++} ++ ++uint ++si_intflag(si_t *sih) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_intflag(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return R_REG(sii->osh, ((uint32 *)(uintptr) ++ (sii->oob_router + OOB_STATUSA))); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint ++si_flag(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_flag(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_flag(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_flag(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_setint(si_t *sih, int siflag) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_setint(sih, siflag); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_setint(sih, siflag); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_setint(sih, siflag); ++ else ++ ASSERT(0); ++} ++ ++uint ++si_coreid(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->coreid[sii->curidx]; ++} ++ ++uint ++si_coreidx(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->curidx; ++} ++ ++/* return the core-type instantiation # of the current core */ ++uint ++si_coreunit(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ uint coreid; ++ uint coreunit; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ coreunit = 0; ++ ++ idx = sii->curidx; ++ ++ ASSERT(GOODREGS(sii->curmap)); ++ coreid = si_coreid(sih); ++ ++ /* count the cores of our type */ ++ for (i = 0; i < idx; i++) ++ if (sii->coreid[i] == coreid) ++ coreunit++; ++ ++ return (coreunit); ++} ++ ++uint ++si_corevendor(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corevendor(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corevendor(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corevendor(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_backplane64(si_t *sih) ++{ ++ return ((sih->cccaps & CC_CAP_BKPLN64) != 0); ++} ++ ++uint ++si_corerev(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corerev(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corerev(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corerev(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++/* return index of coreid or BADIDX if not found */ ++uint ++si_findcoreidx(si_t *sih, uint coreid, uint coreunit) ++{ ++ si_info_t *sii; ++ uint found; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ ++ found = 0; ++ ++ for (i = 0; i < sii->numcores; i++) ++ if (sii->coreid[i] == coreid) { ++ if (found == coreunit) ++ return (i); ++ found++; ++ } ++ ++ return (BADIDX); ++} ++ ++/* return list of found cores */ ++uint ++si_corelist(si_t *sih, uint coreid[]) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); ++ return (sii->numcores); ++} ++ ++/* return current register mapping */ ++void * ++si_coreregs(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curmap)); ++ ++ return (sii->curmap); ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void * ++si_setcore(si_t *sih, uint coreid, uint coreunit) ++{ ++ uint idx; ++ ++ idx = si_findcoreidx(sih, coreid, coreunit); ++ if (!GOODIDX(idx)) ++ return (NULL); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, idx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_setcoreidx(sih, idx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, idx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++void * ++si_setcoreidx(si_t *sih, uint coreidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, coreidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_setcoreidx(sih, coreidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, coreidx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++/* Turn off interrupt as required by sb_setcore, before switch core */ ++void * ++si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) ++{ ++ void *cc; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ if (SI_FAST(sii)) { ++ /* Overloading the origidx variable to remember the coreid, ++ * this works because the core ids cannot be confused with ++ * core indices. ++ */ ++ *origidx = coreid; ++ if (coreid == CC_CORE_ID) ++ return (void *)CCREGS_FAST(sii); ++ else if (coreid == sih->buscoretype) ++ return (void *)PCIEREGS(sii); ++ } ++ INTR_OFF(sii, *intr_val); ++ *origidx = sii->curidx; ++ cc = si_setcore(sih, coreid, 0); ++ ASSERT(cc != NULL); ++ ++ return cc; ++} ++ ++/* restore coreidx and restore interrupt */ ++void ++si_restore_core(si_t *sih, uint coreid, uint intr_val) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) ++ return; ++ ++ si_setcoreidx(sih, coreid); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++int ++si_numaddrspaces(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_numaddrspaces(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_numaddrspaces(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_numaddrspaces(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspace(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspace(sih, asidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_addrspace(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspace(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspacesize(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspacesize(sih, asidx); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_addrspacesize(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspacesize(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ /* Only supported for SOCI_AI */ ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_coreaddrspaceX(sih, asidx, addr, size); ++ else ++ *size = 0; ++} ++ ++uint32 ++si_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_cflags(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_core_cflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_cflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_cflags_wo(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_cflags_wo(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_cflags_wo(sih, mask, val); ++ else ++ ASSERT(0); ++} ++ ++uint32 ++si_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_sflags(sih, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_core_sflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_sflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_iscoreup(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_iscoreup(sih); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_iscoreup(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_iscoreup(sih); ++ else { ++ ASSERT(0); ++ return FALSE; ++ } ++} ++ ++uint ++si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ /* only for AI back plane chips */ ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return (ai_wrap_reg(sih, offset, mask, val)); ++ return 0; ++} ++ ++uint ++si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corereg(sih, coreidx, regoff, mask, val); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ return ai_corereg(sih, coreidx, regoff, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corereg(sih, coreidx, regoff, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_disable(si_t *sih, uint32 bits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_disable(sih, bits); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_disable(sih, bits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_disable(sih, bits); ++} ++ ++void ++si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_reset(sih, bits, resetbits); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_core_reset(sih, bits, resetbits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_reset(sih, bits, resetbits); ++} ++ ++/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ ++int ++si_corebist(si_t *sih) ++{ ++ uint32 cflags; ++ int result = 0; ++ ++ /* Read core control flags */ ++ cflags = si_core_cflags(sih, 0, 0); ++ ++ /* Set bist & fgc */ ++ si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); ++ ++ /* Wait for bist done */ ++ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); ++ ++ if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) ++ result = BCME_ERROR; ++ ++ /* Reset core control flags */ ++ si_core_cflags(sih, 0xffff, cflags); ++ ++ return result; ++} ++ ++static uint32 ++BCMINITFN(factor6)(uint32 x) ++{ ++ switch (x) { ++ case CC_F6_2: return 2; ++ case CC_F6_3: return 3; ++ case CC_F6_4: return 4; ++ case CC_F6_5: return 5; ++ case CC_F6_6: return 6; ++ case CC_F6_7: return 7; ++ default: return 0; ++ } ++} ++ ++/* calculate the speed the SI would run at given a set of clockcontrol values */ ++uint32 ++BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m) ++{ ++ uint32 n1, n2, clock, m1, m2, m3, mc; ++ ++ n1 = n & CN_N1_MASK; ++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; ++ ++ if (pll_type == PLL_TYPE6) { ++ if (m & CC_T6_MMASK) ++ return CC_T6_M1; ++ else ++ return CC_T6_M0; ++ } else if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ n1 = factor6(n1); ++ n2 += CC_F5_BIAS; ++ } else if (pll_type == PLL_TYPE2) { ++ n1 += CC_T2_BIAS; ++ n2 += CC_T2_BIAS; ++ ASSERT((n1 >= 2) && (n1 <= 7)); ++ ASSERT((n2 >= 5) && (n2 <= 23)); ++ } else if (pll_type == PLL_TYPE5) { ++ return (100000000); ++ } else ++ ASSERT(0); ++ /* PLL types 3 and 7 use BASE2 (25Mhz) */ ++ if ((pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE7)) { ++ clock = CC_CLOCK_BASE2 * n1 * n2; ++ } else ++ clock = CC_CLOCK_BASE1 * n1 * n2; ++ ++ if (clock == 0) ++ return 0; ++ ++ m1 = m & CC_M1_MASK; ++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; ++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; ++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; ++ ++ if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ m1 = factor6(m1); ++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) ++ m2 += CC_F5_BIAS; ++ else ++ m2 = factor6(m2); ++ m3 = factor6(m3); ++ ++ switch (mc) { ++ case CC_MC_BYPASS: return (clock); ++ case CC_MC_M1: return (clock / m1); ++ case CC_MC_M1M2: return (clock / (m1 * m2)); ++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); ++ case CC_MC_M1M3: return (clock / (m1 * m3)); ++ default: return (0); ++ } ++ } else { ++ ASSERT(pll_type == PLL_TYPE2); ++ ++ m1 += CC_T2_BIAS; ++ m2 += CC_T2M2_BIAS; ++ m3 += CC_T2_BIAS; ++ ASSERT((m1 >= 2) && (m1 <= 7)); ++ ASSERT((m2 >= 3) && (m2 <= 10)); ++ ASSERT((m3 >= 2) && (m3 <= 7)); ++ ++ if ((mc & CC_T2MC_M1BYP) == 0) ++ clock /= m1; ++ if ((mc & CC_T2MC_M2BYP) == 0) ++ clock /= m2; ++ if ((mc & CC_T2MC_M3BYP) == 0) ++ clock /= m3; ++ ++ return (clock); ++ } ++} ++ ++uint32 ++BCMINITFN(si_clock)(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint32 n, m; ++ uint idx; ++ uint32 pll_type, rate; ++ uint intr_val = 0; ++ ++ if (IS_IPROC_CHIP_ID(CHIPID(sih->chip))) { ++ if (sih->chippkg == BCM4709_PKG_ID) { ++ return NS_SI_CLOCK; ++ } else ++ return NS_SLOW_SI_CLOCK; ++ } ++ ++ sii = SI_INFO(sih); ++ INTR_OFF(sii, intr_val); ++ ++ idx = sii->curidx; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ n = R_REG(sii->osh, &cc->clockcontrol_n); ++ pll_type = sih->cccaps & CC_CAP_PLL_MASK; ++ if (pll_type == PLL_TYPE6) ++ m = R_REG(sii->osh, &cc->clockcontrol_m3); ++ else if (pll_type == PLL_TYPE3) ++ m = R_REG(sii->osh, &cc->clockcontrol_m2); ++ else ++ m = R_REG(sii->osh, &cc->clockcontrol_sb); ++ ++ /* calculate rate */ ++ rate = si_clock_rate(pll_type, n, m); ++ ++ if (pll_type == PLL_TYPE3) ++ rate = rate / 2; ++ ++ /* switch back to previous core */ ++ si_setcoreidx(sih, idx); ++ ++ INTR_RESTORE(sii, intr_val); ++ ++ return rate; ++} ++ ++uint32 ++BCMINITFN(si_alp_clock)(si_t *sih) ++{ ++ if (IS_IPROC_CHIP_ID(CHIPID(sih->chip))) { ++ if (sih->chippkg == BCM4709_PKG_ID) ++ return NS_ALP_CLOCK; ++ else ++ return NS_SLOW_ALP_CLOCK; ++ } ++ ++ return NS_ALP_CLOCK; ++} ++ ++ ++#if defined(BCMDBG) ++/* print interesting sbconfig registers */ ++void ++si_dumpregs(si_t *sih, struct bcmstrbuf *b) ++{ ++ si_info_t *sii; ++ uint origidx, intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ origidx = sii->curidx; ++ ++ INTR_OFF(sii, intr_val); ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_dumpregs(sih, b); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_dumpregs(sih, b); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_dumpregs(sih, b); ++ else ++ ASSERT(0); ++ ++ si_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++} ++#endif ++ ++#ifdef BCMDBG ++void ++si_view(si_t *sih, bool verbose) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_view(sih, verbose); ++ else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_view(sih, verbose); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_view(sih, verbose); ++ else ++ ASSERT(0); ++} ++ ++void ++si_viewall(si_t *sih, bool verbose) ++{ ++ si_info_t *sii; ++ uint curidx, i; ++ uint intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ curidx = sii->curidx; ++ ++ INTR_OFF(sii, intr_val); ++ if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NS)) ++ ai_viewall(sih, verbose); ++ else { ++ SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores)); ++ for (i = 0; i < sii->numcores; i++) { ++ si_setcoreidx(sih, i); ++ si_view(sih, verbose); ++ } ++ } ++ si_setcoreidx(sih, curidx); ++ INTR_RESTORE(sii, intr_val); ++} ++#endif /* BCMDBG */ ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ++si_slowclk_src(si_info_t *sii) ++{ ++ chipcregs_t *cc; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ if (sii->pub.ccrev < 6) { ++ return (SCC_SS_XTAL); ++ } else if (sii->pub.ccrev < 10) { ++ cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); ++ return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); ++ } else /* Insta-clock */ ++ return (SCC_SS_XTAL); ++} ++ ++/* return the ILP (slowclock) min or max frequency */ ++static uint ++si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) ++{ ++ uint32 slowclk; ++ uint div; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ /* shouldn't be here unless we've established the chip has dynamic clk control */ ++ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); ++ ++ slowclk = si_slowclk_src(sii); ++ if (sii->pub.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); ++ else ++ return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); ++ } else if (sii->pub.ccrev < 10) { ++ div = 4 * ++ (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return (max_freq ? LPOMAXFREQ : LPOMINFREQ); ++ else if (slowclk == SCC_SS_XTAL) ++ return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); ++ else if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); ++ else ++ ASSERT(0); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); ++ } ++ return (0); ++} ++ ++static void ++BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs) ++{ ++ chipcregs_t *cc = (chipcregs_t *)chipcregs; ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; ++ ++ pll_delay = PLL_DELAY; ++ ++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay ++ * since the xtal will also be powered down by dynamic clk control logic. ++ */ ++ ++ slowclk = si_slowclk_src(sii); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; ++ ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); ++ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ ++ W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); ++ W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); ++} ++ ++/* initialize power control delay registers */ ++void ++BCMINITFN(si_clkctl_init)(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx = 0; ++ chipcregs_t *cc; ++ bool fast; ++ ++ if (!CCCTL_ENAB(sih)) ++ return; ++ ++ sii = SI_INFO(sih); ++ fast = SI_FAST(sii); ++ if (!fast) { ++ origidx = sii->curidx; ++ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) ++ return; ++ } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) ++ return; ++ ASSERT(cc != NULL); ++ ++ /* set all Instaclk chip ILP to 1 MHz */ ++ if (sih->ccrev >= 10) ++ SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); ++ ++ si_clkctl_setdelay(sii, (void *)(uintptr)cc); ++ ++ if (!fast) ++ si_setcoreidx(sih, origidx); ++} ++ ++/* turn primary xtal and/or pll off/on */ ++int ++si_clkctl_xtal(si_t *sih, uint what, bool on) ++{ ++ switch (BUSTYPE(sih->bustype)) { ++ ++ default: ++ return (-1); ++ } ++ ++} ++ ++/* ++ * clock control policy function throught chipcommon ++ * ++ * set dynamic clk control mode (forceslow, forcefast, dynamic) ++ * returns true if we are forcing fast clock ++ * this is a wrapper over the next internal function ++ * to allow flexible policy settings for outside caller ++ */ ++bool ++si_clkctl_cc(si_t *sih, uint mode) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sih->ccrev < 6) ++ return FALSE; ++ ++ if (PCI_FORCEHT(sii)) ++ return (mode == CLK_FAST); ++ ++ return _si_clkctl_cc(sii, mode); ++} ++ ++/* clk control mechanism through chipcommon, no policy checking */ ++static bool ++_si_clkctl_cc(si_info_t *sii, uint mode) ++{ ++ uint origidx = 0; ++ chipcregs_t *cc; ++ uint32 scc; ++ uint intr_val = 0; ++ bool fast = SI_FAST(sii); ++ ++ /* chipcommon cores prior to rev6 don't support dynamic clock control */ ++ if (sii->pub.ccrev < 6) ++ return (FALSE); ++ ++ /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */ ++ ASSERT(sii->pub.ccrev != 10); ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ origidx = sii->curidx; ++ ++ if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && ++ si_setcore(&sii->pub, MIPS33_CORE_ID, 0) && ++ (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10)) ++ goto done; ++ ++ cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0); ++ } else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL) ++ goto done; ++ ASSERT(cc != NULL); ++ ++ if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20)) ++ goto done; ++ ++ switch (mode) { ++ case CLK_FAST: /* FORCEHT, fast (pll) clock */ ++ if (sii->pub.ccrev < 10) { ++ /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */ ++ si_clkctl_xtal(&sii->pub, XTAL, ON); ++ SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP); ++ } else if (sii->pub.ccrev < 20) { ++ OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR); ++ } else { ++ OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT); ++ } ++ ++ /* wait for the PLL */ ++ if (PMUCTL_ENAB(&sii->pub)) { ++ uint32 htavail = CCS_HTAVAIL; ++ if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID) ++ htavail = CCS0_HTAVAIL; ++ SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0), ++ PMU_MAX_TRANSITION_DLY); ++ ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail); ++ } else { ++ OSL_DELAY(PLL_DELAY); ++ } ++ break; ++ ++ case CLK_DYNAMIC: /* enable dynamic clock control */ ++ if (sii->pub.ccrev < 10) { ++ scc = R_REG(sii->osh, &cc->slow_clk_ctl); ++ scc &= ~(SCC_FS | SCC_IP | SCC_XC); ++ if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) ++ scc |= SCC_XC; ++ W_REG(sii->osh, &cc->slow_clk_ctl, scc); ++ ++ /* for dynamic control, we have to release our xtal_pu "force on" */ ++ if (scc & SCC_XC) ++ si_clkctl_xtal(&sii->pub, XTAL, OFF); ++ } else if (sii->pub.ccrev < 20) { ++ /* Instaclock */ ++ AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR); ++ } else { ++ AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT); ++ } ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++done: ++ if (!fast) { ++ si_setcoreidx(&sii->pub, origidx); ++ INTR_RESTORE(sii, intr_val); ++ } ++ return (mode == CLK_FAST); ++} ++ ++/* Build device path. Support SI, PCI, and JTAG for now. */ ++int ++BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size) ++{ ++ int slen; ++ ++ ASSERT(path != NULL); ++ ASSERT(size >= SI_DEVPATH_BUFSZ); ++ ++ if (!path || size <= 0) ++ return -1; ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih)); ++ break; ++ default: ++ slen = -1; ++ ASSERT(0); ++ break; ++ } ++ ++ if (slen < 0 || slen >= size) { ++ path[0] = '\0'; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++char * ++BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name) ++{ ++ char pathname[SI_DEVPATH_BUFSZ + 32]; ++ char devpath[SI_DEVPATH_BUFSZ + 32]; ++ char *p; ++ int idx; ++ int len; ++ ++ /* try to get compact devpath if it exist */ ++ if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) { ++ len = strlen(devpath); ++ devpath[len - 1] = '\0'; ++ for (idx = 0; idx < SI_MAXCORES; idx++) { ++ snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx); ++ if ((p = getvar(NULL, pathname)) == NULL) ++ continue; ++ ++ if (strncmp(p, devpath, len) == 0) { ++ snprintf(varname, var_len, "%d:%s", idx, name); ++ return varname; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/* Get a variable, but only if it has a devpath prefix */ ++int ++BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name) ++{ ++#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS) ++ return (getintvar(NULL, name)); ++#else ++ char varname[SI_DEVPATH_BUFSZ + 32]; ++ int val; ++ ++ si_devpathvar(sih, varname, sizeof(varname), name); ++ ++ if ((val = getintvar(NULL, varname)) != 0) ++ return val; ++ ++ /* try to get compact devpath if it exist */ ++ if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL) ++ return 0; ++ ++ return (getintvar(NULL, varname)); ++#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */ ++} ++ ++/* Concatenate the dev path with a varname into the given 'var' buffer ++ * and return the 'var' pointer. ++ * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned. ++ * On overflow, the first char will be set to '\0'. ++ */ ++static char * ++BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name) ++{ ++ uint path_len; ++ ++ if (!var || len <= 0) ++ return var; ++ ++ if (si_devpath(sih, var, len) == 0) { ++ path_len = strlen(var); ++ ++ if (strlen(name) + 1 > (uint)(len - path_len)) ++ var[0] = '\0'; ++ else ++ strncpy(var + path_len, name, len - path_len - 1); ++ } ++ ++ return var; ++} ++ ++ ++#if defined(BCMDBG) ++#endif ++ ++ ++/* mask&set gpio output enable bits */ ++uint32 ++si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioouten); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* mask&set gpio output bits */ ++uint32 ++si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioout); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} +diff --git a/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h b/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h +new file mode 100755 +index 0000000..56650d1 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/siutils_priv.h +@@ -0,0 +1,259 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * Include file private to the SOC Interconnect support files. ++ * ++ * $Id: siutils_priv.h 302333 2011-12-11 01:47:49Z $ ++ */ ++ ++#ifndef _siutils_priv_h_ ++#define _siutils_priv_h_ ++ ++#ifdef BCMDBG_ERR ++#define SI_ERROR(args) printf args ++#else ++#define SI_ERROR(args) ++#endif /* BCMDBG_ERR */ ++ ++#ifdef BCMDBG ++#define SI_MSG(args) printf args ++#else ++#define SI_MSG(args) ++#endif /* BCMDBG */ ++ ++#ifdef BCMDBG_SI ++#define SI_VMSG(args) printf args ++#else ++#define SI_VMSG(args) ++#endif ++ ++#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) ++ ++ ++typedef uint32 (*si_intrsoff_t)(void *intr_arg); ++typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); ++typedef bool (*si_intrsenabled_t)(void *intr_arg); ++ ++typedef struct gpioh_item { ++ void *arg; ++ bool level; ++ gpio_handler_t handler; ++ uint32 event; ++ struct gpioh_item *next; ++} gpioh_item_t; ++ ++/* misc si info needed by some of the routines */ ++typedef struct si_info { ++ struct si_pub pub; /* back plane public state (must be first field) */ ++ ++ void *osh; /* osl os handle */ ++ void *sdh; /* bcmsdh handle */ ++ ++ uint dev_coreid; /* the core provides driver functions */ ++ void *intr_arg; /* interrupt callback function arg */ ++ si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ ++ si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ ++ si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ ++ ++ void *pch; /* PCI/E core handle */ ++ ++ gpioh_item_t *gpioh_head; /* GPIO event handlers list */ ++ ++ bool memseg; /* flag to toggle MEM_SEG register */ ++ ++ char *vars; ++ uint varsz; ++ ++ void *curmap; /* current regs va */ ++ void *regs[SI_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SI_MAXCORES]; /* id of each core */ ++ uint32 coresba[SI_MAXCORES]; /* backplane address of each core */ ++ void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */ ++ uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */ ++ uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */ ++ uint32 coresba2_size[SI_MAXCORES]; /* second address space size */ ++ ++ void *curwrap; /* current wrapper va */ ++ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ ++ uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ ++ ++ uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 oob_router; /* oob router registers for axi */ ++} si_info_t; ++ ++#define SI_INFO(sih) (si_info_t *)(uintptr)sih ++ ++#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ ++ ISALIGNED((x), SI_CORE_SIZE)) ++#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE)) ++#define BADCOREADDR 0 ++#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES) ++#define NOREV -1 /* Invalid rev */ ++ ++#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCI_CORE_ID)) ++ ++#define PCIE_GEN1(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE_CORE_ID)) ++ ++#define PCIE_GEN2(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE2_CORE_ID)) ++ ++#define PCIE(si) (PCIE_GEN1(si) || PCIE_GEN2(si)) ++ ++#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE)) ++ ++/* Newer chips can access PCI/PCIE and CC core without requiring to change ++ * PCI BAR0 WIN ++ */ ++#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13))) ++ ++#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET)) ++#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET)) ++ ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ ++ * after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } ++ ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++#define PCI_FORCEHT(si) \ ++ (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ ++ ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4716_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4748_CHIP_ID))) ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ ++ ++#ifndef DEFAULT_GPIOTIMERVAL ++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++#endif ++ ++#define sb_scan(a, b, c) do {} while (0) ++#define sb_coreid(a) (0) ++#define sb_intflag(a) (0) ++#define sb_flag(a) (0) ++#define sb_setint(a, b) do {} while (0) ++#define sb_corevendor(a) (0) ++#define sb_corerev(a) (0) ++#define sb_corereg(a, b, c, d, e) (0) ++#define sb_iscoreup(a) (false) ++#define sb_setcoreidx(a, b) (0) ++#define sb_core_cflags(a, b, c) (0) ++#define sb_core_cflags_wo(a, b, c) do {} while (0) ++#define sb_core_sflags(a, b, c) (0) ++#define sb_commit(a) do {} while (0) ++#define sb_base(a) (0) ++#define sb_size(a) (0) ++#define sb_core_reset(a, b, c) do {} while (0) ++#define sb_core_disable(a, b) do {} while (0) ++#define sb_addrspace(a, b) (0) ++#define sb_addrspacesize(a, b) (0) ++#define sb_numaddrspaces(a) (0) ++#define sb_set_initiator_to(a, b, c) (0) ++#define sb_taclear(a, b) (false) ++#define sb_view(a, b) do {} while (0) ++#define sb_viewall(a, b) do {} while (0) ++#define sb_dump(a, b) do {} while (0) ++#define sb_dumpregs(a, b) do {} while (0) ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool sb_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool sb_pci_fastpmecap(struct osl_info *osh); ++extern bool sb_pci_pmeclr(si_t *sih); ++extern void sb_pci_pmeen(si_t *sih); ++extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset); ++ ++/* AMBA Interconnect exported externs */ ++extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *ai_kattach(osl_t *osh); ++extern void ai_scan(si_t *sih, void *regs, uint devid); ++ ++extern uint ai_flag(si_t *sih); ++extern void ai_setint(si_t *sih, int siflag); ++extern uint ai_coreidx(si_t *sih); ++extern uint ai_corevendor(si_t *sih); ++extern uint ai_corerev(si_t *sih); ++extern bool ai_iscoreup(si_t *sih); ++extern void *ai_setcoreidx(si_t *sih, uint coreidx); ++extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); ++extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void ai_core_disable(si_t *sih, uint32 bits); ++extern int ai_numaddrspaces(si_t *sih); ++extern uint32 ai_addrspace(si_t *sih, uint asidx); ++extern uint32 ai_addrspacesize(si_t *sih, uint asidx); ++extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++ ++#ifdef BCMDBG ++extern void ai_view(si_t *sih, bool verbose); ++extern void ai_viewall(si_t *sih, bool verbose); ++#endif ++#if defined(BCMDBG) ++extern void ai_dumpregs(si_t *sih, struct bcmstrbuf *b); ++#endif ++ ++#ifdef SI_ENUM_BASE_VARIABLE ++extern void si_enum_base_init(si_t *sih, uint bustype); ++#endif /* SI_ENUM_BASE_VARIABLE */ ++ ++#define ub_scan(a, b, c) do {} while (0) ++#define ub_flag(a) (0) ++#define ub_setint(a, b) do {} while (0) ++#define ub_coreidx(a) (0) ++#define ub_corevendor(a) (0) ++#define ub_corerev(a) (0) ++#define ub_iscoreup(a) (0) ++#define ub_setcoreidx(a, b) (0) ++#define ub_core_cflags(a, b, c) (0) ++#define ub_core_cflags_wo(a, b, c) do {} while (0) ++#define ub_core_sflags(a, b, c) (0) ++#define ub_corereg(a, b, c, d, e) (0) ++#define ub_core_reset(a, b, c) do {} while (0) ++#define ub_core_disable(a, b) do {} while (0) ++#define ub_numaddrspaces(a) (0) ++#define ub_addrspace(a, b) (0) ++#define ub_addrspacesize(a, b) (0) ++#define ub_view(a, b) do {} while (0) ++#define ub_dumpregs(a, b) do {} while (0) ++ ++#endif /* _siutils_priv_h_ */ +diff --git a/drivers/bcmdrivers/gmac/src/shared/wl_config b/drivers/bcmdrivers/gmac/src/shared/wl_config +new file mode 100755 +index 0000000..aded587 +--- /dev/null ++++ b/drivers/bcmdrivers/gmac/src/shared/wl_config +@@ -0,0 +1,26 @@ ++# ++# Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++# ++# Permission to use, copy, modify, and/or distribute this software for any ++# purpose with or without fee is hereby granted, provided that the above ++# copyright notice and this permission notice appear in all copies. ++# ++# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++# wl driver config shared hnd files ++# ++ ++HNDDMA=1 ++BCMUTILS=1 ++SIUTILS=1 ++#BCMSROM=1 ++#BCMOTP=1 ++BCMDMA32=1 ++ ++# OSL shared ++OSLLX=1 +diff --git a/drivers/bcmdrivers/gpio/.gitignore b/drivers/bcmdrivers/gpio/.gitignore +new file mode 100644 +index 0000000..9463d48 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/.gitignore +@@ -0,0 +1,12 @@ ++/.built-in.o.cmd ++/.gpio_cfg.o.cmd ++/.gpio.o.cmd ++/.gpiolib.o.cmd ++/.iproc_gpio.o.cmd ++/built-in.o ++/gpio_cfg.o ++/gpio.o ++/gpiolib.o ++/iproc_gpio.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/gpio/Kconfig b/drivers/bcmdrivers/gpio/Kconfig +new file mode 100644 +index 0000000..0bcd76f +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/Kconfig +@@ -0,0 +1,11 @@ ++config IPROC_GPIO ++ tristate "GPIO support" ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select GPIOLIB ++ depends on ARCH_IPROC ++ default y ++ help ++ Add GPIO support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/gpio/Makefile b/drivers/bcmdrivers/gpio/Makefile +new file mode 100644 +index 0000000..edbecf6 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_GPIO) += iproc_gpio.o ++iproc_gpio-objs := gpio.o gpio_cfg.o gpiolib.o +diff --git a/drivers/bcmdrivers/gpio/gpio.c b/drivers/bcmdrivers/gpio/gpio.c +new file mode 100644 +index 0000000..cd41cf6 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio.c +@@ -0,0 +1,744 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#include "gpio.h" ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) ++#define irq_get_chip_data get_irq_chip_data ++#define irq_set_chip_data set_irq_chip_data ++#define irq_set_chip set_irq_chip ++#define irq_set_handler set_irq_handler ++#define status_use_accessors status ++#endif ++ ++ ++static struct iproc_gpio_chip *iproc_gpio_dev[MAX_NS_GPIO] = {}; ++static int dev = 0; ++ ++static unsigned int _iproc_gpio_readl(struct iproc_gpio_chip *chip, int reg) ++{ ++ return readl(chip->ioaddr + reg); ++} ++ ++static void _iproc_gpio_writel(struct iproc_gpio_chip *chip, unsigned int val, int reg) ++{ ++ writel(val, chip->ioaddr + reg); ++} ++ ++ ++/* ++@ pin : the actual pin number of the gpiochip ++*/ ++static int iproc_gpio_to_irq(struct iproc_gpio_chip *chip, unsigned int pin) { ++ return (chip->irq_base + pin - chip->pin_offset); ++} ++ ++/* ++returns the actual pin number of the gpiochip ++*/ ++static int iproc_irq_to_gpio(struct iproc_gpio_chip *chip, unsigned int irq) { ++ return (irq - chip->irq_base + chip->pin_offset); ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_ack(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_ack(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->ack) ++ irqcfg->ack(irq); ++ ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_unmask(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_unmask(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->unmask) ++ irqcfg->unmask(irq); ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static void iproc_gpio_irq_mask(unsigned int irq) ++{ ++#else ++static void iproc_gpio_irq_mask(struct irq_data *d) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->mask) ++ irqcfg->mask(irq); ++ } ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++static int iproc_gpio_irq_set_type(unsigned int irq, unsigned int type) ++{ ++#else ++static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) ++{ ++ unsigned int irq = d->irq; ++#endif ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ ++ if (ourchip) { ++ struct iproc_gpio_irqcfg *irqcfg = ourchip->irqcfg; ++ if (irqcfg && irqcfg->set_type) ++ return irqcfg->set_type(irq, type); ++ } ++ return -EINVAL; ++} ++ ++#if defined(IPROC_GPIO_CCA) ++static irqreturn_t ++iproc_gpio_irq_handler_cca(int irq, void *dev) ++ ++{ ++ unsigned int val, irq_type; ++ unsigned int int_mask, int_pol, in; ++ unsigned int event_mask, event, event_pol, tmp = 0; ++ int iter, g_irq, max_pin; ++ struct iproc_gpio_chip *ourchip = dev; ++ ++ ++ val = readl(ourchip->intr_ioaddr + IPROC_CCA_INT_STS); ++ ++ if (val & IPROC_CCA_INT_F_GPIOINT) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); ++ in = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_DIN); ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ event = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT); ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ ++ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { ++ g_irq = iproc_gpio_to_irq(ourchip, iter); ++ irq_type = irq_desc[g_irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ switch(irq_type) { ++ case IRQ_TYPE_EDGE_RISING: ++ tmp = event_mask; ++ tmp &= event; ++ tmp &= ~event_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ tmp = event_mask; ++ tmp &= event; ++ tmp &= event_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ tmp = in ^ int_pol; ++ tmp &= int_mask; ++ tmp &= int_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ tmp = in ^ int_pol; ++ tmp &= int_mask; ++ tmp &= ~int_pol; ++ if (tmp & (1 << iter)) { ++ generic_handle_irq(g_irq); ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ }else { ++ return IRQ_NONE; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_status, irq_type; ++ ++ event_status = 0; ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) ++ { ++ event_status |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_status, ++ IPROC_GPIO_CCA_INT_EVENT); ++ } ++ ++ } ++} ++ ++static void iproc_gpio_irq_unmask_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask, irq_type; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_mask; ++ ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, event_mask, ++ IPROC_GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask |= 1 << pin; ++ _iproc_gpio_writel(ourchip, int_mask, ++ IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ } ++ } ++ ++} ++ ++static void iproc_gpio_irq_mask_cca(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int irq_type, int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ irq_type = irq_desc[irq].status_use_accessors & IRQ_TYPE_SENSE_MASK; ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_mask; ++ ++ event_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EVENT_MASK); ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ ++ if (irq_type & IRQ_TYPE_EDGE_BOTH) { ++ event_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_mask, ++ IPROC_GPIO_CCA_INT_EVENT_MASK); ++ } else { ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, ++ IPROC_GPIO_CCA_INT_LEVEL_MASK); ++ } ++ } ++} ++ ++static int iproc_gpio_irq_set_type_cca(unsigned int irq, unsigned int type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if (ourchip->id == IPROC_GPIO_CCA_ID) { ++ unsigned int event_pol, int_pol; ++ ++ switch (type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_RISING: ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ event_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ event_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_EDGE); ++ event_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, event_pol, IPROC_GPIO_CCA_INT_EDGE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_pol = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCA_INT_LEVEL); ++ int_pol &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_pol = _iproc_gpio_readl(ourchip,IPROC_GPIO_CCA_INT_LEVEL); ++ int_pol |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_pol, IPROC_GPIO_CCA_INT_LEVEL); ++ break; ++ default: ++ printk(KERN_ERR "unsupport irq type !\n"); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg cca_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND|IRQF_SHARED, ++ .handler = iproc_gpio_irq_handler_cca, ++ .ack = iproc_gpio_irq_ack_cca, ++ .mask = iproc_gpio_irq_mask_cca, ++ .unmask = iproc_gpio_irq_unmask_cca, ++ .set_type = iproc_gpio_irq_set_type_cca, ++}; ++#endif /* IPROC_GPIO_CCA */ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++static irqreturn_t ++iproc_gpio_irq_handler_ccb(int irq, void *dev) ++{ ++ struct iproc_gpio_chip *ourchip = dev; ++ int iter, max_pin; ++ unsigned int val; ++ ++ val = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MSTAT); ++ if(!val){ ++ return IRQ_NONE; ++ } ++ ++ max_pin = ourchip->pin_offset + ourchip->chip.ngpio; ++ for (iter = ourchip->pin_offset; iter < max_pin; iter ++) { ++ if (val & (1 << iter)) { ++ generic_handle_irq(iproc_gpio_to_irq(ourchip, iter)); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void iproc_gpio_irq_ack_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned int int_clear = 0; ++ ++ int_clear |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_clear, IPROC_GPIO_CCB_INT_CLR); ++ ++ } ++} ++ ++static void iproc_gpio_irq_unmask_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); ++ int_mask |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask, IPROC_GPIO_CCB_INT_MASK); ++ } ++ ++} ++ ++static void iproc_gpio_irq_mask_ccb(unsigned int irq) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ unsigned int int_mask; ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ int_mask = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_MASK); ++ int_mask &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_mask,IPROC_GPIO_CCB_INT_MASK); ++ } ++} ++ ++static int iproc_gpio_irq_set_type_ccb(unsigned int irq, unsigned int type) ++{ ++ struct iproc_gpio_chip *ourchip = irq_get_chip_data(irq); ++ int pin; ++ ++ ++ pin = iproc_irq_to_gpio(ourchip, irq); ++ ++ if ((ourchip->id == IPROC_GPIO_CCB_ID) || ++ (ourchip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned int int_type, int_de, int_edge; ++ int_type = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_TYPE); ++ int_edge = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_EDGE); ++ switch (type) { ++ case IRQ_TYPE_EDGE_BOTH: ++ int_type &= ~(1 << pin); ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de |= (1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ int_type &= ~(1 << pin); ++ int_edge |= (1 << pin); ++ ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ int_type &= ~(1 << pin); ++ int_edge &= ~(1 << pin); ++ ++ int_de = _iproc_gpio_readl(ourchip, IPROC_GPIO_CCB_INT_DE); ++ int_de &= ~(1 << pin); ++ _iproc_gpio_writel(ourchip, int_de, IPROC_GPIO_CCB_INT_DE); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_type |= (1 << pin); ++ int_edge |= (1 << pin); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_type |= (1 << pin); ++ int_edge &= ~(1 << pin); ++ break; ++ default: ++ printk(KERN_ERR "unsupport irq type !\n"); ++ return -EINVAL; ++ } ++ _iproc_gpio_writel(ourchip, int_type, IPROC_GPIO_CCB_INT_TYPE); ++ _iproc_gpio_writel(ourchip, int_edge, IPROC_GPIO_CCB_INT_EDGE); ++ } ++ ++ return 0; ++} ++ ++struct iproc_gpio_irqcfg ccb_gpio_irqcfg = { ++ .flags = IRQF_NO_SUSPEND, ++ .handler = iproc_gpio_irq_handler_ccb, ++ .ack = iproc_gpio_irq_ack_ccb, ++ .mask = iproc_gpio_irq_mask_ccb, ++ .unmask = iproc_gpio_irq_unmask_ccb, ++ .set_type = iproc_gpio_irq_set_type_ccb, ++}; ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG*/ ++ ++ ++static struct irq_chip iproc_gpio_irq_chip = { ++ .name = "IPROC-GPIO", ++#if 0 ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 5) ++ .ack = (void *) iproc_gpio_irq_ack, ++ .mask = (void *) iproc_gpio_irq_mask, ++ .unmask = (void *) iproc_gpio_irq_unmask, ++ .set_type = (void *) iproc_gpio_irq_set_type, ++//#else ++#endif ++ .irq_ack = (void *) iproc_gpio_irq_ack, ++ .irq_mask = (void *) iproc_gpio_irq_mask, ++ .irq_unmask = (void *) iproc_gpio_irq_unmask, ++ .irq_set_type = (void *) iproc_gpio_irq_set_type, ++//#endif ++}; ++ ++struct iproc_gpio_chip *iproc_gpios[IPROC_GPIO_END]; ++ ++static __init void iproc_gpiolib_track(struct iproc_gpio_chip *chip) ++{ ++ unsigned int gpn; ++ int i; ++ ++ gpn = chip->chip.base; ++ for (i = 0; i < chip->chip.ngpio; i++, gpn++) { ++ BUG_ON(gpn >= ARRAY_SIZE(iproc_gpios)); ++ iproc_gpios[gpn] = chip; ++ } ++} ++ ++static int iproc_gpiolib_input(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned int val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val &= ~nBitMask; ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_EN); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ return 0; ++} ++ ++static int iproc_gpiolib_output(struct gpio_chip *chip, ++ unsigned gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned long val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val |= nBitMask; ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_EN); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ return 0; ++} ++ ++static void iproc_gpiolib_set(struct gpio_chip *chip, ++ unsigned gpio, int value) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned long val; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ ++ ++ /* determine the GPIO pin direction ++ */ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ val &= nBitMask; ++ ++ /* this function only applies to output pin ++ */ ++ if (!val) ++ return; ++ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ ++ if ( value == 0 ){ ++ /* Set the pin to zero */ ++ val &= ~nBitMask; ++ }else{ ++ /* Set the pin to 1 */ ++ val |= nBitMask; ++ } ++ _iproc_gpio_writel(ourchip, val, REGOFFSET_GPIO_DOUT); ++ ++ iproc_gpio_unlock(ourchip, flags); ++ ++} ++ ++ ++static int iproc_gpiolib_get(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ unsigned long flags; ++ unsigned int val, offset; ++ unsigned int pin_offset = gpio + ourchip->pin_offset; ++ unsigned int nBitMask = 1 << pin_offset; ++ ++ iproc_gpio_lock(ourchip, flags); ++ /* determine the GPIO pin direction ++ */ ++ offset = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_EN); ++ offset &= nBitMask; ++ ++ if (offset){ ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DOUT); ++ } else { ++ val = _iproc_gpio_readl(ourchip, REGOFFSET_GPIO_DIN); ++ } ++ val >>= pin_offset; ++ val &= 1; ++ iproc_gpio_unlock(ourchip, flags); ++ ++ return val; ++} ++ ++/* ++@offset : the gpio pin index number from gpiolib view (minus gpio base only) ++*/ ++static int iproc_gpiolib_to_irq(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ struct iproc_gpio_chip *ourchip = to_iproc_gpio(chip); ++ return iproc_gpio_to_irq(ourchip, offset + ourchip->pin_offset); ++} ++void __init iproc_gpiolib_add(struct iproc_gpio_chip *chip) ++{ ++ struct resource *res; ++ struct gpio_chip *gc = &chip->chip; ++ int ret, i; ++ ++ BUG_ON(!gc->label); ++ BUG_ON(!gc->ngpio); ++ ++ spin_lock_init(&chip->lock); ++ ++ if (!gc->direction_input) ++ gc->direction_input = iproc_gpiolib_input; ++ if (!gc->direction_output) ++ gc->direction_output = iproc_gpiolib_output; ++ if (!gc->set) ++ gc->set = iproc_gpiolib_set; ++ if (!gc->get) ++ gc->get = iproc_gpiolib_get; ++ if (!gc->to_irq) ++ gc->to_irq = iproc_gpiolib_to_irq; ++ ++ /* gpiochip_add() prints own failure message on error. */ ++ ret = gpiochip_add(gc); ++ if (ret >= 0) ++ iproc_gpiolib_track(chip); ++ ++ printk(KERN_INFO "iproc gpiochip add %s\n", gc->label); ++ /* io remap */ ++ res = chip->resource; ++ ++ chip->ioaddr = ioremap_nocache(res->start, (res->end - res->start) + 1); ++ printk(KERN_INFO "%s:ioaddr %p \n", gc->label, chip->ioaddr); ++ chip->intr_ioaddr = NULL; ++ chip->dmu_ioaddr = NULL; ++ if(res->child){ ++ for (i=0; i< 2; i++){ ++ if (!strcmp("intr", res->child[i].name)){ ++ chip->intr_ioaddr = ++ ioremap_nocache(res->child[i].start, ++ (res->child[i].end - res->child[i].start) + 1); ++ } ++ if (!strcmp("dmu", res->child[i].name)){ ++ chip->dmu_ioaddr = ++ ioremap_nocache(res->child[i].start, ++ (res->child[i].end - res->child[i].start) + 1); ++ } ++ } ++ printk(KERN_INFO "%s:intr_ioaddr %p dmu_ioaddr %p\n", ++ gc->label, chip->intr_ioaddr,chip->dmu_ioaddr); ++ } ++ ++ ++ if (chip->irq_base) { ++ for (i = chip->irq_base; i < (chip->irq_base + gc->ngpio); i++) { ++ irq_set_chip(i, &iproc_gpio_irq_chip); ++ irq_set_chip_data(i,chip); ++ irq_set_handler(i, handle_level_irq); ++ set_irq_flags(i, IRQF_VALID); ++ ++ } ++#if defined(IPROC_GPIO_CCA) ++ if (chip->id == IPROC_GPIO_CCA_ID ){ ++ unsigned int val; ++ /* enable the GPIO in CCA interrupt mask */ ++ val = readl(chip->intr_ioaddr + IPROC_CCA_INT_MASK); ++ val |= IPROC_CCA_INT_F_GPIOINT; ++ writel(val, chip->intr_ioaddr + IPROC_CCA_INT_MASK); ++ } ++#endif ++ if (chip->irqcfg) { ++ struct iproc_gpio_irqcfg *irqcfg = chip->irqcfg; ++ if (irqcfg->handler) { ++ ret = request_irq(chip->irq, irqcfg->handler, irqcfg->flags, ++ gc->label, chip); ++ if (ret) ++ printk(KERN_ERR "Unable to request IRQ%d: %d\n", ++ chip->irq, ret); ++ } ++ else ++ printk(KERN_ERR "%s is added without isr!\n", chip->chip.label); ++ } ++ } ++ iproc_gpio_dev[dev] = chip; ++ dev++; ++} ++ ++static int __init gpio_init(void) ++{ ++ iproc_gpiolib_init(); ++ ++ return 0; ++} ++static void __exit gpio_exit(void) ++{ ++ int i=0; ++ ++ for (i = 0 ; i < MAX_NS_GPIO; i++) { ++ if(iproc_gpio_dev[i]){ ++ if(iproc_gpio_dev[i]->ioaddr){ ++ iounmap(iproc_gpio_dev[i]->ioaddr); ++ } ++ if(iproc_gpio_dev[i]->intr_ioaddr){ ++#if defined(IPROC_GPIO_CCA) ++ if (iproc_gpio_dev[i]->id == IPROC_GPIO_CCA_ID ){ ++ unsigned int val; ++ val = readl(iproc_gpio_dev[i]->intr_ioaddr + IPROC_CCA_INT_MASK); ++ val &= ~(IPROC_CCA_INT_F_GPIOINT); ++ writel(val, iproc_gpio_dev[i]->intr_ioaddr + IPROC_CCA_INT_MASK); ++ } ++#endif ++ iounmap(iproc_gpio_dev[i]->intr_ioaddr); ++ } ++ if(iproc_gpio_dev[i]->dmu_ioaddr){ ++ iounmap(iproc_gpio_dev[i]->dmu_ioaddr); ++ } ++ if(iproc_gpio_dev[i]->irq_base) { ++ free_irq(iproc_gpio_dev[i]->irq,iproc_gpio_dev[i]); ++ } ++ ++ gpiochip_remove(&iproc_gpio_dev[i]->chip); ++ iproc_gpio_dev[i] = NULL; ++ } ++ } ++} ++ ++MODULE_DESCRIPTION("IPROC GPIO driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(gpio_init); ++module_exit(gpio_exit); +diff --git a/drivers/bcmdrivers/gpio/gpio.h b/drivers/bcmdrivers/gpio/gpio.h +new file mode 100644 +index 0000000..bfc44f7 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_PLAT_GPIO_H ++#define __IPROC_PLAT_GPIO_H ++ ++#include ++ ++#if defined(CONFIG_MACH_IPROC_P7) ++#define IPROC_GPIO_CCG ++#else ++#define IPROC_GPIO_CCA ++#define IPROC_GPIO_CCB ++#endif ++ ++#define IPROC_GPIO_REG_SIZE (0x50) ++ ++ ++ ++ ++ ++#define REGOFFSET_GPIO_DIN 0x000 /* GPIO Data in register */ ++#define REGOFFSET_GPIO_DOUT 0x004 /* GPIO Data out register */ ++#define REGOFFSET_GPIO_EN 0x008 /* GPIO driver enable register */ ++ ++ ++#define IPROC_GPIO_CCA_ID (0) ++#define IPROC_GPIO_CCB_ID (1) ++#define IPROC_GPIO_CCG_ID (2) ++ ++#define IPROC_GPIO_CCA_IRQ_BASE (IPROC_IRQ_GPIO_0) ++#define IPROC_GPIO_CCB_IRQ_BASE (IPROC_IRQ_GPIO_0 + 32) ++#define IPROC_GPIO_CCG_IRQ_BASE (IPROC_IRQ_GPIO_0) ++ ++ ++ ++ ++#define IPROC_CCA_INT_F_GPIOINT (1) ++ ++struct iproc_gpio_irqcfg { ++ unsigned long flags; ++ irqreturn_t (*handler)(int irq, void *dev); ++ void (*ack)(unsigned int irq); ++ void (*unmask)(unsigned int irq); ++ void (*mask)(unsigned int irq); ++ int (*set_type)(unsigned int irq, unsigned int type); ++}; ++ ++struct iproc_gpio_chip { ++ int id; ++ struct gpio_chip chip; ++ struct iproc_gpio_cfg *config; ++ void __iomem *ioaddr; ++ void __iomem *intr_ioaddr; ++ void __iomem *dmu_ioaddr; ++ spinlock_t lock; ++ int irq_base; ++ struct resource * resource; ++ int irq; ++ struct iproc_gpio_irqcfg *irqcfg; ++ int pin_offset; ++}; ++ ++ ++static inline struct iproc_gpio_chip *to_iproc_gpio(struct gpio_chip *gpc) ++{ ++ return container_of(gpc, struct iproc_gpio_chip, chip); ++} ++ ++#define IPROC_GPIO_END (32 + 4) ++ ++extern struct iproc_gpio_chip *iproc_gpios[IPROC_GPIO_END]; ++ ++static inline struct iproc_gpio_chip *iproc_gpiolib_getchip(unsigned int chip) ++{ ++ return (chip < IPROC_GPIO_END) ? iproc_gpios[chip] : NULL; ++} ++ ++/* locking wrappers to deal with multiple access to the same gpio bank */ ++#define iproc_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) ++#define iproc_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) ++ ++extern void iproc_gpiolib_add(struct iproc_gpio_chip *chip); ++extern int iproc_gpiolib_init(void); ++ ++#define MAX_NS_GPIO 2 ++ ++#endif +diff --git a/drivers/bcmdrivers/gpio/gpio_cfg.c b/drivers/bcmdrivers/gpio/gpio_cfg.c +new file mode 100644 +index 0000000..2bd1a74 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio_cfg.c +@@ -0,0 +1,402 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "gpio.h" ++#include "gpio_cfg.h" ++ ++#if defined(IPROC_GPIO_CCA) ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++int iproc_gpio_set_config_cca(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ aux_sel_reg = IPROC_GPIO_CCA_CTRL0; ++ base = (unsigned int)chip->dmu_ioaddr; ++ if(off <= 17){ ++ pin = 1 << off; ++ } else if (off >= 21){ ++ pin = 1 << (off - 3); ++ } else { ++ if (cfg == IPROC_GPIO_AUX_FUN) ++ return -EINVAL; ++ else ++ return 0; ++ } ++ } ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ switch (cfg) { ++ case IPROC_GPIO_GENERAL: ++ aux_sel |= pin; ++ break; ++ case IPROC_GPIO_AUX_FUN: ++ aux_sel &= ~(pin); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(aux_sel, base + aux_sel_reg); ++ ++ return 0; ++} ++ ++ ++unsigned iproc_gpio_get_config_cca(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ ++ aux_sel_reg = IPROC_GPIO_CCA_CTRL0; ++ base = (unsigned int)chip->dmu_ioaddr; ++ if(off <= 17){ ++ pin = 1 << off; ++ } else if (off >= 21){ ++ pin = 1 << (off - 3); ++ } else { ++ return IPROC_GPIO_GENERAL; ++ } ++ } ++ ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ if (aux_sel & pin) { ++ return IPROC_GPIO_GENERAL; ++ } else { ++ return IPROC_GPIO_AUX_FUN; ++ } ++} ++ ++ ++int iproc_gpio_setpull_updown_cca(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull) ++{ ++ unsigned int base; ++ base = 0; ++ ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ unsigned long pull_up, pull_down; ++ ++ base = (unsigned int)chip->dmu_ioaddr; ++ ++ pull_up = readl_relaxed(base + IPROC_GPIO_CCA_PULL_UP); ++ pull_down = readl_relaxed(base + IPROC_GPIO_CCA_PULL_DOWN); ++ ++ switch (pull) { ++ case IPROC_GPIO_PULL_UP: ++ pull_up |= (1 << off); ++ pull_down &= ~(1 << off); ++ break; ++ case IPROC_GPIO_PULL_DOWN: ++ pull_up &= ~(1 << off); ++ pull_down |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_NONE: ++ pull_up &= ~(1 << off); ++ pull_down &= ~(1 << off); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(pull_up, base + IPROC_GPIO_CCA_PULL_UP); ++ writel_relaxed(pull_down, base + IPROC_GPIO_CCA_PULL_DOWN); ++ } ++ ++ return 0; ++} ++ ++ ++iproc_gpio_pull_t iproc_gpio_getpull_updown_cca(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ ++ unsigned int base; ++ base = 0; ++ ++ if (chip->id == IPROC_GPIO_CCA_ID) { ++ unsigned long pull_up, pull_down; ++ ++ base = (unsigned int)chip->dmu_ioaddr; ++ ++ pull_up = readl_relaxed(base + IPROC_GPIO_CCA_PULL_UP); ++ pull_down = readl_relaxed(base + IPROC_GPIO_CCA_PULL_DOWN); ++ pull_up &= 1 << off; ++ pull_down &= 1 << off; ++ ++ if (pull_up ^ pull_down) { ++ if (pull_up) { ++ return IPROC_GPIO_PULL_UP; ++ } else { ++ return IPROC_GPIO_PULL_DOWN; ++ } ++ } else if(!pull_up) { ++ return IPROC_GPIO_PULL_NONE; ++ } ++ } ++ ++ return IPROC_GPIO_PULL_NONE; ++} ++struct iproc_gpio_cfg cca_gpio_cfg = { ++ .get_pull = iproc_gpio_getpull_updown_cca, ++ .set_pull = iproc_gpio_setpull_updown_cca, ++ .get_config = iproc_gpio_get_config_cca, ++ .set_config = iproc_gpio_set_config_cca, ++}; ++#endif ++#endif /* IPROC_GPIO_CCA */ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++int iproc_gpio_set_config_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ aux_sel_reg = IPROC_GPIO_CCB_AUX_SEL; ++ base = (unsigned int)chip->ioaddr; ++ pin = 1 << off; ++ } ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ switch (cfg) { ++ case IPROC_GPIO_GENERAL: ++ aux_sel &= ~(pin); ++ break; ++ case IPROC_GPIO_AUX_FUN: ++ aux_sel |= (pin); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(aux_sel, base + aux_sel_reg); ++ ++ return 0; ++} ++ ++ ++unsigned iproc_gpio_get_config_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ unsigned long aux_sel; ++ unsigned int aux_sel_reg; ++ unsigned int base, pin; ++ ++ base = 0; ++ pin = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ aux_sel_reg = IPROC_GPIO_CCB_AUX_SEL; ++ base = (unsigned int)chip->ioaddr; ++ pin = 1 << off; ++ } ++ ++ aux_sel = readl_relaxed(base + aux_sel_reg); ++ ++ if (aux_sel & pin) { ++ return IPROC_GPIO_AUX_FUN; ++ } else { ++ return IPROC_GPIO_GENERAL; ++ } ++} ++ ++ ++int iproc_gpio_setpull_updown_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull) ++{ ++ unsigned int base; ++ base = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned long pad_res, res_en; ++ ++ base = (unsigned int)chip->ioaddr; ++ ++ pad_res = readl_relaxed(base + IPROC_GPIO_CCB_PAD_RES); ++ res_en = readl_relaxed(base + IPROC_GPIO_CCB_RES_EN); ++ switch (pull) { ++ case IPROC_GPIO_PULL_UP: ++ pad_res |= (1 << off); ++ res_en |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_DOWN: ++ pad_res &= ~(1 << off); ++ res_en |= (1 << off); ++ break; ++ case IPROC_GPIO_PULL_NONE: ++ res_en &= ~(1 << off); ++ break; ++ default: ++ return -EINVAL; ++ } ++ writel_relaxed(pad_res, base + IPROC_GPIO_CCB_PAD_RES); ++ writel_relaxed(res_en, base + IPROC_GPIO_CCB_RES_EN); ++ } ++ return 0; ++} ++ ++ ++iproc_gpio_pull_t iproc_gpio_getpull_updown_ccb(struct iproc_gpio_chip *chip, ++ unsigned int off) ++{ ++ ++ unsigned int base; ++ base = 0; ++ ++ if ((chip->id == IPROC_GPIO_CCB_ID) || (chip->id == IPROC_GPIO_CCG_ID)) { ++ unsigned long pad_res, res_en; ++ ++ base = (unsigned int)chip->ioaddr; ++ ++ pad_res = readl_relaxed(base + IPROC_GPIO_CCB_PAD_RES); ++ res_en = readl_relaxed(base + IPROC_GPIO_CCB_RES_EN); ++ pad_res &= 1 << off; ++ res_en &= 1 << off; ++ ++ if (res_en) { ++ if (pad_res) { ++ return IPROC_GPIO_PULL_UP; ++ } else { ++ return IPROC_GPIO_PULL_DOWN; ++ } ++ } else { ++ return IPROC_GPIO_PULL_NONE; ++ } ++ } ++ return IPROC_GPIO_PULL_NONE; ++} ++ ++struct iproc_gpio_cfg ccb_gpio_cfg = { ++ .get_pull = iproc_gpio_getpull_updown_ccb, ++ .set_pull = iproc_gpio_setpull_updown_ccb, ++ .get_config = iproc_gpio_get_config_ccb, ++ .set_config = iproc_gpio_set_config_ccb, ++}; ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG */ ++ ++iproc_gpio_pull_t iproc_gpio_getpull(unsigned int pin) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset, ret = -EINVAL; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->get_pull)(chip, offset); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(iproc_gpio_getpull); ++ ++ ++int iproc_gpio_setpull(unsigned int pin, iproc_gpio_pull_t pull) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset, ret = -EINVAL; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->set_pull)(chip, offset, pull); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(iproc_gpio_setpull); ++ ++unsigned iproc_gpio_getcfg(unsigned int pin) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset; ++ unsigned ret = 0; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ ret = (chip->config->get_config)(chip, offset); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++} ++ ++EXPORT_SYMBOL(iproc_gpio_getcfg); ++ ++int iproc_gpio_cfgpin(unsigned int pin, unsigned int config) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpiolib_getchip(pin); ++ unsigned long flags; ++ int offset; ++ int ret = 0; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ offset = pin - chip->chip.base; ++ offset += chip->pin_offset; ++ iproc_gpio_lock(chip, flags); ++ if (chip->config){ ++ (chip->config->set_config)(chip, offset, config); ++ } ++ iproc_gpio_unlock(chip, flags); ++ ++ return ret; ++ ++ ++} ++EXPORT_SYMBOL(iproc_gpio_cfgpin); +diff --git a/drivers/bcmdrivers/gpio/gpio_cfg.h b/drivers/bcmdrivers/gpio/gpio_cfg.h +new file mode 100644 +index 0000000..126a7fb +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpio_cfg.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef __PLAT_GPIO_CFG_H ++#define __PLAT_GPIO_CFG_H ++ ++typedef unsigned int __bitwise__ iproc_gpio_pull_t; ++typedef unsigned int __bitwise__ iproc_gpio_drvstr_t; ++ ++struct iproc_gpio_chip; ++ ++struct iproc_gpio_cfg { ++ iproc_gpio_pull_t (*get_pull)(struct iproc_gpio_chip *chip, unsigned int offs); ++ int (*set_pull)(struct iproc_gpio_chip *chip, unsigned int offs, ++ iproc_gpio_pull_t pull); ++ unsigned (*get_config)(struct iproc_gpio_chip *chip, unsigned int offs); ++ int (*set_config)(struct iproc_gpio_chip *chip, unsigned int offs, ++ unsigned int config); ++}; ++ ++ ++/** ++ * iproc_gpio_cfgpin() - Change the GPIO function of a pin. ++ * @pin pin The pin number to configure. ++ * @to to The configuration (IPROC_GPIO_GENERAL/ IPROC_GPIO_AUX_FUN) for the pin's function. ++ * ++ */ ++ ++extern int iproc_gpio_cfgpin(unsigned int pin, unsigned int to); ++ ++ ++/** ++ * iproc_gpio_getcfg - Read the current function for a GPIO pin ++ * @pin: The pin to read the configuration value for. ++ * ++ * Read the configuration state of the given @pin, returning a value that ++ * could be passed back to iproc_gpio_cfgpin(). ++ * ++ * ++ */ ++extern unsigned iproc_gpio_getcfg(unsigned int pin); ++ ++#define IPROC_GPIO_GENERAL 0 ++#define IPROC_GPIO_AUX_FUN 1 ++ ++ ++/* Define values for the pull-{up,down} available for each gpio pin. ++ * ++ * These values control the state of the weak pull-{up,down} resistors. ++ */ ++#define IPROC_GPIO_PULL_NONE ((__force iproc_gpio_pull_t)0x00) ++#define IPROC_GPIO_PULL_DOWN ((__force iproc_gpio_pull_t)0x01) ++#define IPROC_GPIO_PULL_UP ((__force iproc_gpio_pull_t)0x02) ++ ++ ++ ++ ++/** ++ * iproc_gpio_setpull() - set the state of a gpio pin pull resistor ++ * @pin: The pin number to configure the pull resistor. ++ * @pull: The configuration for the pull resistor. ++ * ++ * This function sets the state of the pull-{up,down} resistor for the ++ * specified pin. It will return 0 if successfull, or a negative error ++ * code if the pin cannot support the requested pull setting. ++ * ++ * @pull is one of IPROC_GPIO_PULL_NONE, IPROC_GPIO_PULL_DOWN or IPROC_GPIO_PULL_UP. ++*/ ++extern int iproc_gpio_setpull(unsigned int pin, iproc_gpio_pull_t pull); ++ ++ ++/** ++ * iproc_gpio_getpull() - get the pull resistor state of a gpio pin ++ * @pin: The pin number to get the settings for ++ * ++ * Read the pull resistor value for the specified pin. ++*/ ++extern iproc_gpio_pull_t iproc_gpio_getpull(unsigned int pin); ++ ++/* internal gpio functions */ ++extern int iproc_gpio_setpull_updown(struct iproc_gpio_chip *chip, ++ unsigned int off, iproc_gpio_pull_t pull); ++ ++extern iproc_gpio_pull_t iproc_gpio_getpull_updown(struct iproc_gpio_chip *chip, ++ unsigned int off); ++ ++extern int iproc_gpio_set_config(struct iproc_gpio_chip *chip, ++ unsigned int off, unsigned int cfg); ++ ++unsigned iproc_gpio_get_config(struct iproc_gpio_chip *chip, ++ unsigned int off); ++ ++#endif +diff --git a/drivers/bcmdrivers/gpio/gpiolib.c b/drivers/bcmdrivers/gpio/gpiolib.c +new file mode 100644 +index 0000000..6348974 +--- /dev/null ++++ b/drivers/bcmdrivers/gpio/gpiolib.c +@@ -0,0 +1,259 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "gpio.h" ++#include "gpio_cfg.h" ++ ++ ++#if defined(IPROC_GPIO_CCA) ++ ++extern struct iproc_gpio_irqcfg cca_gpio_irqcfg; ++ ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ ++extern struct iproc_gpio_cfg cca_gpio_cfg; ++ ++#endif /*CONFIG_MACH_NS || CONFIG_MACH_NSP */ ++ ++static struct resource iproc_gpio_cca_config_resource[] = { ++ [0] = { ++ .start = IPROC_CCA_BASE, ++ .end = IPROC_CCA_BASE + IPROC_GPIO_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "intr", ++ }, ++#if (defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP)) ++ [1] = { ++ .start = IPROC_DMU_BASE, ++ .end = IPROC_DMU_BASE + 0x200 - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "dmu", ++ }, ++#else ++ [1] = {.name = "",}, ++#endif ++}; ++ ++#endif /* IPROC_GPIO_CCA */ ++ ++ ++#if defined(IPROC_GPIO_CCB) || defined(IPROC_GPIO_CCG) ++ ++extern struct iproc_gpio_irqcfg ccb_gpio_irqcfg; ++extern struct iproc_gpio_cfg ccb_gpio_cfg; ++ ++#endif /* IPROC_GPIO_CCB || IPROC_GPIO_CCG */ ++ ++ ++#if defined(IPROC_GPIO_CCG) ++static struct resource iproc_gpio_resources[] = { ++ [0] = { ++ .start = IPROC_GPIO_CCG_BASE, ++ .end = IPROC_GPIO_CCG_BASE + IPROC_GPIO_REG_SIZE -1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++#else ++static struct resource iproc_gpio_resources[] = { ++ [0] = { ++ .start = IPROC_GPIO_CCA_BASE, ++ .end = IPROC_GPIO_CCA_BASE + IPROC_GPIO_REG_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ .child = iproc_gpio_cca_config_resource, ++ }, ++ [1] = { ++ .start = IPROC_GPIO_CCB_BASE, ++ .end = IPROC_GPIO_CCB_BASE + IPROC_GPIO_REG_SIZE -1, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++#endif ++ ++#if defined(CONFIG_MACH_NS) || defined(CONFIG_MACH_NSP) ++ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .config = &cca_gpio_cfg, ++ .chip = { ++ .base = 0, ++ .label = "GPIOA", ++ .ngpio = 24, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++/* CONFIG_MACH_NS */ ++#elif defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54) ++/* ++ * Chip level GPIO 0-3 from CMICD, ++ * GPIO 4-11 from ChipcommonA gpio pin 0 - 7 ++ * Hence the base is 4 and the number is 8. ++ */ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 4, ++ .label = "GPIOA", ++ .ngpio = 8, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#elif defined(CONFIG_MACH_HR2) ++/* ++ * Chip level GPIO 0-3 from CMICD, ++ * GPIO 4-15 are from ChipcommonA gpio pin 0 - 11 ++ * where GPIO 8-15 are shared with MII or LED depends on strap pin ++ * Hence the base is 4 and the number is 12. ++ */ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 4, ++ .label = "GPIOA", ++ .ngpio = 12, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#elif defined(CONFIG_MACH_GH) ++/* ++* Chip level GPIO 0-3 from CMICD, ++* GPIO 4-15 are from ChipcommonG gpio pin 4 - 15 ++*/ ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCG_ID, ++ .config = &ccb_gpio_cfg, ++ .chip = { ++ .base = 4, ++ .label = "GPIOG", ++ .ngpio = 12, ++ }, ++ .irq_base = IPROC_GPIO_CCG_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCG_INT, ++ .irqcfg = &ccb_gpio_irqcfg, ++ .pin_offset = 4, ++ }, ++}; ++#else ++struct iproc_gpio_chip iproc_gpios_config[] = { ++ [0] = { ++ .id = IPROC_GPIO_CCA_ID, ++ .chip = { ++ .base = 0, ++ .label = "GPIOA", ++ .ngpio = 32, ++ }, ++ .irq_base = IPROC_GPIO_CCA_IRQ_BASE, ++ .resource = &iproc_gpio_resources[0], ++ .irq = IPROC_GPIO_CCA_INT, ++ .irqcfg = &cca_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++ [1] = { ++ .id = IPROC_GPIO_CCB_ID, ++ .chip = { ++ .base = -EINVAL, ++ .label = "GPIOB", ++ .ngpio = 4, ++ }, ++ .irq_base = IPROC_GPIO_CCB_IRQ_BASE, ++ .resource = &iproc_gpio_resources[1], ++ .irq = IPROC_GPIO_CCB_INT, ++ .irqcfg = &ccb_gpio_irqcfg, ++ .pin_offset = 0, ++ }, ++}; ++#endif ++ ++int iproc_gpiolib_init(void) ++{ ++ struct iproc_gpio_chip *chip = iproc_gpios_config; ++ int gpn; ++ int temp_base; ++ ++#if defined(CONFIG_MACH_NS) ++ /* bcm53012 support 24 gpios; bcm53010/53011 support 16 gpios */ ++ if ((__REG32(IPROC_IDM_REGISTER_VA + 0xd500) & 0xc) != 0x0) { ++ iproc_gpios_config[0].chip.ngpio = 16; ++ } ++#endif ++#if defined(CONFIG_MACH_NSP) ++ /* bcm53025 support 32 gpios; bcm53022/53023 support 24 gpios */ ++ reg32_write((volatile uint32_t *)(IPROC_PCIE_AXIB0_REG_VA + PAXB_0_CONFIG_IND_ADDR_BASE), 0); ++ ++/* ++ the mechanism to get the chip number does not work, always reads 22K. ++ OTP must be programmed and then need to look at OTP ++ for now assume 25K chip ++ ++ if ((__REG32(IPROC_PCIE_AXIB0_REG_VA + PAXB_0_CONFIG_IND_DATA_BASE) ++ & 0xffff0000) == 0x80250000) { ++*/ ++ if (1) { ++ iproc_gpios_config[0].chip.ngpio = 32; ++ } ++#endif ++ ++ ++ temp_base = 0; ++ for (gpn = 0; gpn < ARRAY_SIZE(iproc_gpios_config); gpn++, chip++) { ++ if (gpn >= MAX_NS_GPIO){ ++ printk("Unavailabe to add gpiolib\n"); ++ return -EINVAL; ++ } ++ ++ if (chip->chip.base == -EINVAL) { ++ chip->chip.base = temp_base; ++ } ++ ++ iproc_gpiolib_add(chip); ++ temp_base = chip->chip.base + chip->chip.ngpio; ++ } ++ ++ return 0; ++} +diff --git a/drivers/bcmdrivers/include/Readme.txt b/drivers/bcmdrivers/include/Readme.txt +new file mode 100644 +index 0000000..41eb87c +--- /dev/null ++++ b/drivers/bcmdrivers/include/Readme.txt +@@ -0,0 +1 @@ ++Only shared api's or exported api's common files +diff --git a/drivers/bcmdrivers/mdio/.gitignore b/drivers/bcmdrivers/mdio/.gitignore +new file mode 100644 +index 0000000..c1e8a25 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_mdio.o.cmd ++/.iproc_mii.o.cmd ++/built-in.o ++/iproc_mdio.o ++/iproc_mii.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/mdio/Kconfig b/drivers/bcmdrivers/mdio/Kconfig +new file mode 100644 +index 0000000..3d54c81 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_MDIO ++ tristate "MDIO support" ++ depends on ARCH_IPROC ++ default n ++ help ++ MDIO support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/mdio/Makefile b/drivers/bcmdrivers/mdio/Makefile +new file mode 100644 +index 0000000..03746c7 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_MDIO) += iproc_mii.o ++iproc_mii-objs := iproc_mdio.o +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio.c b/drivers/bcmdrivers/mdio/iproc_mdio.c +new file mode 100755 +index 0000000..5ecb92e +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio.c +@@ -0,0 +1,585 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include "iproc_mdio.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "iproc_mdio_dev.h" ++ ++static void * baseAddr; ++ ++#define R_REG(reg) ioread32(baseAddr + (reg&0x0fff)) ++#define W_REG(reg, val) iowrite32(val, baseAddr + (reg&0x0fff)) ++ ++#define MII_ERR_VAL 0x0001 ++#define MII_MSG_VAL 0x0002 ++#define MII_DBG_VAL 0x0004 ++//static u32 mii_msg_level = MII_ERR_VAL; ++ ++#if defined(BCMDBG) || defined(BCMDBG_ERR) ++#define MII_ERR(args) do {if (mii_msg_level & MII_ERR_VAL) printk args;} while (0) ++#else ++#define MII_ERR(args) ++#endif ++ ++#ifdef BCMDBG ++#define MII_MSG(args) do {if (mii_msg_level & MII_MSG_VAL) printk args;} while (0) ++#define MII_DBG(args) do {if (mii_msg_level & MII_DBG_VAL) printk args;} while (0) ++#else ++#define MII_MSG(args) ++#define MII_DBG(args) ++#endif ++ ++#define MII_EN_CHK \ ++ {\ ++ if (!baseAddr) { \ ++ return MII_ERR_INIT; \ ++ } \ ++ if (!(R_REG(MII_MGMT) & 0x7f)) { \ ++ return MII_ERR_INTERNAL; \ ++ } \ ++ } ++ ++#define MII_TRIES 100000 ++#define MII_POLL_USEC 20 ++ ++struct mdio_device_data { ++ mdio_info_t *mdio; ++ int init; ++}; ++ ++static struct mdio_device_data mdio_devices={0}; ++ ++#define DRIVER_VERSION "0.01" ++#define DRIVER_NAME "iproc mdio" ++ ++static int mdio_major; ++static struct cdev mdio_cdev; ++ ++#define MDIO_IOC_OP_EXTERNAL_READ 0 ++#define MDIO_IOC_OP_EXTERNAL_WRITE 1 ++#define MDIO_IOC_OP_LOCAL_READ 2 ++#define MDIO_IOC_OP_LOCAL_WRITE 3 ++ ++/* Function : ccb_mii_read ++ * - Read operation. ++ * Return : ++ * Note : ++ */ ++int ++ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data) ++{ ++ int i; ++ uint32_t ctrl = 0; ++ unsigned long flags; ++ mdio_info_t *mdio = NULL; ++ ++ MII_EN_CHK; ++ ++ mdio = mdio_devices.mdio; ++ ++ spin_lock_irqsave(&mdio->lock, flags); ++ ++ ctrl = R_REG(MII_MGMT); ++ if (dev_type == MII_DEV_LOCAL) { ++ ctrl &= ~MII_MGMT_EXP_MASK; ++ } else { ++ ctrl |= MII_MGMT_EXP_MASK; ++ } ++ W_REG(MII_MGMT, ctrl); ++ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = ((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | ++ ((2 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | ++ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | ++ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | ++ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK); ++ W_REG(MII_CMD_DATA, ctrl); ++ MII_DBG(("MII READ: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); ++ ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = R_REG(MII_CMD_DATA); ++ ++ MII_DBG(("MDIO READ: addr=%x off=%x value=%x\n", phy_addr, reg_off, ctrl)); ++ ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ ++ *data = (ctrl & 0xffff); ++ return 0; ++} ++ ++/* Function : ccb_mii_write ++ * - Write operation. ++ * Return : ++ * Note : ++ */ ++int ++ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data) ++{ ++ int i; ++ uint32_t ctrl = 0; ++ unsigned long flags; ++ mdio_info_t *mdio = NULL; ++ ++ MII_DBG(("MDIO WRITE: addr=%x off=%x\n", phy_addr, reg_off)); ++ ++ MII_EN_CHK; ++ ++ mdio = mdio_devices.mdio; ++ ++ spin_lock_irqsave(&mdio->lock, flags); ++ ++ ctrl = R_REG(MII_MGMT); ++ if (dev_type == MII_DEV_LOCAL) { ++ ctrl &= ~MII_MGMT_EXP_MASK; ++ } else { ++ ctrl |= MII_MGMT_EXP_MASK; ++ } ++ W_REG(MII_MGMT, ctrl); ++ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_MGMT, ctrl)); ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ ctrl = ((1 << MII_CMD_DATA_SB_SHIFT) & MII_CMD_DATA_SB_MASK) | ++ ((1 << MII_CMD_DATA_OP_SHIFT) & MII_CMD_DATA_OP_MASK) | ++ ((phy_addr << MII_CMD_DATA_PA_SHIFT) & MII_CMD_DATA_PA_MASK) | ++ ((reg_off << MII_CMD_DATA_RA_SHIFT) & MII_CMD_DATA_RA_MASK) | ++ ((2 << MII_CMD_DATA_TA_SHIFT) & MII_CMD_DATA_TA_MASK) | ++ ((data << MII_CMD_DATA_DATA_SHIFT) & MII_CMD_DATA_DATA_MASK); ++ W_REG(MII_CMD_DATA, ctrl); ++ MII_DBG(("MII WRITE: write(0x%x)=0x%x\n",MII_CMD_DATA, ctrl)); ++ ++ ++ for (i = 0; i < MII_TRIES; i++) { ++ ctrl = R_REG(MII_MGMT); ++ if (!(ctrl & MII_MGMT_BSY_MASK)) { ++ break; ++ } ++ udelay(MII_POLL_USEC); ++ } ++ if (i >= MII_TRIES) { ++ MII_ERR(("\n%s: BUSY stuck: ctrl=0x%x, count=%d\n", __FUNCTION__, ctrl, i)); ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ return -1; ++ } ++ ++ spin_unlock_irqrestore(&mdio->lock, flags); ++ ++ return MII_ERR_NONE; ++} ++ ++/* Function : ccb_mii_freq_set ++ * - Set MII management interface frequency. ++ * Return : ++ * Note : ++ * ++ */ ++int ++ccb_mii_freq_set(int speed_khz) ++{ ++ int rv = MII_ERR_NONE; ++ uint32_t divider = 0; ++ uint32_t mgmt = 0; ++ ++ MII_DBG(("MDIO FREQ SET: %d KHz\n", speed_khz)); ++ ++ /* host clock 66MHz device value the MDCDIV field */ ++ /* resultant MDIO clock should not exceed 2.5MHz */ ++ ++ if (speed_khz > 2560) { ++ MII_ERR(("\n%s: Maximum MDIO frequency is 2.5MHz\n", __FUNCTION__)); ++ return MII_ERR_PARAM; ++ } ++ ++ divider = 67584 / speed_khz; ++ divider = (divider & MII_MGMT_MDCDIV_MASK); ++ if (divider > 0x7f) { ++ /* make sure the minimum configurable frequency */ ++ divider = 0x7f; ++ } ++ mgmt = R_REG(MII_MGMT); ++ mgmt &= ~MII_MGMT_MDCDIV_MASK; ++ mgmt |= divider; ++ ++ W_REG(MII_MGMT, mgmt); ++ MII_DBG(("MII FREQ(%d KHz): write(0x%x)=0x%x\n",speed_khz, MII_MGMT, mgmt)); ++ ++ return rv; ++} ++ ++static void __maybe_unused ++_dump_devs(void) ++{ ++// int r; ++// int addr, off; ++ int addr; ++ int phyid1, phyid2; ++ int cnt = 0; ++ int found = 0; ++ ++ for (addr = 0; addr <= 0x1f; addr++) { ++ ccb_mii_read(MII_DEV_LOCAL, addr, 2, (uint16_t *)&phyid1); ++ ccb_mii_read(MII_DEV_LOCAL, addr, 3, (uint16_t *)&phyid2); ++ found = 0; ++ if (phyid1 == 0xffff) { ++ continue; ++ } ++ ++ if ((phyid1) && (phyid2)) { ++ cnt ++; ++ found = 1; ++ } ++ if (cnt == 1) { ++ printk("Found LOCAL device(s) on MDC/MDIO interface:\n"); ++ } ++ if (found) { ++ printk("PHY address=%2d, IDs = 0x%4x 0x%4x\n", addr, phyid1, phyid2); ++ } ++ } ++ ++ cnt = 0; ++ found = 0; ++ for (addr = 0; addr <= 0x1f; addr++) { ++ ccb_mii_read(MII_DEV_EXT, addr, 2, (uint16_t *)&phyid1); ++ ccb_mii_read(MII_DEV_EXT, addr, 3, (uint16_t *)&phyid2); ++ found = 0; ++ if (phyid1 == 0xffff) { ++ continue; ++ } ++ ++ if ((phyid1) && (phyid2)) { ++ cnt ++; ++ found = 1; ++ } ++ if (cnt == 1) { ++ printk("Found EXTERNAL device(s) on MDC/MDIO interface:\n"); ++ } ++ if (found) { ++ printk("PHY address=%2d, IDs = 0x%4x 0x%4x\n", addr, phyid1, phyid2); ++ } ++ } ++} ++ ++static int ++mdio_open(struct inode *inode, struct file *filp) ++{ ++ filp->private_data = mdio_devices.mdio; ++ return 0; ++} ++ ++static int ++mdio_release(struct inode *inode, struct file *filp) ++{ ++ ++ return 0; ++} ++ ++static int mdio_message(mdio_info_t *mdio, ++ struct mdio_ioc_transfer *u_xfers, unsigned n_xfers, int op) ++{ ++ ++ uint8_t pa, ra; ++ uint16_t regval; ++ ++ pa = u_xfers->pa; ++ ra = u_xfers->ra; ++ ++ MII_DBG(("mdio_message: op = %d\n", op)); ++ ++ if(op == MDIO_IOC_OP_LOCAL_READ) { ++ ccb_mii_read(MII_DEV_LOCAL, pa, ra, ®val); ++ u_xfers->rx_buf = regval; ++ } ++ ++ if(op == MDIO_IOC_OP_LOCAL_WRITE) { ++ ccb_mii_write(MII_DEV_LOCAL, pa, ra, u_xfers->tx_buf); ++ } ++ ++ if(op == MDIO_IOC_OP_EXTERNAL_READ) { ++ ccb_mii_read(MII_DEV_EXT, pa, ra, ®val); ++ u_xfers->rx_buf = regval; ++ } ++ ++ if(op == MDIO_IOC_OP_EXTERNAL_WRITE) { ++ ccb_mii_write(MII_DEV_EXT, pa, ra, u_xfers->tx_buf); ++ } ++ return 0; ++} ++ ++static long ++mdio_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ int err = 0; ++ int retval = 0; ++ int ioc_op = 0; ++ uint32_t tmp; ++ unsigned n_ioc; ++ struct mdio_ioc_transfer *ioc, *uf; ++ mdio_info_t *mdio; ++ ++ MII_DBG(("mdio_ioctl: cmd = %d\n", cmd)); ++ ++ /* Check type and command number */ ++ if (_IOC_TYPE(cmd) != MDIO_IOC_MAGIC){ ++ return -ENOTTY; ++ } ++ ++ /* Check access direction once here; don't repeat below. ++ * IOC_DIR is from the user perspective, while access_ok is ++ * from the kernel perspective; so they look reversed. ++ */ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ err = !access_ok(VERIFY_WRITE, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) ++ err = !access_ok(VERIFY_READ, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err) ++ return -EFAULT; ++ ++ mdio = (mdio_info_t *)filp->private_data; ++ ++ switch (cmd) { ++ ++ case MDIO_IOC_EXTERNAL_R_REG: ++ ioc_op = MDIO_IOC_OP_EXTERNAL_READ; ++ break; ++ case MDIO_IOC_EXTERNAL_W_REG: ++ ioc_op = MDIO_IOC_OP_EXTERNAL_WRITE; ++ break; ++ case MDIO_IOC_LOCAL_R_REG: ++ ioc_op = MDIO_IOC_OP_LOCAL_READ; ++ break; ++ case MDIO_IOC_LOCAL_W_REG: ++ ioc_op = MDIO_IOC_OP_LOCAL_WRITE; ++ break; ++ } ++ ++ tmp = _IOC_SIZE(cmd); ++ if ((tmp % sizeof(struct mdio_ioc_transfer)) != 0) { ++ retval = -EINVAL; ++ return retval; ++ } ++ n_ioc = tmp / sizeof(struct mdio_ioc_transfer); ++ if (n_ioc == 0) ++ return 0; ++ ++ /* copy into scratch area */ ++ ioc = kmalloc(tmp, GFP_KERNEL); ++ if (!ioc) { ++ retval = -ENOMEM; ++ return retval; ++ } ++ if (__copy_from_user(ioc, (void __user *)arg, tmp)) { ++ kfree(ioc); ++ retval = -EFAULT; ++ return retval; ++ } ++ /* translate to mdio_message, execute */ ++ retval = mdio_message(mdio, ioc, n_ioc, ioc_op); ++ ++ if ((ioc_op == MDIO_IOC_OP_EXTERNAL_READ) || (ioc_op == MDIO_IOC_OP_LOCAL_READ)) { ++ ++ uf = (struct mdio_ioc_transfer *)arg; ++ if (__copy_to_user((u8 __user *)&uf->rx_buf, (uint8_t *)&ioc->rx_buf, 2)) { ++ kfree(ioc); ++ retval = -EFAULT; ++ return retval; ++ } ++ } ++ kfree(ioc); ++ ++ return 0; ++} ++ ++static const struct file_operations mdio_fops = { ++ .open = mdio_open, ++ .release = mdio_release, ++ .unlocked_ioctl = mdio_ioctl, ++ .owner = THIS_MODULE, ++}; ++ ++static int _mdio_handler_init(mdio_info_t **mdio) ++{ ++ *mdio = kmalloc(sizeof(mdio_info_t), GFP_KERNEL); ++ if (*mdio == NULL) { ++ MII_ERR(("mdio_init: out of memory\n")); ++ return -ENOMEM; ++ } ++ memset(*mdio, 0, sizeof(mdio_info_t)); ++ ++ /* Initialize lock */ ++ spin_lock_init(&(*mdio)->lock); ++ ++ ++ mdio_devices.mdio = *mdio; ++ mdio_devices.init = 1; ++ ++ return 0; ++} ++ ++/* Function : ccb_mii_init ++ * - Init Northstar CCB MII management interface. ++ * Return : ++ * Note : ++ * ++ */ ++int ++ccb_mii_init(void) ++{ ++ int ret = -ENODEV; ++ dev_t mdio_dev; ++ mdio_info_t *mdio=NULL; ++ ++ _mdio_handler_init(&mdio); ++ ++ /* Get register base address */ ++ baseAddr = ioremap(IPROC_CCB_MDIO_REG_BASE, 0x1000); ++ MII_DBG(("MDIO INIT: baseAddr %x\n",baseAddr)); ++ ++ /* Set preamble */ ++ W_REG(MII_MGMT, MII_MGMT_PRE_MASK); ++ /* Set the MII default clock 1MHz */ ++ ccb_mii_freq_set(1024); ++ ++// _dump_devs(); ++ ++ if(mdio_devices.init != 1) { ++ return -ENOMEM; ++ } ++ mdio = mdio_devices.mdio; ++ ++ if (mdio_major) { ++ mdio_dev = MKDEV(mdio_major, 0); ++ ret = register_chrdev_region(mdio_dev, ++ 1, "mdio"); ++ } else { ++ ret = alloc_chrdev_region(&mdio_dev, 0, ++ 1, "mdio"); ++ mdio_major = MAJOR(mdio_dev); ++ } ++ ++ if (ret) { ++ goto error; ++ } ++ cdev_init(&mdio_cdev, &mdio_fops); ++ ret = cdev_add(&mdio_cdev, mdio_dev, 1); ++ if (ret) { ++ printk(KERN_ERR "Fail to add mdio char dev!\n"); ++ goto error_region; ++ } ++ ++ return 0; ++ ++error_region: ++ unregister_chrdev_region(mdio_dev, 1); ++error: ++ kfree(mdio); ++ return ret; ++} ++ ++void ++ccb_mii_exit(void) ++{ ++ mdio_info_t *mdio=NULL; ++ ++ /* Get register base address */ ++ if (baseAddr) { ++ iounmap(baseAddr); ++ baseAddr = NULL; ++ } ++ ++ mdio = mdio_devices.mdio; ++ kfree(mdio); ++ ++ mdio_devices.mdio = NULL; ++ mdio_devices.init = 0; ++ unregister_chrdev_region(MKDEV(mdio_major, 0), 1); ++ ++} ++ ++module_init(ccb_mii_init); ++module_exit(ccb_mii_exit); ++ ++EXPORT_SYMBOL(ccb_mii_init); ++EXPORT_SYMBOL(ccb_mii_freq_set); ++EXPORT_SYMBOL(ccb_mii_read); ++EXPORT_SYMBOL(ccb_mii_write); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("BCM5301X MDIO Device Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio.h b/drivers/bcmdrivers/mdio/iproc_mdio.h +new file mode 100755 +index 0000000..2356ce6 +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _bcm5301x_ccb_mii_h_ ++#define _bcm5301x_ccb_mii_h_ ++ ++#include ++ ++typedef struct _mdio_info_s { ++ void *h; /* dev handle */ ++ spinlock_t lock; ++} mdio_info_t; ++ ++/* reutrn value for MII driver */ ++#define MII_ERR_NONE 0 ++#define MII_ERR_TIMEOUT -1 ++#define MII_ERR_INTERNAL -2 ++#define MII_ERR_PARAM -3 ++#define MII_ERR_UNAVAIL -4 ++#define MII_ERR_UNKNOW -5 ++#define MII_ERR_INIT -6 ++ ++/* device type */ ++#define MII_DEV_LOCAL 0 ++#define MII_DEV_EXT 1 ++ ++/* MII register definition */ ++#define MII_MGMT 0x18003000 ++#define MII_MGMT_BASE 0x000 ++#define MII_MGMT_DATAMASK 0x000007ff ++#define MII_CMD_DATA 0x18003004 ++#define MII_CMD_DATA_BASE 0x004 ++#define MII_CMD_DATA_DATAMASK 0xffffffff ++ ++/* fields in MII_MGMT */ ++#define MII_MGMT_BYP_MASK 0x00000400 ++#define MII_MGMT_BYP_SHIFT 10 ++#define MII_MGMT_EXP_MASK 0x00000200 ++#define MII_MGMT_EXP_SHIFT 9 ++#define MII_MGMT_BSY_MASK 0x00000100 ++#define MII_MGMT_BSY_SHIFT 8 ++#define MII_MGMT_PRE_MASK 0x00000080 ++#define MII_MGMT_PRE_SHIFT 7 ++#define MII_MGMT_MDCDIV_MASK 0x0000007f ++#define MII_MGMT_MDCDIV_SHIFT 0 ++/* fields in MII_CMD_DATA */ ++#define MII_CMD_DATA_SB_MASK 0xc0000000 ++#define MII_CMD_DATA_SB_SHIFT 30 ++#define MII_CMD_DATA_OP_MASK 0x30000000 ++#define MII_CMD_DATA_OP_SHIFT 28 ++#define MII_CMD_DATA_PA_MASK 0x0f800000 ++#define MII_CMD_DATA_PA_SHIFT 23 ++#define MII_CMD_DATA_RA_MASK 0x007c0000 ++#define MII_CMD_DATA_RA_SHIFT 18 ++#define MII_CMD_DATA_TA_MASK 0x00030000 ++#define MII_CMD_DATA_TA_SHIFT 16 ++#define MII_CMD_DATA_DATA_MASK 0x0000ffff ++#define MII_CMD_DATA_DATA_SHIFT 0 ++ ++ ++/* external functions for SPI driver */ ++extern int ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16_t *data); ++extern int ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16_t data); ++ ++extern int ccb_mii_freq_set(int speed_khz); ++extern int ccb_mii_init(void); ++ ++#endif /* _bcm5301x_ccb_mii_h_ */ +diff --git a/drivers/bcmdrivers/mdio/iproc_mdio_dev.h b/drivers/bcmdrivers/mdio/iproc_mdio_dev.h +new file mode 100755 +index 0000000..fcf080a +--- /dev/null ++++ b/drivers/bcmdrivers/mdio/iproc_mdio_dev.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#ifndef _IPROC_MDIO_DEV_H ++#define _IPROC_MDIO_DEV_H ++ ++/* IOCTL commands */ ++ ++#define MDIO_IOC_MAGIC 'm' ++ ++struct mdio_ioc_transfer { ++ uint8_t pa; /* phy address */ ++ uint8_t ra; /* register address */ ++ uint16_t tx_buf; ++ uint16_t rx_buf; ++}; ++ ++#define MDIO_MSGSIZE(N) \ ++ ((((N)*(sizeof (struct mdio_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ ++ ? ((N)*(sizeof (struct mdio_ioc_transfer))) : 0) ++ ++#define MDIO_IOC_MESSAGE(N) _IOW(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(N)]) ++ ++#define MDIO_IOC_EXTERNAL_R_REG _IOWR(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_EXTERNAL_W_REG _IOW(MDIO_IOC_MAGIC, 1, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_LOCAL_R_REG _IOWR(MDIO_IOC_MAGIC, 2, char[MDIO_MSGSIZE(1)]) ++#define MDIO_IOC_LOCAL_W_REG _IOW(MDIO_IOC_MAGIC, 3, char[MDIO_MSGSIZE(1)]) ++ ++ ++#endif +diff --git a/drivers/bcmdrivers/nand/.gitignore b/drivers/bcmdrivers/nand/.gitignore +new file mode 100644 +index 0000000..26ea8be +--- /dev/null ++++ b/drivers/bcmdrivers/nand/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order ++/.iproc_mtd_nand.o.cmd ++/.nand_iproc.o.cmd ++/iproc_mtd_nand.o ++/nand_iproc.o +diff --git a/drivers/bcmdrivers/nand/Kconfig b/drivers/bcmdrivers/nand/Kconfig +new file mode 100644 +index 0000000..1cd1050 +--- /dev/null ++++ b/drivers/bcmdrivers/nand/Kconfig +@@ -0,0 +1,24 @@ ++menuconfig IPROC_MTD_NAND ++ tristate "NAND support" ++ depends on ARCH_IPROC ++ select MTD ++ select MTD_NAND ++ default n ++ help ++ This selects a driver for the iProc NAND Controller. ++ ++ If unsure, say N. ++ ++if IPROC_MTD_NAND ++ ++config IPROC_MTD_NAND_USE_JFFS2 ++ bool "Use JFFS2 on NAND" ++ default n ++ help ++ Enable this if JFFS2 will be used on NAND. This is to solve compatibility ++ issue for the NAND controller to work with JFFS2 (with some performance ++ degrade). ++ ++ If unsure, say N. ++ ++endif # IPROC_MTD_NAND +diff --git a/drivers/bcmdrivers/nand/Makefile b/drivers/bcmdrivers/nand/Makefile +new file mode 100644 +index 0000000..5d2b01d +--- /dev/null ++++ b/drivers/bcmdrivers/nand/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_IPROC_MTD_NAND) += iproc_mtd_nand.o ++iproc_mtd_nand-objs := nand_iproc.o +diff --git a/drivers/bcmdrivers/nand/nand_iproc.c b/drivers/bcmdrivers/nand/nand_iproc.c +new file mode 100644 +index 0000000..f4b5d90 +--- /dev/null ++++ b/drivers/bcmdrivers/nand/nand_iproc.c +@@ -0,0 +1,1733 @@ ++ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../../mtd/mtdcore.h" ++ ++/* ++ * Current version of NAND controller includes spare area for ECC calculation. ++ * This is not what some file system (eg. JFFS2) expects because they could ++ * write OOB first and data later. Thus we need to do some special handling. ++ */ ++#ifdef CONFIG_IPROC_MTD_NAND_USE_JFFS2 ++#define NAND_MTD_WRITE_OOB_SEPARATELY ++#endif /* CONFIG_IPROC_MTD_NAND_USE_JFFS2 */ ++#define NAND_REPORT_ECC_UNCORR_ERRORS ++ ++/* ++ * This flag controls if WP stays on between erase/write ++ * commands to mitigate flash corruption due to power glitches. Values: ++ * 0: NAND_WP is not used or not available ++ * 1: NAND_WP is set by default, cleared for erase/write operations ++ * 2: NAND_WP is always cleared ++ */ ++static int wp_on = 1; ++module_param(wp_on, int, 0444); ++ ++/*********************************************************************** ++ * Definitions ++ ***********************************************************************/ ++ ++#ifdef IPROC_NAND_DEBUG ++#define DBG(args...) printk(args) ++#else ++#define DBG(args...) do { } while(0) ++#endif ++ ++/* ++ * Controller/driver specific ++ */ ++#define DRV_NAME "nand_iproc" ++#define MAX_CONTROLLER_OOB 64 ++ ++/* ++ * NAND flash commands ++ */ ++#define CMD_PAGE_READ 0x01 ++#define CMD_SPARE_AREA_READ 0x02 ++#define CMD_STATUS_READ 0x03 ++#define CMD_PROGRAM_PAGE 0x04 ++#define CMD_PROGRAM_SPARE_AREA 0x05 ++#define CMD_COPY_BACK 0x06 ++#define CMD_DEVICE_ID_READ 0x07 ++#define CMD_BLOCK_ERASE 0x08 ++#define CMD_FLASH_RESET 0x09 ++#define CMD_BLOCKS_LOCK 0x0a ++#define CMD_BLOCKS_LOCK_DOWN 0x0b ++#define CMD_BLOCKS_UNLOCK 0x0c ++#define CMD_READ_BLOCKS_LOCK_STATUS 0x0d ++#define CMD_PARAMETER_READ 0x0e ++#define CMD_PARAMETER_CHANGE_COL 0x0f ++#define CMD_LOW_LEVEL_OP 0x10 ++ ++/* ++ * NAND controller register offset ++ */ ++#define NCREG_REVISION 0x000 /* Revision */ ++#define NCREG_CMD_START 0x004 /* Flash Command Start */ ++#define NCREG_CMD_EXT_ADDRESS 0x008 /* Flash Command Extended Address */ ++#define NCREG_CMD_ADDRESS 0x00c /* Flash Command Address */ ++#define NCREG_CMD_END_ADDRESS 0x010 /* Flash Command End Address */ ++#define NCREG_INTFC_STATUS 0x014 /* Flash Interface Status */ ++#define NCREG_CS_NAND_SELECT 0x018 /* Flash EBI CS Select */ ++#define NCREG_CS_NAND_XOR 0x01c /* Flash EBI CS Address XOR with 1FC0 Control */ ++#define NCREG_LL_OP 0x020 /* Flash Low Level Operation */ ++#define NCREG_MPLANE_BASE_EXT_ADDRESS 0x024 /* Flash Multiplane base address */ ++#define NCREG_MPLANE_BASE_ADDRESS 0x028 /* Flash Multiplane base address */ ++#define NCREG_ACC_CONTROL_CS0 0x050 /* Flash Access Control */ ++#define NCREG_CONFIG_CS0 0x054 /* Flash Config */ ++#define NCREG_TIMING_1_CS0 0x058 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS0 0x05c /* Flash Timing Parameters 2 */ ++#define NCREG_ACC_CONTROL_CS1 0x060 /* Flash Access Control */ ++#define NCREG_CONFIG_CS1 0x064 /* Flash Config */ ++#define NCREG_TIMING_1_CS1 0x068 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS1 0x06c /* Flash Timing Parameters 2 */ ++#define NCREG_ACC_CONTROL_CS2 0x070 /* Flash Access Control */ ++#define NCREG_CONFIG_CS2 0x074 /* Flash Config */ ++#define NCREG_TIMING_1_CS2 0x078 /* Flash Timing Parameters 1 */ ++#define NCREG_TIMING_2_CS2 0x07c /* Flash Timing Parameters 2 */ ++#define NCREG_CORR_STAT_THRESHOLD 0x0c0 /* Correctable Error Reporting Threshold */ ++#define NCREG_BLK_WR_PROTECT 0x0c8 /* Block Write Protect Enable and Size for EBI_CS0b */ ++#define NCREG_MULTIPLANE_OPCODES_1 0x0cc /* Flash Multiplane Customerized Opcodes */ ++#define NCREG_MULTIPLANE_OPCODES_2 0x0d0 /* Flash Multiplane Customerized Opcodes */ ++#define NCREG_MULTIPLANE_CTRL 0x0d4 /* Flash Multiplane Control */ ++#define NCREG_UNCORR_ERROR_COUNT 0x0fc /* Read Uncorrectable Event Count */ ++#define NCREG_CORR_ERROR_COUNT 0x100 /* Read Error Count */ ++#define NCREG_READ_ERROR_COUNT 0x104 /* Read Error Count */ ++#define NCREG_BLOCK_LOCK_STATUS 0x108 /* Flash Block Lock Status */ ++#define NCREG_ECC_CORR_EXT_ADDR 0x10c /* ECC Correctable Error Extended Address */ ++#define NCREG_ECC_CORR_ADDR 0x110 /* ECC Correctable Error Address */ ++#define NCREG_ECC_UNC_EXT_ADDR 0x114 /* ECC Uncorrectable Error Extended Address */ ++#define NCREG_ECC_UNC_ADDR 0x118 /* ECC Uncorrectable Error Address */ ++#define NCREG_FLASH_READ_EXT_ADDR 0x11c /* Flash Read Data Extended Address */ ++#define NCREG_FLASH_READ_ADDR 0x120 /* Flash Read Data Address */ ++#define NCREG_PROGRAM_PAGE_EXT_ADDR 0x124 /* Page Program Extended Address */ ++#define NCREG_PROGRAM_PAGE_ADDR 0x128 /* Page Program Address */ ++#define NCREG_COPY_BACK_EXT_ADDR 0x12c /* Copy Back Extended Address */ ++#define NCREG_COPY_BACK_ADDR 0x130 /* Copy Back Address */ ++#define NCREG_BLOCK_ERASE_EXT_ADDR 0x134 /* Block Erase Extended Address */ ++#define NCREG_BLOCK_ERASE_ADDR 0x138 /* Block Erase Address */ ++#define NCREG_INV_READ_EXT_ADDR 0x13c /* Flash Invalid Data Extended Address */ ++#define NCREG_INV_READ_ADDR 0x140 /* Flash Invalid Data Address */ ++#define NCREG_INIT_STATUS 0x144 /* Initialization status */ ++#define NCREG_ONFI_STATUS 0x148 /* ONFI Status */ ++#define NCREG_ONFI_DEBUG_DATA 0x14c /* ONFI Debug Data */ ++#define NCREG_SEMAPHORE 0x150 /* Semaphore */ ++#define NCREG_FLASH_DEVICE_ID 0x194 /* Flash Device ID */ ++#define NCREG_FLASH_DEVICE_ID_EXT 0x198 /* Flash Extended Device ID */ ++#define NCREG_LL_RDDATA 0x19c /* Flash Low Level Read Data */ ++#define NCREG_SPARE_AREA_READ_OFS_0 0x200 /* Flash Spare Area Read Bytes */ ++#define NCREG_SPARE_AREA_WRITE_OFS_0 0x280 /* Flash Spare Area Write Bytes */ ++#define NCREG_FLASH_CACHE_BASE 0x400 /* Flash Cache Buffer Access */ ++ ++/* ++ * Required NAND controller register fields ++ */ ++#define NCFLD_CMD_START_OPCODE_SHIFT 24 ++#define NCFLD_INTFC_STATUS_FLASH_STATUS_MASK 0x000000FF ++#define NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG 0x40000000 ++#define NCFLD_CS_NAND_SELECT_WP 0x20000000 ++#define NCFLD_CS_NAND_SELECT_DIRECT_ACCESS_CS_MASK 0x000000FF ++#define NCFLD_CS_NAND_XOR_CS_MASK 0x000000FF ++#define NCFLD_CONFIG_CS0_BLOCK_SIZE_MASK 0x70000000 ++#define NCFLD_CONFIG_CS0_BLOCK_SIZE_SHIFT 28 ++#define NCFLD_CONFIG_CS0_DEVICE_SIZE_MASK 0x0f000000 ++#define NCFLD_CONFIG_CS0_DEVICE_SIZE_SHIFT 24 ++#define NCFLD_CONFIG_CS0_DEVICE_WIDTH_MASK 0x00800000 ++#define NCFLD_CONFIG_CS0_DEVICE_WIDTH_SHIFT 23 ++#define NCFLD_CONFIG_CS0_PAGE_SIZE_MASK 0x00300000 ++#define NCFLD_CONFIG_CS0_PAGE_SIZE_SHIFT 20 ++#define NCFLD_CONFIG_CS0_FUL_ADR_BYTES_MASK 0x00070000 ++#define NCFLD_CONFIG_CS0_FUL_ADR_BYTES_SHIFT 16 ++#define NCFLD_CONFIG_CS0_COL_ADR_BYTES_MASK 0x00007000 ++#define NCFLD_CONFIG_CS0_COL_ADR_BYTES_SHIFT 12 ++#define NCFLD_CONFIG_CS0_BLK_ADR_BYTES_MASK 0x00000700 ++#define NCFLD_CONFIG_CS0_BLK_ADR_BYTES_SHIFT 8 ++#define NCFLD_ACC_CONTROL_CS0_RD_ECC_EN_MASK 0x80000000 ++#define NCFLD_ACC_CONTROL_CS0_RD_ECC_EN_SHIFT 31 ++#define NCFLD_ACC_CONTROL_CS0_WR_ECC_EN_MASK 0x40000000 ++#define NCFLD_ACC_CONTROL_CS0_WR_ECC_EN_SHIFT 30 ++#define NCFLD_ACC_CONTROL_CS0_FAST_PGM_RDIN_MASK 0x10000000 ++#define NCFLD_ACC_CONTROL_CS0_FAST_PGM_RDIN_SHIFT 28 ++#define NCFLD_ACC_CONTROL_CS0_RD_ERASED_ECC_EN_MASK 0x08000000 ++#define NCFLD_ACC_CONTROL_CS0_RD_ERASED_ECC_EN_SHIFT 27 ++#define NCFLD_ACC_CONTROL_CS0_PARTIAL_PAGE_EN_MASK 0x04000000 ++#define NCFLD_ACC_CONTROL_CS0_PARTIAL_PAGE_EN_SHIFT 26 ++#define NCFLD_ACC_CONTROL_CS0_PAGE_HIT_EN_MASK 0x01000000 ++#define NCFLD_ACC_CONTROL_CS0_PAGE_HIT_EN_SHIFT 24 ++#define NCFLD_ACC_CONTROL_CS0_ECC_LEVEL_MASK 0x001f0000 ++#define NCFLD_ACC_CONTROL_CS0_ECC_LEVEL_SHIFT 16 ++#define NCFLD_ACC_CONTROL_CS0_SECTOR_SIZE_1K_MASK 0x00000080 ++#define NCFLD_ACC_CONTROL_CS0_SECTOR_SIZE_1K_SHIFT 7 ++#define NCFLD_ACC_CONTROL_CS0_SPARE_AREA_SIZE_MASK 0x0000007f ++#define NCFLD_ACC_CONTROL_CS0_SPARE_AREA_SIZE_SHIFT 0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS0_MASK 0x0000003f ++#define NCFLD_CORR_STAT_THRESHOLD_CS0_SHIFT 0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS1_MASK 0x00000fc0 ++#define NCFLD_CORR_STAT_THRESHOLD_CS1_SHIFT 6 ++ ++/* ++ * IDM register base (for interrupts) ++ */ ++#define IDMREG_NAND_IO_CONTROL_DIRECT 0x00000000 ++ ++/* ++ * Required IDM NAND IO Control register fields ++ */ ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_AXI_BE_MODE (1UL << 28) ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE (1UL << 24) ++#define IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT 2 ++ ++/* ++ * Interrupts ++ */ ++#define NCINTR_NP_READ 0 ++#define NCINTR_BLKERA 1 ++#define NCINTR_CPYBK 2 ++#define NCINTR_PGMPG 3 ++#define NCINTR_CTLRDY 4 ++#define NCINTR_RBPIN 5 ++#define NCINTR_UNC 6 ++#define NCINTR_CORR 7 ++ ++/* 512B flash cache in the NAND controller HW */ ++#define FC_SHIFT 9U ++#define FC_BYTES 512U ++#define FC_WORDS (FC_BYTES >> 2) ++#define FC(x) (NCREG_FLASH_CACHE_BASE + ((x) << 2)) ++ ++/* ++ * Register access macros - generic ++ */ ++#define REG_RD(ptr) readl(ptr) ++#define REG_WR(ptr, val) writel(val, ptr) ++ ++/* ++ * Register access macros - NAND flash controller ++ */ ++#define NAND_REG_RD(x) REG_RD(ctrl.nand_regs + (x)) ++#define NAND_REG_WR(x, y) \ ++ do { REG_WR(ctrl.nand_regs + (x), (y)); } while(0) ++#define NAND_REG_UNSET(x, y) \ ++ do { NAND_REG_WR((x), NAND_REG_RD(x) & ~(y)); } while(0) ++#define NAND_REG_SET(x, y) \ ++ do { NAND_REG_WR((x), NAND_REG_RD(x) | (y)); } while(0) ++#define NAND_REG_WR_RB(x, y) \ ++ do { NAND_REG_WR((x), (y)); NAND_REG_RD(x); } while(0) ++#define NAND_REG_SET_RB(x, y) \ ++ do { NAND_REG_SET((x), (y)); NAND_REG_RD(x); } while(0) ++#define NAND_REG_UNSET_RB(x, y) \ ++ do { NAND_REG_UNSET((x), (y)); NAND_REG_RD(x); } while(0) ++ ++/* ++ * IRQ operations ++ */ ++ ++#define NAND_ENABLE_IRQ(bit) do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) | \ ++ (1UL << ((bit) + IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT)) \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_DISABLE_IRQ(bit) do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) & \ ++ ~(1UL << ((bit) + IDMFLD_NAND_IO_CONTROL_DIRECT_IRQ_SHIFT)) \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_ACK_IRQ(bit) do { \ ++ REG_WR(((u32 *)ctrl.nand_intr_regs) + (bit), 1); \ ++ REG_RD(((u32 *)ctrl.nand_intr_regs) + (bit)); \ ++} while(0) ++ ++#define NAND_TEST_IRQ(bit) (REG_RD(((u32 *)ctrl.nand_intr_regs) + (bit)) & 1) ++ ++/* ++ * Data access macros for endianness ++ */ ++#ifdef __LITTLE_ENDIAN ++#define NAND_BEGIN_DATA_ACCESS() do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) | \ ++ IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++ ++#define NAND_END_DATA_ACCESS() do { \ ++ REG_WR(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT, \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT) & \ ++ ~IDMFLD_NAND_IO_CONTROL_DIRECT_APB_LE_MODE \ ++ ); \ ++ REG_RD(ctrl.idm_nand_regs + IDMREG_NAND_IO_CONTROL_DIRECT); \ ++} while (0) ++#else /* !__LITTLE_ENDIAN */ ++#define NAND_BEGIN_DATA_ACCESS() do { } while (0) ++#define NAND_END_DATA_ACCESS() do { } while (0) ++#endif /* !__LITTLE_ENDIAN */ ++ ++/* ++ * Misc NAND controller configuration/status macros ++ */ ++ ++#define NC_REG_CONFIG(cs) (NCREG_CONFIG_CS0 + ((cs) << 4)) ++ ++#define WR_CONFIG(cs, field, val) do { \ ++ u32 reg = NC_REG_CONFIG(cs), contents = NAND_REG_RD(reg); \ ++ contents &= ~(NCFLD_CONFIG_CS0_##field##_MASK); \ ++ contents |= (val) << NCFLD_CONFIG_CS0_##field##_SHIFT; \ ++ NAND_REG_WR(reg, contents); \ ++} while(0) ++ ++#define RD_CONFIG(cs, field) \ ++ ((NAND_REG_RD(NC_REG_CONFIG(cs)) & NCFLD_CONFIG_CS0_##field##_MASK) \ ++ >> NCFLD_CONFIG_CS0_##field##_SHIFT) ++ ++#define NC_REG_ACC_CONTROL(cs) (NCREG_ACC_CONTROL_CS0 + ((cs) << 4)) ++ ++#define WR_ACC_CONTROL(cs, field, val) do { \ ++ u32 reg = NC_REG_ACC_CONTROL(cs), contents = NAND_REG_RD(reg); \ ++ contents &= ~(NCFLD_ACC_CONTROL_CS0_##field##_MASK); \ ++ contents |= (val) << NCFLD_ACC_CONTROL_CS0_##field##_SHIFT; \ ++ NAND_REG_WR(reg, contents); \ ++} while(0) ++ ++#define RD_ACC_CONTROL(cs, field) \ ++ ((NAND_REG_RD(NC_REG_ACC_CONTROL(cs)) & \ ++ NCFLD_ACC_CONTROL_CS0_##field##_MASK) \ ++ >> NCFLD_ACC_CONTROL_CS0_##field##_SHIFT) ++ ++#define CORR_ERROR_COUNT (NAND_REG_RD(NCREG_CORR_ERROR_COUNT)) ++#define UNCORR_ERROR_COUNT (NAND_REG_RD(NCREG_UNCORR_ERROR_COUNT)) ++ ++#define WR_CORR_THRESH(cs, val) do { \ ++ u32 contents = NAND_REG_RD(NCREG_CORR_STAT_THRESHOLD); \ ++ u32 shift = NCFLD_CORR_STAT_THRESHOLD_CS1_SHIFT * (cs); \ ++ contents &= ~(NCFLD_CORR_STAT_THRESHOLD_CS0_MASK << shift); \ ++ contents |= ((val) & NCFLD_CORR_STAT_THRESHOLD_CS0_MASK) << shift; \ ++ NAND_REG_WR(NCREG_CORR_STAT_THRESHOLD, contents); \ ++} while(0) ++ ++/* ++ * Internal structures ++ */ ++struct iproc_nand_controller { ++ struct nand_hw_control controller; ++ int irq; ++ int cmd_pending; ++ struct completion done; ++ int boot_inited; ++ ++ volatile void *nand_regs; ++ volatile void *nand_intr_regs; ++ volatile void *idm_nand_regs; ++}; ++ ++struct iproc_nand_cfg { ++ u64 device_size; ++ unsigned int block_size; ++ unsigned int page_size; ++ unsigned int spare_area_size; ++ unsigned int device_width; ++ unsigned int col_adr_bytes; ++ unsigned int blk_adr_bytes; ++ unsigned int ful_adr_bytes; ++ unsigned int sector_size_1k; ++}; ++ ++struct iproc_nand_host { ++ u32 buf[FC_WORDS]; ++ struct nand_chip chip; ++ struct mtd_info mtd; ++ struct platform_device *pdev; ++ int cs; ++ unsigned int last_cmd; ++ unsigned int last_byte; ++ u64 last_addr; ++ struct iproc_nand_cfg hwcfg; ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ u16 eccpos; ++ u16 eccbytes; ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++}; ++ ++static struct nand_ecclayout iproc_nand_oob_layout; ++ ++struct iproc_nand_exception { ++ const char *name; ++ int id[7]; ++ int idlen; /* usable */ ++ unsigned int chipsize; /* MB */ ++ unsigned int writesize; /* B */ ++ unsigned int erasesize; /* B */ ++ unsigned int oobsize; /* B per page */ ++ int chipoptions; ++ int badblockpos; ++}; ++ ++/* ++ * Global variables ++ */ ++ ++static struct iproc_nand_controller ctrl; ++ ++static struct iproc_nand_exception iproc_exceptions_list[] = { ++ {"Micron MT29F8G08ABACA", ++ {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00}, ++ 5, 0x00400, 4096, 0x040000, 224}, ++ {"Micron MT29F16G08ABABA", ++ {0x2C, 0x48, 0x00, 0x26, 0x89, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x080000, 224}, ++ {"Micron MT29F16G08CBABA", ++ {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x100000, 224}, ++ {"Micron MT29F16G08CBACA", ++ {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x100000, 224}, ++ {"Micron MT29F16G08MAA", ++ {0x2C, 0xD5, 0x94, 0x3E, 0x74, 0x00, 0x00}, ++ 5, 0x00800, 4096, 0x080000, 218}, ++ {"Micron MT29F32G08CBACA", ++ {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00}, ++ 5, 0x01000, 4096, 0x100000, 224}, ++ {"Micron MT29F64G08CBAAA", ++ {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00}, ++ 5, 0x02000, 8192, 0x200000, 448}, ++ {"Micron MT29F256G08CJAAA", ++ {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00}, ++ 5, 0x08000, 8192, 0x200000, 448}, ++ {NULL,} ++}; ++ ++/* Used for running nand_scan_ident without the built-in heuristics */ ++static struct nand_flash_dev iproc_empty_flash_table[] = { ++ {NULL,} ++}; ++ ++/* ECC bytes required per 512B */ ++static const uint8_t nand_iproc_ecc_levels[2] = { 18, 21 }; ++static const uint8_t nand_iproc_ecc_bytes[] = { ++ 0, 2, 4, 6, 7, 9, 11, 13, 14, 16, 18, 20, 21, 23, 25, ++ 27, /* or 3 if SPARE_AREA_SIZE == 16 && SECTOR_SIZE_1K == 0*/ ++ 28, 30, 32, 34, 35 ++}; ++ ++/* Strap settings */ ++struct nand_strap_type_t { ++ uint8_t sector_1k; ++ uint8_t ecclevel; ++ uint16_t spare_size; ++}; ++static const struct nand_strap_type_t nand_strap_types[] = { ++ { 0, 0, 16 }, ++ { 0, 15, 16 }, ++ { 0, 4, 16 }, ++ { 0, 8, 16 }, ++ { 0, 8, 27 }, ++ { 0, 12, 27 }, ++ { 1, 12, 27 }, ++ { 1, 15, 27 }, ++ { 1, 20, 45 }, ++}; ++static const uint32_t nand_strap_page_sizes[] = { 2048, 2048, 4096, 8192 }; ++ ++/*********************************************************************** ++ * Internal support functions ++ ***********************************************************************/ ++ ++static void ++iproc_nand_wp(struct mtd_info *mtd, int wp) ++{ ++ if (wp_on == 1) { ++ static int old_wp = -1; ++ if (old_wp != wp) { ++ DBG("%s: WP %s\n", __func__, wp ? "on" : "off"); ++ old_wp = wp; ++ } ++ if (wp) { ++ NAND_REG_SET_RB(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } else { ++ NAND_REG_UNSET_RB(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } ++ } ++} ++ ++/* Helper functions for reading and writing OOB registers */ ++static inline unsigned char ++oob_reg_read(int offs) ++{ ++ if (offs >= MAX_CONTROLLER_OOB) ++ return 0x77; ++ ++ return NAND_REG_RD(NCREG_SPARE_AREA_READ_OFS_0 + (offs & ~0x03)) ++ >> (24 - ((offs & 0x03) << 3)); ++} ++ ++static inline void ++oob_reg_write(int offs, unsigned long data) ++{ ++ if (offs >= MAX_CONTROLLER_OOB) ++ return; ++ ++ NAND_REG_WR(NCREG_SPARE_AREA_WRITE_OFS_0 + (offs & ~0x03), ++ data); ++} ++ ++/* ++ * read_oob_from_regs - read data from OOB registers ++ * @i: sub-page sector index ++ * @oob: buffer to read to ++ * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) ++ * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal ++ */ ++static int ++read_oob_from_regs(int i, u8 *oob, int sas, int sector_1k) ++{ ++ int tbytes = sas << sector_1k; ++ int j; ++ ++ /* Adjust OOB values for 1K sector size */ ++ if (sector_1k && (i & 0x01)) ++ tbytes = max(0, tbytes - MAX_CONTROLLER_OOB); ++ tbytes = min(tbytes, MAX_CONTROLLER_OOB); ++ ++ for (j = 0; j < tbytes; j++) ++ oob[j] = oob_reg_read(j); ++ return tbytes; ++} ++ ++/* ++ * write_oob_to_regs - write data to OOB registers ++ * @i: sub-page sector index ++ * @oob: buffer to write from ++ * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) ++ * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal ++ */ ++static int ++write_oob_to_regs(int i, const u8 *oob, int sas, int sector_1k) ++{ ++ int tbytes = sas << sector_1k; ++ int j; ++ ++ /* Adjust OOB values for 1K sector size */ ++ if (sector_1k && (i & 0x01)) ++ tbytes = max(0, tbytes - MAX_CONTROLLER_OOB); ++ tbytes = min(tbytes, MAX_CONTROLLER_OOB); ++ ++ for (j = 0; j < tbytes; j += 4) ++ oob_reg_write(j, ++ (oob[j + 0] << 24) | ++ (oob[j + 1] << 16) | ++ (oob[j + 2] << 8) | ++ (oob[j + 3] << 0)); ++ return tbytes; ++} ++ ++static irqreturn_t ++iproc_nand_irq(int irq, void *data) ++{ ++ if (NAND_TEST_IRQ(NCINTR_CTLRDY)) { ++ NAND_ACK_IRQ(NCINTR_CTLRDY); ++ if (ctrl.cmd_pending) { ++ /* ++ * If the direct access region (eg. 0x1c000000 on NS) is accessed, ++ * IRQ handler will also be called with NCINTR_CTLRDY asserted. ++ * Thus we need to filter these events by ctrl.cmd_pending, or ++ * ctrl.done will be mistakenly set and cause incorrect result for ++ * the following command. ++ * We actually should avoid direct access to the mapped region when ++ * NAND driver is running. ++ */ ++ complete(&ctrl.done); ++ } ++ return IRQ_HANDLED; ++ } ++ return IRQ_NONE; ++} ++ ++static void ++iproc_nand_send_cmd(int cmd) ++{ ++ DBG("%s: native cmd %d addr_lo 0x%lx\n", __func__, cmd,(unsigned long)NAND_REG_RD(NCREG_CMD_ADDRESS)); ++ BUG_ON(ctrl.cmd_pending != 0); ++ ctrl.cmd_pending = cmd; ++ mb(); ++ NAND_REG_WR(NCREG_CMD_START, cmd << NCFLD_CMD_START_OPCODE_SHIFT); ++} ++ ++/*********************************************************************** ++ * NAND MTD API: read/program/erase ++ ***********************************************************************/ ++ ++static void ++iproc_nand_cmd_ctrl(struct mtd_info *mtd, int dat, ++ unsigned int ctrl) ++{ ++ /* intentionally left blank */ ++} ++ ++static int ++iproc_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ ++ DBG("%s: native cmd %d\n", __func__, ctrl.cmd_pending); ++ if (ctrl.cmd_pending && ++ wait_for_completion_timeout(&ctrl.done, HZ / 10) <= 0) { ++ dev_err(&host->pdev->dev, ++ "timeout waiting for command %u (%ld)\n", ++ host->last_cmd, (unsigned long)NAND_REG_RD(NCREG_CMD_START) >> 24); ++ dev_err(&host->pdev->dev, ++ "irq status %08lx, intfc status %08lx\n", ++ (unsigned long)NAND_TEST_IRQ(NCINTR_CTLRDY), ++ (unsigned long)NAND_REG_RD(NCREG_INTFC_STATUS)); ++ } ++ ctrl.cmd_pending = 0; ++ iproc_nand_wp(mtd, 1); ++ return NAND_REG_RD(NCREG_INTFC_STATUS) & ++ NCFLD_INTFC_STATUS_FLASH_STATUS_MASK; ++} ++ ++static void ++iproc_nand_cmdfunc(struct mtd_info *mtd, unsigned command, ++ int column, int page_addr) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ u64 addr = (u64)page_addr << chip->page_shift; ++ int native_cmd = 0; ++ ++ if (command == NAND_CMD_READID ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ || command == NAND_CMD_PARAM ++#endif ++ ) ++ addr = (u64)column; ++ ++ DBG("%s: cmd 0x%x addr 0x%llx\n", __func__, command,(unsigned long long)addr); ++ host->last_cmd = command; ++ host->last_byte = 0; ++ host->last_addr = addr; ++ ++ switch (command) { ++ case NAND_CMD_RESET: ++ native_cmd = CMD_FLASH_RESET; ++ break; ++ case NAND_CMD_STATUS: ++ native_cmd = CMD_STATUS_READ; ++ break; ++ case NAND_CMD_READID: ++ native_cmd = CMD_DEVICE_ID_READ; ++ break; ++ case NAND_CMD_READOOB: ++ native_cmd = CMD_SPARE_AREA_READ; ++ break; ++ case NAND_CMD_ERASE1: ++ native_cmd = CMD_BLOCK_ERASE; ++ iproc_nand_wp(mtd, 0); ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ case NAND_CMD_PARAM: ++ native_cmd = CMD_PARAMETER_READ; ++ break; ++#endif ++ } ++ ++ if (!native_cmd) ++ return; ++ ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ ++ iproc_nand_send_cmd(native_cmd); ++ iproc_nand_waitfunc(mtd, chip); ++} ++ ++static uint8_t ++iproc_nand_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ uint8_t ret = 0; ++ ++ switch (host->last_cmd) { ++ case NAND_CMD_READID: ++ if (host->last_byte < 4) ++ ret = NAND_REG_RD(NCREG_FLASH_DEVICE_ID) >> ++ (24 - (host->last_byte << 3)); ++ else if (host->last_byte < 8) ++ ret = NAND_REG_RD(NCREG_FLASH_DEVICE_ID_EXT) >> ++ (56 - (host->last_byte << 3)); ++ break; ++ ++ case NAND_CMD_READOOB: ++ ret = oob_reg_read(host->last_byte); ++ break; ++ ++ case NAND_CMD_STATUS: ++ ret = NAND_REG_RD(NCREG_INTFC_STATUS) & ++ NCFLD_INTFC_STATUS_FLASH_STATUS_MASK; ++ if (wp_on) { ++ /* Hide WP status from MTD */ ++ ret |= NAND_STATUS_WP; ++ } ++ break; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) ++ case NAND_CMD_PARAM: ++ if (host->last_byte < FC_BYTES) ++ ret = NAND_REG_RD(FC(host->last_byte >> 2)) >> ++ (24 - ((host->last_byte & 0x03) << 3)); ++ break; ++#endif ++ } ++ ++ DBG("%s: byte = 0x%02x\n", __func__, ret); ++ host->last_byte++; ++ ++ return ret; ++} ++ ++static void ++iproc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++, buf++) ++ *buf = iproc_nand_read_byte(mtd); ++} ++ ++/* Copied from nand_base.c to support custom iproc_check_exceptions() */ ++static void ++iproc_nand_erase_cmd(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *chip = mtd->priv; ++ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); ++} ++ ++/* ++ * Assumes proper CS is already set ++ */ ++static void ++iproc_nand_read_by_pio(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, unsigned int trans, ++ u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int i, j; ++ ++ for (i = 0; i < trans; i++, addr += FC_BYTES) { ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ ++ iproc_nand_send_cmd(CMD_PAGE_READ); ++ iproc_nand_waitfunc(mtd, chip); ++ ++ if (likely(buf)) { ++ NAND_BEGIN_DATA_ACCESS(); ++ for (j = 0; j < FC_WORDS; j++, buf++) ++ *buf = NAND_REG_RD(FC(j)); ++ NAND_END_DATA_ACCESS(); ++ } ++ ++ if (oob) ++ oob += read_oob_from_regs(i, oob, ++ mtd->oobsize / trans, host->hwcfg.sector_size_1k); ++ } ++} ++ ++static int ++iproc_nand_read(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, unsigned int trans, ++ u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ u64 err_addr; ++ DBG("%s %llx -> %p\n", __func__, (unsigned long long)addr, buf); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* If reading OOB only, don't enable ECC correction */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ } ++ ++ /* We must read spare area to check false uncorrectable errors. */ ++ if (oob == NULL) { ++ oob = (u8 *)host->buf; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ NAND_REG_WR_RB(NCREG_ECC_UNC_ADDR, 0); ++ NAND_REG_WR_RB(NCREG_ECC_CORR_ADDR, 0); ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ ++ iproc_nand_read_by_pio(mtd, chip, addr, trans, buf, oob); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Rollback ECC correction */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ ++ /* No ECC correction was performed */ ++ return 0; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ /* Check correctable errors */ ++ err_addr = NAND_REG_RD(NCREG_ECC_CORR_ADDR) | ++ ((u64)(NAND_REG_RD(NCREG_ECC_CORR_EXT_ADDR) & 0xffff) << 32); ++ if (err_addr) { ++ printk(KERN_DEBUG "%s: corrected error at 0x%llx\n", ++ DRV_NAME, (unsigned long long)err_addr); ++ mtd->ecc_stats.corrected += CORR_ERROR_COUNT; ++ /* NAND layer expects zero on ECC errors */ ++ return 0; ++ } ++ ++ /* Check uncorrectable errors */ ++ err_addr = NAND_REG_RD(NCREG_ECC_UNC_ADDR) | ++ ((u64)(NAND_REG_RD(NCREG_ECC_UNC_EXT_ADDR) & 0xffff) << 32); ++ if (err_addr != 0) { ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ int i; ++ ++ /* Check if ECC bytes are FFs. Only the first sector is required. */ ++ for(i=0; ieccbytes; i++) { ++ if (oob[host->eccpos + i] != 0xFF) { ++ break; ++ } ++ } ++ if (i == host->eccbytes) { ++ /* False alarm (the page was written with OOB only and ECC off) */ ++ return 0; ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++#ifdef NAND_REPORT_ECC_UNCORR_ERRORS ++ printk(KERN_WARNING "%s: uncorrectable error at 0x%llx\n", ++ DRV_NAME, (unsigned long long)err_addr); ++ mtd->ecc_stats.failed += UNCORR_ERROR_COUNT; ++#endif /* NAND_REPORT_ECC_UNCORR_ERRORS */ ++ ++ /* NAND layer expects zero on ECC errors */ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static int ++iproc_nand_read_page(struct mtd_info *mtd, ++ struct nand_chip *chip, uint8_t *buf, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ return iproc_nand_read(mtd, chip, host->last_addr, ++ mtd->writesize >> FC_SHIFT, (u32 *)buf, ++ (u8 *)chip->oob_poi); ++} ++ ++static int ++iproc_nand_read_page_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, uint8_t *buf, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int ret; ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ ret = iproc_nand_read(mtd, chip, host->last_addr, ++ mtd->writesize >> FC_SHIFT, ++ (u32 *)buf, (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ return ret; ++} ++ ++static int ++iproc_nand_read_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ return iproc_nand_read(mtd, chip, (u64)page << chip->page_shift, ++ mtd->writesize >> FC_SHIFT, ++ NULL, (u8 *)chip->oob_poi); ++} ++ ++#ifdef NAND_BBT_USE_FLASH ++/* Patched MTD implementation */ ++static int ++iproc_nand_read_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 0); ++ iproc_nand_read(mtd, chip, (u64)page << chip->page_shift, ++ mtd->writesize >> FC_SHIFT, ++ NULL, (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ return 0; ++} ++#endif ++ ++static int ++iproc_nand_read_subpage(struct mtd_info *mtd, ++ struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, ++ uint8_t *bufpoi) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ return iproc_nand_read(mtd, chip, host->last_addr + data_offs, ++ readlen >> FC_SHIFT, (u32 *)bufpoi, NULL); ++} ++ ++static int ++iproc_nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_host *host = chip->priv; ++ unsigned int i, j; ++ int err; ++ u64 addr = host->last_addr; ++ u32 *src = (u32 *)buf, *dst; ++ ++ for (i = 0; i < (mtd->writesize >> FC_SHIFT); i++) { ++ err = iproc_nand_read(mtd, chip, addr, 1, host->buf, NULL); ++ ++ if (err) { ++ dev_info(&host->pdev->dev, ++ "verify failed at 0x%llx (error %d)\n", ++ (unsigned long long)addr, err); ++ return -EFAULT; ++ } ++ dst = host->buf; ++ ++ for (j = 0; j < FC_WORDS; j++, src++, dst++) ++ if (*src != le32_to_cpu(*dst)) { ++ dev_info(&host->pdev->dev, ++ "mismatch at 0x%llx (read %08lx, " ++ "expected %08lx)\n", ++ (unsigned long long)addr + (j << 2), ++ (unsigned long)*dst, ++ (unsigned long)*src); ++ return -EFAULT; ++ } ++ addr += FC_BYTES; ++ } ++ return 0; ++} ++ ++static int ++iproc_nand_write(struct mtd_info *mtd, ++ struct nand_chip *chip, u64 addr, const u32 *buf, u8 *oob) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ unsigned int i = 0, j, trans = mtd->writesize >> FC_SHIFT; ++ int status; ++ ++ DBG("%s %llx <- %p\n", __func__, (unsigned long long)addr, buf); ++ ++ if (unlikely((u32)buf & 0x03)) { ++ dev_warn(&host->pdev->dev, "unaligned buffer: %p\n", buf); ++ buf = (u32 *)((u32)buf & ~0x03); ++ } ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Merge (AND) the new and old OOB data */ ++ if (oob) { ++ ++ u8 *oob0 = (u8 *)host->buf; ++ int i; ++ ++ /* Read the spare area from flash */ ++ iproc_nand_read(mtd, chip, addr, 8, NULL, oob0); ++ ++ /* AND them with new OOB data */ ++ for(i=0; ioobsize; i++) { ++ oob[i] &= oob0[i]; ++ } ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ NAND_REG_WR_RB(NCREG_CMD_EXT_ADDRESS, ++ (host->cs << 16) | ((addr >> 32) & 0xffff)); ++ ++ for (j = 0; j < MAX_CONTROLLER_OOB; j += 4) ++ oob_reg_write(j, 0xffffffff); ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Disable ECC generation if writing OOB only */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ for (; i < trans; i++, addr += FC_BYTES) { ++ ++ /* full address MUST be set before populating FC */ ++ NAND_REG_WR_RB(NCREG_CMD_ADDRESS, addr & 0xffffffff); ++ ++ if (buf) { ++ NAND_BEGIN_DATA_ACCESS(); ++ for (j = 0; j < FC_WORDS; j++, buf++) ++ NAND_REG_WR(FC(j), *buf); ++ NAND_END_DATA_ACCESS(); ++ } else if (oob) { ++ for (j = 0; j < FC_WORDS; j++) ++ NAND_REG_WR(FC(j), 0xffffffff); ++ } ++ ++ if (oob) { ++ oob += write_oob_to_regs(i, oob, mtd->oobsize / trans, ++ host->hwcfg.sector_size_1k); ++ } ++ ++ iproc_nand_wp(mtd, 0); ++ ++ /* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */ ++ iproc_nand_send_cmd(CMD_PROGRAM_PAGE); ++ status = iproc_nand_waitfunc(mtd, chip); ++ ++ if (status & NAND_STATUS_FAIL) { ++ dev_info(&host->pdev->dev, "program failed at %llx\n", ++ (unsigned long long)addr); ++ return -EIO; ++ } ++ } ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ /* Rollback ECC generation */ ++ if (!buf) { ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ } ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ return 0; ++} ++ ++static void ++iproc_nand_write_page(struct mtd_info *mtd, ++ struct nand_chip *chip, const uint8_t *buf) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ iproc_nand_write(mtd, chip, host->last_addr, (u32 *)buf, (u8 *)chip->oob_poi); ++} ++ ++static void ++iproc_nand_write_page_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, const uint8_t *buf) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ iproc_nand_write(mtd, chip, host->last_addr, (u32 *)buf, ++ (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++} ++ ++static int ++iproc_nand_write_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page) ++{ ++ return iproc_nand_write(mtd, chip, (u64)page << chip->page_shift, NULL, ++ (u8 *)chip->oob_poi); ++} ++ ++#ifdef NAND_BBT_USE_FLASH ++/* Patched MTD implementation */ ++static int ++iproc_nand_write_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *chip, int page) ++{ ++ struct iproc_nand_host *host = chip->priv; ++ int r; ++ ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 0); ++ r = iproc_nand_write(mtd, chip, (u64)page << chip->page_shift, NULL, ++ (u8 *)chip->oob_poi); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ return r; ++} ++#endif ++ ++ ++/*********************************************************************** ++ * Per-CS setup (1 NAND device) ++ ***********************************************************************/ ++ ++static const unsigned int block_sizes[] = { 8, 16, 128, 256, 512, 1024, 2048 }; ++static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192 }; ++ ++static void ++iproc_nand_set_cfg(struct iproc_nand_host *host, ++ struct iproc_nand_cfg *cfg) ++{ ++ int i, found; ++ ++ for (i = 0, found = 0; i < ARRAY_SIZE(block_sizes); i++) ++ if ((block_sizes[i] << 10) == cfg->block_size) { ++ WR_CONFIG(host->cs, BLOCK_SIZE, i); ++ found = 1; ++ } ++ if (!found) ++ dev_warn(&host->pdev->dev, "invalid block size %u\n", ++ cfg->block_size); ++ ++ for (i = 0, found = 0; i < ARRAY_SIZE(page_sizes); i++) ++ if (page_sizes[i] == cfg->page_size) { ++ WR_CONFIG(host->cs, PAGE_SIZE, i); ++ found = 1; ++ } ++ if (!found) ++ dev_warn(&host->pdev->dev, "invalid page size %u\n", ++ cfg->page_size); ++ ++ if (fls64(cfg->device_size) < 23) ++ dev_warn(&host->pdev->dev, "invalid device size 0x%llx\n", ++ (unsigned long long)cfg->device_size); ++ ++ WR_CONFIG(host->cs, DEVICE_SIZE, fls64(cfg->device_size) - 23); ++ WR_CONFIG(host->cs, DEVICE_WIDTH, cfg->device_width == 16 ? 1 : 0); ++ WR_CONFIG(host->cs, COL_ADR_BYTES, cfg->col_adr_bytes); ++ WR_CONFIG(host->cs, BLK_ADR_BYTES, cfg->blk_adr_bytes); ++ WR_CONFIG(host->cs, FUL_ADR_BYTES, cfg->ful_adr_bytes); ++ ++ WR_ACC_CONTROL(host->cs, SPARE_AREA_SIZE, cfg->spare_area_size); ++ WR_ACC_CONTROL(host->cs, SECTOR_SIZE_1K, cfg->sector_size_1k); ++} ++ ++static void ++iproc_nand_get_cfg(struct iproc_nand_host *host, ++ struct iproc_nand_cfg *cfg) ++{ ++ cfg->block_size = RD_CONFIG(host->cs, BLOCK_SIZE); ++ cfg->device_size = (4ULL << 20) << RD_CONFIG(host->cs, DEVICE_SIZE); ++ cfg->page_size = RD_CONFIG(host->cs, PAGE_SIZE); ++ cfg->device_width = RD_CONFIG(host->cs, DEVICE_WIDTH) ? 16 : 8; ++ cfg->col_adr_bytes = RD_CONFIG(host->cs, COL_ADR_BYTES); ++ cfg->blk_adr_bytes = RD_CONFIG(host->cs, BLK_ADR_BYTES); ++ cfg->ful_adr_bytes = RD_CONFIG(host->cs, FUL_ADR_BYTES); ++ cfg->spare_area_size = RD_ACC_CONTROL(host->cs, SPARE_AREA_SIZE); ++ cfg->sector_size_1k = RD_ACC_CONTROL(host->cs, SECTOR_SIZE_1K); ++ ++ if (cfg->block_size < ARRAY_SIZE(block_sizes)) ++ cfg->block_size = block_sizes[cfg->block_size] << 10; ++ else ++ cfg->block_size = 128 << 10; ++ ++ if (cfg->page_size < ARRAY_SIZE(page_sizes)) ++ cfg->page_size = page_sizes[cfg->page_size]; ++ else ++ cfg->page_size = 2048; ++} ++ ++static void ++iproc_nand_print_cfg(char *buf, struct iproc_nand_cfg *cfg) ++{ ++ sprintf(buf, ++ "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit", ++ (unsigned long long)cfg->device_size >> 20, ++ cfg->block_size >> 10, ++ cfg->page_size >= 1024 ? cfg->page_size >> 10 : cfg->page_size, ++ cfg->page_size >= 1024 ? "KiB" : "B", ++ cfg->spare_area_size, cfg->device_width); ++} ++ ++static int __devinit ++iproc_nand_setup_dev( ++ struct iproc_nand_host *host, ++ struct brcmnand_platform_data *pd) ++{ ++ struct mtd_info *mtd = &host->mtd; ++ struct nand_chip *chip = &host->chip; ++ struct iproc_nand_cfg orig_cfg, new_cfg; ++ struct nand_oobfree *free = iproc_nand_oob_layout.oobfree; ++ char msg[128]; ++ unsigned int ecclevel; ++ ++ iproc_nand_get_cfg(host, &orig_cfg); ++ host->hwcfg = orig_cfg; ++ ++ memset(&new_cfg, 0, sizeof(new_cfg)); ++ new_cfg.device_size = mtd->size; ++ new_cfg.block_size = mtd->erasesize; ++ new_cfg.page_size = mtd->writesize; ++ new_cfg.spare_area_size = mtd->oobsize / (mtd->writesize >> FC_SHIFT); ++ new_cfg.device_width = (chip->options & NAND_BUSWIDTH_16) ? 16 : 8; ++ new_cfg.col_adr_bytes = 2; ++ ++ if (mtd->writesize > 512) ++ if (mtd->size >= (256 << 20)) ++ new_cfg.blk_adr_bytes = 3; ++ else ++ new_cfg.blk_adr_bytes = 2; ++ else ++ if (mtd->size >= (64 << 20)) ++ new_cfg.blk_adr_bytes = 3; ++ else ++ new_cfg.blk_adr_bytes = 2; ++ new_cfg.ful_adr_bytes = new_cfg.blk_adr_bytes + new_cfg.col_adr_bytes; ++ ++ /* Original ECC level */ ++ ecclevel = RD_ACC_CONTROL(host->cs, ECC_LEVEL); ++ ++ /* Check settings inherited from bootloader */ ++ if(ctrl.boot_inited) { ++ ++ /* Check basic device attributes first */ ++ int sz1k = orig_cfg.sector_size_1k? 1 : 0; ++ if (orig_cfg.device_size != new_cfg.device_size || ++ orig_cfg.block_size != new_cfg.block_size || ++ orig_cfg.page_size != new_cfg.page_size || ++ orig_cfg.device_width != new_cfg.device_width || ++ orig_cfg.col_adr_bytes != new_cfg.col_adr_bytes || ++ orig_cfg.blk_adr_bytes != new_cfg.blk_adr_bytes || ++ orig_cfg.ful_adr_bytes != new_cfg.ful_adr_bytes || ++ ecclevel == 0 || ecclevel >= nand_iproc_ecc_levels[sz1k] || ++ orig_cfg.spare_area_size > new_cfg.spare_area_size || ++ nand_iproc_ecc_bytes[ecclevel] > orig_cfg.spare_area_size) { ++ ++ ctrl.boot_inited = 0; ++ printk(KERN_INFO "%s: invalid bootloader settings\n", DRV_NAME); ++ ++ } else { ++ /* Bootloader has initialized the flash correctly. */ ++ new_cfg = orig_cfg; ++ iproc_nand_print_cfg(msg, &orig_cfg); ++ printk(KERN_INFO "%s: following bootloader settings\n", DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ } ++ } ++ ++ /* Decide ECC settings ourselves if it's not initialized before */ ++ if (!ctrl.boot_inited) { ++ ++ /* Check if strap settings are valid */ ++ if (pd->strap_type > 0 && ++ nand_strap_page_sizes[pd->strap_page_size] == new_cfg.page_size && ++ nand_strap_types[pd->strap_type].spare_size <= mtd->writesize ) { ++ ++ /* It's valid, follow the strap settings */ ++ new_cfg.spare_area_size = nand_strap_types[pd->strap_type].spare_size; ++ new_cfg.sector_size_1k = nand_strap_types[pd->strap_type].sector_1k; ++ ecclevel = nand_strap_types[pd->strap_type].ecclevel; ++ if (pd->strap_page_size == 0) { ++ new_cfg.blk_adr_bytes = 2; ++ new_cfg.ful_adr_bytes = 4; ++ } else { ++ new_cfg.blk_adr_bytes = 3; ++ new_cfg.ful_adr_bytes = 5; ++ } ++ ++ iproc_nand_print_cfg(msg, &new_cfg); ++ printk(KERN_INFO "%s: following strap settings\n", DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ ++ } else { ++ ++ /* ++ * Strap settings are not valid, decide the settings on our own ++ */ ++ ++ /* Trying to fit with available strap settings */ ++ new_cfg.spare_area_size = new_cfg.spare_area_size >= 27 ? 27 : 16; ++ new_cfg.sector_size_1k = 0; ++ if (new_cfg.spare_area_size == 27) { ++ ecclevel = 12; ++ new_cfg.sector_size_1k = (new_cfg.page_size >= 2048) ? 1 : 0; ++ } else if (chip->badblockpos == NAND_SMALL_BADBLOCK_POS) { ++ ecclevel = 4; ++ } else { ++ ecclevel = 8; ++ } ++ ++ iproc_nand_print_cfg(msg, &new_cfg); ++ printk(KERN_ERR "*ERROR* Invalid board strap settings for NAND!"); ++ printk(KERN_INFO "%s: overriding invalid strap settings\n", ++ DRV_NAME); ++ printk(KERN_INFO "%s: %s\n", DRV_NAME, msg); ++ } ++ ++ iproc_nand_set_cfg(host, &new_cfg); ++ host->hwcfg = new_cfg; ++ ++ WR_ACC_CONTROL(host->cs, ECC_LEVEL, ecclevel); ++ /* threshold = ceil(BCH-level * 0.75) */ ++ WR_CORR_THRESH(host->cs, ((ecclevel << new_cfg.sector_size_1k) ++ * 3 + 2) / 4); ++ ++ /* Account for 24-bit per 1024-byte ECC settings */ ++ if (new_cfg.sector_size_1k) ++ printk(KERN_INFO "%s: ECC set to BCH-%u (1KiB sector)\n", ++ DRV_NAME, ecclevel << 1); ++ else ++ printk(KERN_INFO "%s: ECC set to BCH-%u (512B sector)\n", ++ DRV_NAME, ecclevel); ++ } ++ ++ WR_ACC_CONTROL(host->cs, RD_ECC_EN, 1); ++ WR_ACC_CONTROL(host->cs, WR_ECC_EN, 1); ++ WR_ACC_CONTROL(host->cs, FAST_PGM_RDIN, 0); ++ WR_ACC_CONTROL(host->cs, RD_ERASED_ECC_EN, 0); ++ WR_ACC_CONTROL(host->cs, PARTIAL_PAGE_EN, 0); ++ WR_ACC_CONTROL(host->cs, PAGE_HIT_EN, 1); ++ ++ mb(); ++ ++ /* Adjust MTD oobsize according to the configuration */ ++ mtd->oobsize = new_cfg.spare_area_size * (mtd->writesize >> FC_SHIFT); ++ ++ /* Adjust ECC layout for storing usb OOB data */ ++ free->length = 0; ++ if (ecclevel < nand_iproc_ecc_levels[new_cfg.sector_size_1k]) { ++ ++ uint8_t steps = mtd->writesize >> FC_SHIFT; ++ uint8_t eccbytes = nand_iproc_ecc_bytes[ecclevel]; ++ ++ /* Special case: using Hamming code when ecclevel == 15 */ ++ if (ecclevel == 15) { ++ if (new_cfg.spare_area_size == 16 && !new_cfg.sector_size_1k) { ++ eccbytes = 3; ++ } ++ } ++ ++ /* These are not really used. We still prepare them for safety. */ ++ iproc_nand_oob_layout.eccbytes = eccbytes * steps; ++ chip->ecc.bytes = eccbytes; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) ++ chip->ecc.strength = ecclevel; ++#endif ++ ++#ifdef NAND_MTD_WRITE_OOB_SEPARATELY ++ host->eccpos = ++ (new_cfg.spare_area_size - eccbytes) << new_cfg.sector_size_1k; ++ host->eccbytes = eccbytes << new_cfg.sector_size_1k; ++#endif /* NAND_MTD_WRITE_OOB_SEPARATELY */ ++ ++ /* Create oobfree for storing user OOB data */ ++ if (new_cfg.spare_area_size > eccbytes) { ++ ++ unsigned int spare_size; ++ uint8_t i, cnt; ++ ++ spare_size = new_cfg.spare_area_size << new_cfg.sector_size_1k; ++ eccbytes <<= new_cfg.sector_size_1k; ++ steps >>= new_cfg.sector_size_1k; ++ if (steps > MTD_MAX_OOBFREE_ENTRIES) { ++ steps = MTD_MAX_OOBFREE_ENTRIES; ++ } ++ for(i=0, cnt=0; ioffset = i * spare_size; ++ free->length = 6; ++ ++ } else { ++ ++ /* BCH: ECC bytes at the bottom */ ++ free->offset = i * spare_size; ++ free->length = spare_size - eccbytes; ++ } ++ ++ /* Reserve the first two bytes of the page */ ++ if (i == 0) { ++ if (free->length <= 2) { ++ /* Don't claim this entry if less than 2 bytes */ ++ continue; ++ } ++ free->offset += 2; ++ free->length -= 2; ++ } ++ ++ if (eccbytes == 3) { ++ /* Hamming code: the 2nd free part */ ++ free++; ++ cnt++; ++ if (cnt < MTD_MAX_OOBFREE_ENTRIES) { ++ free->offset = i * spare_size + 9; ++ free->length = 7; ++ } else { ++ /* The structure limits us. */ ++ break; ++ } ++ } ++ ++ free++; ++ cnt++; ++ } ++ if (cnt < MTD_MAX_OOBFREE_ENTRIES) { ++ /* Terminater */ ++ free->length = 0; ++ } ++ ++ /* Print out oob space information */ ++ free = iproc_nand_oob_layout.oobfree; ++ if (free->length) { ++ spare_size = 0; ++ while(free->length) { ++ spare_size += free->length; ++ free++; ++ } ++ printk(KERN_INFO "%s: user oob per page: %u bytes (%u steps)\n", ++ DRV_NAME, spare_size, (int)steps); ++ } ++ } ++ } ++ ++ if (iproc_nand_oob_layout.oobfree[0].length == 0) { ++ printk(KERN_INFO "%s: no oob space available\n", DRV_NAME); ++ } ++ ++ return 0; ++} ++ ++static int ++iproc_check_exceptions(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct iproc_nand_exception *list = iproc_exceptions_list; ++ int i; ++ u8 id_data[8]; ++ ++ /* ++ * run default nand_base initialization w/o built-in ID table; ++ * should return error, so we tell it to be "silent" ++ */ ++ chip->options |= NAND_SCAN_SILENT_NODEV; ++ nand_scan_ident(mtd, 1, iproc_empty_flash_table); ++ chip->options &= ~NAND_SCAN_SILENT_NODEV; ++ ++ /* Send the command for reading device ID */ ++ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ++ for (i = 0; i < 8; i++) ++ id_data[i] = chip->read_byte(mtd); ++ ++ for (; list->name != NULL; list++) { ++ for (i = 0; i < list->idlen; i++) ++ if (id_data[i] != list->id[i]) ++ break; ++ if (i == list->idlen) ++ break; ++ } ++ ++ if (!list->name) ++ return -ENODEV; ++ ++ chip->chipsize = (uint64_t)list->chipsize << 20; ++ mtd->size = chip->chipsize; ++ ++ mtd->erasesize = list->erasesize; ++ mtd->writesize = list->writesize; ++ mtd->oobsize = list->oobsize; ++ ++ chip->options |= list->chipoptions; ++ chip->badblockpos = list->badblockpos; ++ ++ /* The 3rd id byte holds MLC / multichip data */ ++ chip->cellinfo = id_data[2]; ++ ++ chip->numchips = 1; ++ ++ /* Calculate the address shift from the page size */ ++ chip->page_shift = ffs(mtd->writesize) - 1; ++ /* Convert chipsize to number of pages per chip -1. */ ++ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; ++ ++ chip->bbt_erase_shift = chip->phys_erase_shift = ++ ffs(mtd->erasesize) - 1; ++ chip->chip_shift = fls64(chip->chipsize) - 1; ++ ++ chip->erase_cmd = iproc_nand_erase_cmd; ++ ++ printk(KERN_INFO "%s: heuristics exception detected, %s\n", ++ DRV_NAME, list->name); ++ return 0; ++} ++ ++static int __devinit ++iproc_nand_probe(struct platform_device *pdev) ++{ ++ struct brcmnand_platform_data *pd = pdev->dev.platform_data; ++ struct iproc_nand_host *host; ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ int ret = 0; ++ ++#if defined(CONFIG_MTD_PARTITIONS) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) ++ int nr_parts; ++ struct mtd_partition *parts; ++ const char *part_probe_types[] = { "cmdlinepart", NULL }; ++#endif ++ ++ DBG("%s: id %d cs %d\n", __func__, pdev->id, pd->chip_select); ++ ++ host = kzalloc(sizeof(*host), GFP_KERNEL); ++ if (!host) { ++ dev_err(&pdev->dev, "can't allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ host->cs = pd->chip_select; ++ ++ mtd = &host->mtd; ++ chip = &host->chip; ++ host->pdev = pdev; ++ dev_set_drvdata(&pdev->dev, host); ++ ++ chip->priv = host; ++ mtd->priv = chip; ++ mtd->name = dev_name(&pdev->dev); ++ mtd->owner = THIS_MODULE; ++ mtd->dev.parent = &pdev->dev; ++ ++ chip->IO_ADDR_R = (void *)0xdeadbeef; ++ chip->IO_ADDR_W = (void *)0xdeadbeef; ++ ++ chip->cmd_ctrl = iproc_nand_cmd_ctrl; ++ chip->cmdfunc = iproc_nand_cmdfunc; ++ chip->waitfunc = iproc_nand_waitfunc; ++ chip->read_byte = iproc_nand_read_byte; ++ chip->read_buf = iproc_nand_read_buf; ++ chip->verify_buf = iproc_nand_verify_buf; ++ ++ chip->ecc.mode = NAND_ECC_HW; ++ chip->ecc.size = 512; ++ chip->ecc.layout = &iproc_nand_oob_layout; ++ chip->ecc.read_page = (void *) iproc_nand_read_page; ++ chip->ecc.read_subpage = iproc_nand_read_subpage; ++ chip->ecc.write_page = (void *) iproc_nand_write_page; ++ chip->ecc.read_page_raw = (void *) iproc_nand_read_page_raw; ++ chip->ecc.write_page_raw = (void *) iproc_nand_write_page_raw; ++ ++#ifdef NAND_BBT_USE_FLASH ++ /* Patched MTD implementation */ ++ chip->ecc.write_oob_raw = iproc_nand_write_oob_raw; ++ chip->ecc.read_oob_raw = (void *) iproc_nand_read_oob_raw; ++#endif ++ ++ chip->ecc.read_oob = (void *) iproc_nand_read_oob; ++ chip->ecc.write_oob = iproc_nand_write_oob; ++ ++ chip->controller = &ctrl.controller; ++ ++ if (iproc_check_exceptions(mtd) && nand_scan_ident(mtd, 1, NULL)) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_SKIP_BBTSCAN; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) ++ chip->options |= NAND_NO_AUTOINCR; ++#endif ++ ++#ifdef NAND_BBT_USE_FLASH ++ /* patched MTD implementation */ ++ chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; ++#else /* Standard MTD implementation */ ++ chip->options |= NAND_USE_FLASH_BBT; ++#ifdef NAND_USE_FLASH_BBT_NO_OOB ++ chip->options |= NAND_USE_FLASH_BBT_NO_OOB; ++#endif /* NAND_USE_FLASH_BBT_NO_OOB */ ++#endif /* NAND_BBT_USE_FLASH */ ++ ++ if (iproc_nand_setup_dev(host, pd) || nand_scan_tail(mtd) || ++ chip->scan_bbt(mtd)) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) ++ mtd_device_parse_register(mtd, NULL, NULL, pd->parts, pd->nr_parts); ++#else ++#ifdef CONFIG_MTD_PARTITIONS ++ nr_parts = parse_mtd_partitions(mtd, part_probe_types, &parts, 0); ++ if (nr_parts <= 0) { ++ nr_parts = pd->nr_parts; ++ parts = pd->parts; ++ } ++ ++ if (nr_parts) ++ add_mtd_partitions(mtd, parts, nr_parts); ++ else ++#endif ++ add_mtd_device(mtd); ++#endif ++ ++ return 0; ++ ++err1: ++ kfree(host); ++ return ret; ++} ++ ++static int __devexit ++iproc_nand_remove(struct platform_device *pdev) ++{ ++ struct iproc_nand_host *host = dev_get_drvdata(&pdev->dev); ++ struct mtd_info *mtd = &host->mtd; ++ ++ nand_release(mtd); ++ dev_set_drvdata(&pdev->dev, NULL); ++ kfree(host); ++ ++ return 0; ++} ++ ++/*********************************************************************** ++ * Platform driver setup (per controller) ++ ***********************************************************************/ ++static struct platform_driver iproc_nand_driver = { ++ .probe = iproc_nand_probe, ++ .remove = __devexit_p(iproc_nand_remove), ++ .driver = { ++ .name = "nand_iproc", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init iproc_nand_init(void) ++{ ++ int err = -ENODEV; ++ ++ init_completion(&ctrl.done); ++ spin_lock_init(&ctrl.controller.lock); ++ init_waitqueue_head(&ctrl.controller.wq); ++ ctrl.cmd_pending = 0; ++ ctrl.boot_inited = 1; ++ ++ /* Initialize registers and IRQ */ ++ ctrl.nand_regs = ctrl.nand_intr_regs = ctrl.idm_nand_regs = NULL; ++ ctrl.nand_regs = (volatile void *)ioremap(NAND_NAND_FLASH_REV, 0x1000); ++ if (!ctrl.nand_regs) { ++ printk(KERN_ERR "%s: can't ioremap\n", DRV_NAME); ++ err = -EIO; ++ goto err; ++ } ++ ctrl.nand_intr_regs = ctrl.nand_regs + ++ (NAND_DIRECT_READ_RD_MISS - NAND_NAND_FLASH_REV); ++ ctrl.idm_nand_regs = (volatile void *)ioremap(IPROC_IDM_NAND_REG_BASE, 4); ++ if (!ctrl.idm_nand_regs) { ++ printk(KERN_ERR "%s: can't ioremap\n", DRV_NAME); ++ err = -EIO; ++ goto err; ++ } ++ ctrl.irq = IPROC_NAND_IRQ_START; ++ DBG("%s: nand_regs - %p\n", __func__, ctrl.nand_regs); ++ DBG("%s: nand_intr_regs - %p\n", __func__, ctrl.nand_intr_regs); ++ DBG("%s: idm_nand_regs - %p\n", __func__, ctrl.idm_nand_regs); ++ DBG("%s: irq - %d\n", __func__, ctrl.irq); ++ ++ /* If bootloader has initialized it, auto-config should be cleared */ ++ if (NAND_REG_RD(NCREG_CS_NAND_SELECT) & ++ NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG) { ++ ctrl.boot_inited = 0; ++ } ++ ++ /* Perform basic controller initialization */ ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_AUTO_DEVID_CONFIG); ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_DIRECT_ACCESS_CS_MASK); ++ NAND_REG_UNSET(NCREG_CS_NAND_XOR, NCFLD_CS_NAND_XOR_CS_MASK); ++ if (wp_on == 2) { ++ /* Permanently remove write-protection */ ++ NAND_REG_UNSET(NCREG_CS_NAND_SELECT, NCFLD_CS_NAND_SELECT_WP); ++ } ++ ++ /* Attach IRQ handler */ ++ NAND_ACK_IRQ(NCINTR_CTLRDY); ++ NAND_ENABLE_IRQ(NCINTR_CTLRDY); ++ err = request_irq((unsigned int)ctrl.irq, iproc_nand_irq, 0, ++ DRV_NAME, &ctrl); ++ if (err < 0) { ++ printk(KERN_ERR "%s: unable to allocate IRQ (error %d)\n", DRV_NAME, err); ++ goto err; ++ } ++ ++ err = platform_driver_register(&iproc_nand_driver); ++ if (err < 0) { ++ printk(KERN_ERR "%s: can't register platform driver " ++ "(error %d)\n", DRV_NAME, err); ++ free_irq(ctrl.irq, &ctrl); ++ goto err; ++ } ++ ++ printk(KERN_INFO DRV_NAME ": NAND controller driver is loaded\n"); ++ return 0; ++ ++err: ++ NAND_DISABLE_IRQ(NCINTR_CTLRDY); ++ if (ctrl.idm_nand_regs) { ++ iounmap(ctrl.idm_nand_regs); ++ ctrl.idm_nand_regs = NULL; ++ } ++ ctrl.nand_intr_regs = NULL; ++ if (ctrl.nand_regs) { ++ iounmap(ctrl.nand_regs); ++ ctrl.nand_regs = NULL; ++ } ++ return err; ++} ++ ++static void __exit iproc_nand_exit(void) ++{ ++ platform_driver_unregister(&iproc_nand_driver); ++ free_irq(ctrl.irq, &ctrl); ++ NAND_DISABLE_IRQ(NCINTR_CTLRDY); ++ if (ctrl.idm_nand_regs) { ++ iounmap(ctrl.idm_nand_regs); ++ ctrl.idm_nand_regs = NULL; ++ } ++ ctrl.nand_intr_regs = NULL; ++ if (ctrl.nand_regs) { ++ iounmap(ctrl.nand_regs); ++ ctrl.nand_regs = NULL; ++ } ++} ++ ++module_init(iproc_nand_init); ++module_exit(iproc_nand_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("NAND driver for iProc chips"); +diff --git a/drivers/bcmdrivers/pmu/.gitignore b/drivers/bcmdrivers/pmu/.gitignore +new file mode 100644 +index 0000000..af7303c +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_pmu.o.cmd ++/.iproc-pmu.o.cmd ++/built-in.o ++/iproc_pmu.o ++/iproc-pmu.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/pmu/Kconfig b/drivers/bcmdrivers/pmu/Kconfig +new file mode 100644 +index 0000000..8b09c0c +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/Kconfig +@@ -0,0 +1,9 @@ ++ ++config IPROC_PMU ++ tristate "Iproc PMU support" ++ depends on ARCH_IPROC ++ default y ++ help ++ Iproc PMU support ++ This config provides kernel-side support for iProc PMU description. ++ Its generic driver is perf_event.c +diff --git a/drivers/bcmdrivers/pmu/Makefile b/drivers/bcmdrivers/pmu/Makefile +new file mode 100644 +index 0000000..b491218 +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/Makefile +@@ -0,0 +1,8 @@ ++# iproc TDM support ++ ++EXTRA_CFLAGS += -I$(BCMDRIVERS_DIR)/gmac/src/include ++KBUILD_CFLAGS += -DBCMDRIVER -Dlinux ++ ++iproc_pmu-objs := iproc-pmu.o ++ ++obj-$(CONFIG_IPROC_PMU) += iproc_pmu.o +diff --git a/drivers/bcmdrivers/pmu/iproc-pmu.c b/drivers/bcmdrivers/pmu/iproc-pmu.c +new file mode 100644 +index 0000000..83e1aec +--- /dev/null ++++ b/drivers/bcmdrivers/pmu/iproc-pmu.c +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * PMU device description to Iproc ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct resource iproc_pmu_resource = { ++ .start = BCM_INT_ID_IHOST_PMU, ++ .end = BCM_INT_ID_IHOST_PMU+1, ++ .flags = IORESOURCE_IRQ, ++}; ++ ++ ++static struct platform_device iproc_pmu_device = { ++ .name = "arm-pmu", ++ .id = ARM_PMU_DEVICE_CPU, ++ .dev = { ++ .init_name = "arm-pmu", ++ }, ++ .num_resources = 1, ++ .resource = &iproc_pmu_resource, ++}; ++ ++ ++static int __init iproc_pmu_init(void) ++{ ++ int ret; ++ printk(KERN_INFO "Registering iproc_pmu_device\n"); ++ ret = platform_device_register(&iproc_pmu_device); ++ return ret; ++} ++module_init(iproc_pmu_init); ++ ++ ++/* Module information */ ++MODULE_DESCRIPTION("IPROC PMU Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/pwm/.gitignore b/drivers/bcmdrivers/pwm/.gitignore +new file mode 100644 +index 0000000..6e1da9b +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_pwm.o.cmd ++/.iproc_pwmc.o.cmd ++/built-in.o ++/iproc_pwm.o ++/iproc_pwmc.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/pwm/Kconfig b/drivers/bcmdrivers/pwm/Kconfig +new file mode 100644 +index 0000000..c3bf727 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_PWM ++ tristate "PWM support" ++ depends on ARCH_IPROC ++ default n ++ help ++ Add PWM support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/pwm/Makefile b/drivers/bcmdrivers/pwm/Makefile +new file mode 100644 +index 0000000..18ac980 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_PWM) += iproc_pwm.o ++iproc_pwm-objs := iproc_pwmc.o +diff --git a/drivers/bcmdrivers/pwm/iproc_pwmc.c b/drivers/bcmdrivers/pwm/iproc_pwmc.c +new file mode 100644 +index 0000000..4ea9255 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/iproc_pwmc.c +@@ -0,0 +1,411 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 5) ++#include "iproc_pwmc_3x.c" ++#else ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++#define IPROC_PWM_CHANNEL_CNT 4 ++#define PWM_PRESCALER_MAX 63 /* 6 bits field */ ++ ++ ++#define PWM_CTL_ENABLE_SHIFT (0) ++#define PWM_CTL_POLARITY_SHIFT (8) ++ ++#define PWM_PRESCALE_PWM3_PRESCALE_SHIFT (0) ++#define PWM_PRESCALE_PWM3_PRESCALE_MASK (0x0000003F) ++#define PWM_PRESCALE_PWM2_PRESCALE_SHIFT (6) ++#define PWM_PRESCALE_PWM2_PRESCALE_MASK (0x00000FC0) ++#define PWM_PRESCALE_PWM1_PRESCALE_SHIFT (12) ++#define PWM_PRESCALE_PWM1_PRESCALE_MASK (0x0003F000) ++#define PWM_PRESCALE_PWM0_PRESCALE_SHIFT (18) ++#define PWM_PRESCALE_PWM0_PRESCALE_MASK (0x00FC0000) ++ ++#define PWM_DUTY_HI_CNT0_SHIFT (0) ++#define PWM_DUTY_HI_CNT0_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT1_SHIFT (0) ++#define PWM_DUTY_HI_CNT1_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT2_SHIFT (0) ++#define PWM_DUTY_HI_CNT2_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT3_SHIFT (0) ++#define PWM_DUTY_HI_CNT3_MASK (0xFFFF) ++ ++#define PWM_PERIOD_CNT0_SHIFT (0) ++#define PWM_PERIOD_CNT0_MASK (0xFFFF) ++#define PWM_PERIOD_CNT1_SHIFT (0) ++#define PWM_PERIOD_CNT1_MASK (0xFFFF) ++#define PWM_PERIOD_CNT2_SHIFT (0) ++#define PWM_PERIOD_CNT2_MASK (0xFFFF) ++#define PWM_PERIOD_CNT3_SHIFT (0) ++#define PWM_PERIOD_CNT3_MASK (0xFFFF) ++ ++ ++struct pwm_reg_def { ++ u32 mask ; ++ u32 shift ; ++ u32 offset ; ++} ; ++ ++#define PWM_REG_DEF(c, m, s, a) \ ++ [c] = { \ ++ .mask = m, \ ++ .shift = s, \ ++ .offset = a \ ++ } ++ ++static const ++struct pwm_reg_def pwm_chan_pre_scaler_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PRESCALE_PWM0_PRESCALE_MASK, ++ PWM_PRESCALE_PWM0_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(1, PWM_PRESCALE_PWM1_PRESCALE_MASK, ++ PWM_PRESCALE_PWM1_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(2, PWM_PRESCALE_PWM2_PRESCALE_MASK, ++ PWM_PRESCALE_PWM2_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(3, PWM_PRESCALE_PWM3_PRESCALE_MASK, ++ PWM_PRESCALE_PWM3_PRESCALE_SHIFT, CCB_PWM_PRESCALE_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_period_cnt_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PERIOD_CNT0_MASK, ++ PWM_PERIOD_CNT0_SHIFT, CCB_PWM_PERIOD_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_PERIOD_CNT1_MASK, ++ PWM_PERIOD_CNT1_SHIFT, CCB_PWM_PERIOD_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_PERIOD_CNT2_MASK, ++ PWM_PERIOD_CNT2_SHIFT, CCB_PWM_PERIOD_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_PERIOD_CNT3_MASK, ++ PWM_PERIOD_CNT3_SHIFT, CCB_PWM_PERIOD_COUNT3_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_duty_cycle_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_DUTY_HI_CNT0_MASK, ++ PWM_DUTY_HI_CNT0_SHIFT, CCB_PWM_DUTY_HI_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_DUTY_HI_CNT1_MASK, ++ PWM_DUTY_HI_CNT1_SHIFT, CCB_PWM_DUTY_HI_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_DUTY_HI_CNT2_MASK, ++ PWM_DUTY_HI_CNT2_SHIFT, CCB_PWM_DUTY_HI_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_DUTY_HI_CNT3_MASK, ++ PWM_DUTY_HI_CNT3_SHIFT, CCB_PWM_DUTY_HI_COUNT3_BASE), ++} ; ++ ++ ++struct iproc_pwmc { ++ struct pwm_device *p[IPROC_PWM_CHANNEL_CNT]; ++ struct pwm_device_ops ops; ++ void __iomem *iobase; ++ struct clk *clk; ++}; ++ ++ ++static int iproc_get_chan(const struct iproc_pwmc *ap, const struct pwm_device *p) ++{ ++ int chan; ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) ++ if (p == ap->p[chan]) ++ return chan; ++ BUG(); ++ return 0; ++} ++ ++static void iproc_pwmc_clear_set_bit(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int shift, unsigned char en_dis) ++{ ++ unsigned long val = readl(ap->iobase + offset ) ; ++ ++ // Clear bit. ++ clear_bit(shift,&val) ; ++ if ( en_dis == 1 ) ++ set_bit(shift,&val); ++ ++ writel(val, (ap->iobase + offset )); ++} ++ ++ ++static void iproc_pwmc_set_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int wval) ++{ ++ unsigned int val = readl(ap->iobase + offset ) ; ++ ++ val = (val & ~mask) | ( wval << shift ) ; ++ writel(val, (ap->iobase + offset )); ++} ++ ++static void iproc_pwmc_get_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int *val) ++{ ++ *val = readl(ap->iobase + offset ) ; ++ *val = ( *val & mask ) >> shift ; ++} ++ ++ ++static void iproc_pwmc_start(const struct iproc_pwmc *ap, int chan) ++{ ++ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 1) ; ++} ++ ++static void iproc_pwmc_stop(const struct iproc_pwmc *ap, int chan) ++{ ++ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 0) ; ++ ++ ++} ++static void iproc_pwmc_config_polarity(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ struct pwm_device *p = ap->p[chan]; ++ ++ if ( c->polarity ){ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 1) ; ++ }else{ ++ iproc_pwmc_clear_set_bit(ap, CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 0) ; ++ } ++ p->polarity = c->polarity ? 1 : 0; ++ ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ ++} ++ ++ ++static void iproc_pwmc_config_duty_ticks(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ struct pwm_device *p = ap->p[chan]; ++ unsigned int pre_scaler = 0 ; ++ unsigned int duty_cnt = 0 ; ++ ++ iproc_pwmc_get_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, pwm_chan_pre_scaler_info[chan].shift, ++ &pre_scaler) ; ++ ++ /* Read prescaler value from register. */ ++ duty_cnt = c->duty_ticks / (pre_scaler + 1) ; ++ ++ /* program duty cycle. */ ++ iproc_pwmc_set_field(ap, pwm_chan_duty_cycle_info[chan].offset, ++ pwm_chan_duty_cycle_info[chan].mask, ++ pwm_chan_duty_cycle_info[chan].shift, duty_cnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ p->duty_ticks = c->duty_ticks; ++ ++} ++ ++static int iproc_pwmc_config_period_ticks(struct iproc_pwmc *ap, int chan, ++ struct pwm_config *c) ++{ ++ unsigned int pcnt ; ++ unsigned char pre_scaler = 0 ; ++ struct pwm_device *p = ap->p[chan]; ++ ++ pre_scaler = c->period_ticks / 0xFFFF ; ++ if ( pre_scaler > PWM_PRESCALER_MAX ) ++ pre_scaler = PWM_PRESCALER_MAX ; ++ ++ pcnt = c->period_ticks / (pre_scaler + 1) ; ++ ++ /* programe prescaler */ ++ iproc_pwmc_set_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, ++ pwm_chan_pre_scaler_info[chan].shift, pre_scaler) ; ++ ++ /* program period count. */ ++ iproc_pwmc_set_field(ap, pwm_chan_period_cnt_info[chan].offset, ++ pwm_chan_period_cnt_info[chan].mask, ++ pwm_chan_period_cnt_info[chan].shift, pcnt) ; ++ if (BIT(chan) & (readl(ap->iobase + CCB_PWM_CTL_BASE)&0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(ap, chan) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(ap, chan) ; ++ } ++ ++ p->period_ticks = c->period_ticks; ++ ++ return 0; ++} ++ ++static int iproc_pwmc_request(struct pwm_device *p) ++{ ++ struct iproc_pwmc *ap = pwm_get_drvdata(p); ++ int chan = iproc_get_chan(ap, p); ++ ++ /* 1M */ ++ p->tick_hz = 1000000UL; ++ iproc_pwmc_stop(ap,chan); ++ ++ return 0; ++} ++ ++static int iproc_pwmc_config(struct pwm_device *p, struct pwm_config *c) ++{ ++ struct iproc_pwmc *ap = pwm_get_drvdata(p); ++ int chan = iproc_get_chan(ap, p); ++ int ret; ++ ++ if (test_bit(PWM_CONFIG_PERIOD_TICKS, &c->config_mask)) { ++ ret = iproc_pwmc_config_period_ticks(ap, chan, c); ++ if (ret) ++ return ret; ++ if (!test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) { ++ struct pwm_config d = { ++ .config_mask = PWM_CONFIG_DUTY_TICKS, ++ .duty_ticks = p->duty_ticks, ++ }; ++ iproc_pwmc_config_duty_ticks(ap, chan, &d); ++ } ++ } ++ ++ if (test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) ++ iproc_pwmc_config_duty_ticks(ap, chan, c); ++ ++ if (test_bit(PWM_CONFIG_POLARITY, &c->config_mask)) ++ iproc_pwmc_config_polarity(ap, chan, c); ++ ++ if (test_bit(PWM_CONFIG_START, &c->config_mask)) ++ iproc_pwmc_start(ap, chan); ++ ++ if (test_bit(PWM_CONFIG_STOP, &c->config_mask)) ++ iproc_pwmc_stop(ap, chan); ++ ++ return 0; ++} ++ ++ ++static const struct pwm_device_ops iproc_pwm_ops = { ++ .request = iproc_pwmc_request, ++ .config = iproc_pwmc_config, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static int __devinit iproc_pwmc_probe(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ int chan; ++ int ret = 0; ++ ++ ap = kzalloc(sizeof(*ap), GFP_KERNEL); ++ if (!ap) { ++ ret = -ENOMEM; ++ goto err_iproc_pwmc_alloc; ++ } ++ ++ platform_set_drvdata(pdev, ap); ++ ++ ap->iobase = ioremap_nocache(r->start, resource_size(r)); ++ if (!ap->iobase) { ++ ret = -ENODEV; ++ goto err_ioremap; ++ } ++ printk(KERN_INFO "iproc_pwmc_probe iobase %p phys:%x\n", ++ ap->iobase,r->start); ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ ap->p[chan] = pwm_register(&iproc_pwm_ops, &pdev->dev, "%s:%d", ++ dev_name(&pdev->dev), chan); ++ if (IS_ERR_OR_NULL(ap->p[chan])) ++ goto err_pwm_register; ++ pwm_set_drvdata(ap->p[chan], ap); ++ } ++ ++ return 0; ++ ++err_pwm_register: ++ while (--chan > 0) ++ pwm_unregister(ap->p[chan]); ++ ++ iounmap(ap->iobase); ++err_ioremap: ++ platform_set_drvdata(pdev, NULL); ++ kfree(ap); ++err_iproc_pwmc_alloc: ++ printk(KERN_ERR "%s: error, returning %d\n", __func__, ret); ++return ret; ++} ++ ++static int __devexit iproc_pwmc_remove(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap = platform_get_drvdata(pdev); ++ int chan; ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) ++ pwm_unregister(ap->p[chan]); ++ ++ iounmap(ap->iobase); ++ ++ kfree(ap); ++ return 0; ++} ++ ++static struct platform_driver iproc_pwmc_driver = { ++ .driver = { ++ .name = "iproc_pwmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = iproc_pwmc_probe, ++ .remove = __devexit_p(iproc_pwmc_remove), ++}; ++ ++static int __init iproc_pwmc_init(void) ++{ ++ return platform_driver_register(&iproc_pwmc_driver); ++} ++ ++static void __exit iproc_pwmc_exit(void) ++{ ++ platform_driver_unregister(&iproc_pwmc_driver); ++} ++module_init(iproc_pwmc_init); ++module_exit(iproc_pwmc_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Driver for iProc PWMC"); ++MODULE_LICENSE("GPL"); ++ ++#endif +diff --git a/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c b/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c +new file mode 100644 +index 0000000..c410014 +--- /dev/null ++++ b/drivers/bcmdrivers/pwm/iproc_pwmc_3x.c +@@ -0,0 +1,575 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_DEBUG_FS ++#include ++#endif ++ ++#include ++ ++ ++#define IPROC_PWM_CHANNEL_CNT 4 ++#define PWM_PRESCALER_MAX 63 /* 6 bits field */ ++ ++ ++#define PWM_CTL_ENABLE_SHIFT (0) ++#define PWM_CTL_POLARITY_SHIFT (8) ++ ++#define PWM_PRESCALE_PWM3_PRESCALE_SHIFT (0) ++#define PWM_PRESCALE_PWM3_PRESCALE_MASK (0x0000003F) ++#define PWM_PRESCALE_PWM2_PRESCALE_SHIFT (6) ++#define PWM_PRESCALE_PWM2_PRESCALE_MASK (0x00000FC0) ++#define PWM_PRESCALE_PWM1_PRESCALE_SHIFT (12) ++#define PWM_PRESCALE_PWM1_PRESCALE_MASK (0x0003F000) ++#define PWM_PRESCALE_PWM0_PRESCALE_SHIFT (18) ++#define PWM_PRESCALE_PWM0_PRESCALE_MASK (0x00FC0000) ++ ++#define PWM_DUTY_HI_CNT0_SHIFT (0) ++#define PWM_DUTY_HI_CNT0_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT1_SHIFT (0) ++#define PWM_DUTY_HI_CNT1_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT2_SHIFT (0) ++#define PWM_DUTY_HI_CNT2_MASK (0xFFFF) ++#define PWM_DUTY_HI_CNT3_SHIFT (0) ++#define PWM_DUTY_HI_CNT3_MASK (0xFFFF) ++ ++#define PWM_PERIOD_CNT0_SHIFT (0) ++#define PWM_PERIOD_CNT0_MASK (0xFFFF) ++#define PWM_PERIOD_CNT1_SHIFT (0) ++#define PWM_PERIOD_CNT1_MASK (0xFFFF) ++#define PWM_PERIOD_CNT2_SHIFT (0) ++#define PWM_PERIOD_CNT2_MASK (0xFFFF) ++#define PWM_PERIOD_CNT3_SHIFT (0) ++#define PWM_PERIOD_CNT3_MASK (0xFFFF) ++ ++ ++struct pwm_reg_def { ++ u32 mask ; ++ u32 shift ; ++ u32 offset ; ++} ; ++ ++#define PWM_REG_DEF(c, m, s, a) \ ++ [c] = { \ ++ .mask = m, \ ++ .shift = s, \ ++ .offset = a \ ++ } ++ ++static const ++struct pwm_reg_def pwm_chan_pre_scaler_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PRESCALE_PWM0_PRESCALE_MASK, ++ PWM_PRESCALE_PWM0_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(1, PWM_PRESCALE_PWM1_PRESCALE_MASK, ++ PWM_PRESCALE_PWM1_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(2, PWM_PRESCALE_PWM2_PRESCALE_MASK, ++ PWM_PRESCALE_PWM2_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++ PWM_REG_DEF(3, PWM_PRESCALE_PWM3_PRESCALE_MASK, ++ PWM_PRESCALE_PWM3_PRESCALE_SHIFT, IPROC_CCB_PWM_PRESCALE_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_period_cnt_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_PERIOD_CNT0_MASK, ++ PWM_PERIOD_CNT0_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_PERIOD_CNT1_MASK, ++ PWM_PERIOD_CNT1_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_PERIOD_CNT2_MASK, ++ PWM_PERIOD_CNT2_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_PERIOD_CNT3_MASK, ++ PWM_PERIOD_CNT3_SHIFT, IPROC_CCB_PWM_PERIOD_COUNT3_BASE), ++} ; ++ ++static const ++struct pwm_reg_def pwm_chan_duty_cycle_info[IPROC_PWM_CHANNEL_CNT] = { ++ PWM_REG_DEF(0, PWM_DUTY_HI_CNT0_MASK, ++ PWM_DUTY_HI_CNT0_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT0_BASE), ++ PWM_REG_DEF(1, PWM_DUTY_HI_CNT1_MASK, ++ PWM_DUTY_HI_CNT1_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT1_BASE), ++ PWM_REG_DEF(2, PWM_DUTY_HI_CNT2_MASK, ++ PWM_DUTY_HI_CNT2_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT2_BASE), ++ PWM_REG_DEF(3, PWM_DUTY_HI_CNT3_MASK, ++ PWM_DUTY_HI_CNT3_SHIFT, IPROC_CCB_PWM_DUTY_HI_COUNT3_BASE), ++} ; ++ ++#ifdef CONFIG_DEBUG_FS ++struct iproc_pwm_config_debug_fs{ ++ struct dentry *period; ++ struct dentry *duty; ++ struct dentry *polarity; ++ struct dentry *run; ++}; ++#endif ++ ++struct iproc_pwm_config { ++ struct device *dev; ++ struct pwm_device *pwm; ++ int pwm_id; ++ int duty_ns; ++ int period_ns; ++ u32 duty_ticks; ++ u32 period_ticks; ++ u8 polarity; ++ int running; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfs_entry; ++ struct iproc_pwm_config_debug_fs config_entry; ++#endif ++ ++}; ++ ++ ++struct iproc_pwmc { ++ void __iomem *iobase; ++ unsigned long tick_hz; ++ struct pwm_chip chip; ++ struct iproc_pwm_config *config[IPROC_PWM_CHANNEL_CNT]; ++}; ++ ++ ++#ifdef CONFIG_DEBUG_FS ++static int __init iproc_pwmc_debugfs_init(void); ++void iproc_pwmc_debugfs_add_chan(struct iproc_pwmc *ap, int chan); ++ ++static struct dentry *debugfs_base; ++ ++static int _debug_pwm_config_set(void *data, u64 val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ if (val) { ++ iproc_pwmc_config_polarity(config->pwm->chip, config->pwm, config->polarity); ++ pwm_config(config->pwm, config->duty_ns, config->period_ns); ++ pwm_enable(config->pwm); ++ config->running = 1; ++ } else { ++ pwm_disable(config->pwm); ++ config->running = 0; ++ } ++ return 0; ++} ++static int _debug_pwm_config_get(void *data, u64 *val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ *val = config->running; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(iproc_pwm_config_fop, _debug_pwm_config_get, ++ _debug_pwm_config_set, "%llu\n"); ++ ++static int _debug_pwm_export_set(void *data, u64 val) ++{ ++ ++ struct iproc_pwm_config *config = data; ++ struct pwm_device *pwm; ++ char pwm_id[16]; ++ ++ sprintf(pwm_id, "pwm-%d", config->pwm_id); ++ ++ if (val) { ++ pwm = pwm_get(config->dev,pwm_id); ++ config->pwm = pwm; ++ config->config_entry.polarity = debugfs_create_u8("polarity", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->polarity); ++ config->config_entry.period = debugfs_create_u32("period_ns", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->period_ns); ++ config->config_entry.duty = debugfs_create_u32("duty_ns", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ &config->duty_ns); ++ config->config_entry.run = debugfs_create_file("run", S_IRUGO | S_IWUSR, config->debugfs_entry, ++ data, &iproc_pwm_config_fop); ++ ++ } else { ++ debugfs_remove(config->config_entry.polarity); ++ debugfs_remove(config->config_entry.period); ++ debugfs_remove(config->config_entry.duty); ++ debugfs_remove(config->config_entry.run); ++ pwm_disable(config->pwm); ++ pwm_put(config->pwm); ++ config->pwm = NULL; ++ } ++ ++ return 0; ++} ++static int _debug_pwm_export_get(void *data, u64 *val) ++{ ++ struct iproc_pwm_config *config = data; ++ ++ if(config->pwm){ ++ *val = 1; ++ } else { ++ *val = 0; ++ } ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(iproc_pwm_export_fop, _debug_pwm_export_get, ++ _debug_pwm_export_set, "%llu\n"); ++ ++void iproc_pwmc_debugfs_add_chan(struct iproc_pwmc *ap, int chan) ++{ ++ char fname[16]; ++ ++ if (!debugfs_base) ++ return; ++ ++ ++ sprintf(fname, "iproc-pwm%d", chan); ++ ap->config[chan]->debugfs_entry = debugfs_create_dir(fname, debugfs_base); ++ ++ ++ debugfs_create_file("export", S_IRUGO | S_IWUSR, ap->config[chan]->debugfs_entry, ++ ap->config[chan], &iproc_pwm_export_fop); ++ ++} ++static int __init iproc_pwmc_debugfs_init(void) ++{ ++ ++ debugfs_base = debugfs_create_dir("iproc", NULL); ++ if (!debugfs_base) ++ return -ENOMEM; ++ ++ return 0; ++} ++#endif ++ ++ ++static int iproc_get_chan(const struct iproc_pwmc *ap, const struct pwm_device *p) ++{ ++ int chan; ++ ++ chan = p->hwpwm; ++ return chan; ++} ++ ++static void iproc_pwmc_clear_set_bit(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int shift, unsigned char en_dis) ++{ ++ unsigned long val = readl(ap->iobase + offset ) ; ++ ++ // Clear bit. ++ clear_bit(shift,&val) ; ++ if ( en_dis == 1 ) ++ set_bit(shift,&val); ++ ++ writel(val, (ap->iobase + offset )); ++} ++ ++ ++static void iproc_pwmc_set_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int wval) ++{ ++ unsigned int val = readl(ap->iobase + offset ) ; ++ ++ val = (val & ~mask) | ( wval << shift ) ; ++ writel(val, (ap->iobase + offset )); ++} ++ ++static void iproc_pwmc_get_field(const struct iproc_pwmc *ap, unsigned int offset, ++ unsigned int mask, unsigned int shift, unsigned int *val) ++{ ++ *val = readl(ap->iobase + offset ) ; ++ *val = ( *val & mask ) >> shift ; ++} ++ ++ ++#define to_iproc_chip(chip) container_of(chip, struct iproc_pwmc, chip) ++static int iproc_pwmc_start(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, pwm); ++ ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 1) ; ++ ++ return 0; ++} ++ ++static void iproc_pwmc_stop(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, pwm); ++ ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_ENABLE_SHIFT + chan), 0) ; ++ ++} ++static int iproc_pwmc_request(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ iproc_pwmc_stop(chip, pwm); ++ return 0; ++} ++ ++static void iproc_pwmc_config_duty_ticks(struct iproc_pwmc *ap, int chan, ++ unsigned long duty_ticks) ++{ ++ /*struct pwm_device *p = ap->p[chan];*/ ++ unsigned int pre_scaler = 0 ; ++ unsigned int duty_cnt = 0 ; ++ ++ iproc_pwmc_get_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, pwm_chan_pre_scaler_info[chan].shift, ++ &pre_scaler) ; ++ ++ /* Read prescaler value from register. */ ++ duty_cnt = duty_ticks / (pre_scaler + 1) ; ++ ++ /* program duty cycle. */ ++ iproc_pwmc_set_field(ap, pwm_chan_duty_cycle_info[chan].offset, ++ pwm_chan_duty_cycle_info[chan].mask, ++ pwm_chan_duty_cycle_info[chan].shift, duty_cnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ++} ++ ++static int iproc_pwmc_config_period_ticks(struct iproc_pwmc *ap, int chan, ++ unsigned long period_ticks) ++{ ++ unsigned int pcnt ; ++ unsigned char pre_scaler = 0 ; ++ /*struct pwm_device *p = ap->p[chan]; */ ++ ++ pre_scaler = period_ticks / 0xFFFF ; ++ if ( pre_scaler > PWM_PRESCALER_MAX ) ++ pre_scaler = PWM_PRESCALER_MAX ; ++ ++ pcnt = period_ticks / (pre_scaler + 1) ; ++ ++ /* programe prescaler */ ++ iproc_pwmc_set_field(ap, pwm_chan_pre_scaler_info[chan].offset, ++ pwm_chan_pre_scaler_info[chan].mask, ++ pwm_chan_pre_scaler_info[chan].shift, pre_scaler) ; ++ ++ /* program period count. */ ++ iproc_pwmc_set_field(ap, pwm_chan_period_cnt_info[chan].offset, ++ pwm_chan_period_cnt_info[chan].mask, ++ pwm_chan_period_cnt_info[chan].shift, pcnt) ; ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ++ return 0; ++} ++static unsigned long pwm_ns_to_ticks(struct iproc_pwmc *ap, unsigned long nsecs) ++{ ++ unsigned long long ticks; ++ ++ ticks = nsecs; ++ ticks *= ap->tick_hz; ++ do_div(ticks,1000000000UL); ++ ++ return ticks; ++} ++ ++int iproc_pwmc_config_polarity(struct pwm_chip *chip, ++ struct pwm_device *p, int polarity) ++{ ++ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, p); ++ ++ if (polarity) { ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 1) ; ++ } else { ++ iproc_pwmc_clear_set_bit(ap, IPROC_CCB_PWM_CTL_BASE, ++ (PWM_CTL_POLARITY_SHIFT + chan), 0) ; ++ } ++ ++ if (BIT(chan) & (readl(ap->iobase + IPROC_CCB_PWM_CTL_BASE) & 0xf)) { ++ /* disable channel */ ++ iproc_pwmc_stop(&ap->chip, ap->config[chan]->pwm) ; ++ udelay(1); ++ /* enable channel. */ ++ iproc_pwmc_start(&ap->chip, ap->config[chan]->pwm) ; ++ } ++ ap->config[chan]->polarity = polarity; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(iproc_pwmc_config_polarity); ++ ++ ++static int iproc_pwmc_config(struct pwm_chip *chip, ++ struct pwm_device *p, int duty_ns, int period_ns) ++{ ++ struct iproc_pwmc *ap = to_iproc_chip(chip); ++ int chan = iproc_get_chan(ap, p); ++ int ret; ++ unsigned long period_ticks, duty_ticks; ++ ++ period_ticks = pwm_ns_to_ticks(ap, period_ns); ++ ret = iproc_pwmc_config_period_ticks(ap, chan, period_ticks); ++ if (ret) ++ return ret; ++ ap->config[chan]->period_ticks = period_ticks; ++ ap->config[chan]->period_ns = period_ns; ++ ++ duty_ticks = pwm_ns_to_ticks(ap, duty_ns); ++ iproc_pwmc_config_duty_ticks(ap, chan, duty_ticks); ++ ap->config[chan]->duty_ticks = duty_ticks; ++ ap->config[chan]->duty_ns = duty_ns; ++ ++ return 0; ++} ++ ++ ++static const struct pwm_ops iproc_pwm_ops = { ++ .enable = iproc_pwmc_start, ++ .disable = iproc_pwmc_stop, ++ .request = iproc_pwmc_request, ++ .free = iproc_pwmc_stop, ++ .config = iproc_pwmc_config, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static int __devinit iproc_pwmc_probe(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ struct resource *r; ++ int ret = 0; ++ int chan; ++ ++ ap = devm_kzalloc(&pdev->dev, sizeof(*ap), GFP_KERNEL); ++ if (!ap) { ++ dev_err(&pdev->dev, "failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++#ifdef CONFIG_MACH_NSP ++ ap->tick_hz = 25000000UL; ++#else ++ ap->tick_hz = 1000000UL; ++#endif ++ ap->chip.ops = &iproc_pwm_ops; ++ ap->chip.dev = &pdev->dev; ++ ap->chip.base = -1; ++ ap->chip.npwm = IPROC_PWM_CHANNEL_CNT; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ dev_err(&pdev->dev, "no memory resource defined\n"); ++ return -ENODEV; ++ } ++ ++ ap->iobase = devm_request_and_ioremap(&pdev->dev, r); ++ if (!ap->iobase) { ++ return -EADDRNOTAVAIL; ++ } ++ printk(KERN_INFO "iproc_pwmc_probe iobase %p phys:%x\n", ++ ap->iobase,r->start); ++ ret = pwmchip_add(&ap->chip); ++ if (ret < 0) ++ return ret; ++ ++ platform_set_drvdata(pdev, ap); ++ ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ ap->config[chan] = kzalloc(sizeof(struct iproc_pwm_config), GFP_KERNEL); ++ ap->config[chan]->pwm_id = chan; ++ ap->config[chan]->dev = &pdev->dev; ++ } ++ ++ ++#ifdef CONFIG_DEBUG_FS ++ iproc_pwmc_debugfs_init(); ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++) { ++ iproc_pwmc_debugfs_add_chan(ap,chan); ++ } ++#endif ++ ++ return 0; ++ ++} ++ ++static int __devexit iproc_pwmc_remove(struct platform_device *pdev) ++{ ++ struct iproc_pwmc *ap; ++ int chan; ++ ++ ap = platform_get_drvdata(pdev); ++ ++#ifdef CONFIG_DEBUG_FS ++ if (debugfs_base) ++ debugfs_remove_recursive(debugfs_base); ++ ++#endif ++ ++ if (ap == NULL) ++ return -ENODEV; ++ ++ for (chan = 0; chan < IPROC_PWM_CHANNEL_CNT; chan++){ ++ kfree(ap->config[chan]); ++ } ++ pwmchip_remove(&ap->chip); ++ ++ devm_iounmap(&pdev->dev,ap->iobase); ++ kfree(ap); ++ ++ return 0; ++} ++ ++static struct platform_driver iproc_pwmc_driver = { ++ .driver = { ++ .name = "iproc_pwmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = iproc_pwmc_probe, ++ .remove = __devexit_p(iproc_pwmc_remove), ++}; ++ ++static int __init iproc_pwmc_init(void) ++{ ++ return platform_driver_register(&iproc_pwmc_driver); ++} ++ ++static void __exit iproc_pwmc_exit(void) ++{ ++ platform_driver_unregister(&iproc_pwmc_driver); ++} ++module_init(iproc_pwmc_init); ++module_exit(iproc_pwmc_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Driver for iProc PWMC"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/qspi/.gitignore b/drivers/bcmdrivers/qspi/.gitignore +new file mode 100644 +index 0000000..d03ee50 +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order ++/.iproc_qspi.o.cmd ++/.qspi_iproc.o.cmd ++/iproc_qspi.o ++/qspi_iproc.o +diff --git a/drivers/bcmdrivers/qspi/Kconfig b/drivers/bcmdrivers/qspi/Kconfig +new file mode 100644 +index 0000000..fac545c +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/Kconfig +@@ -0,0 +1,72 @@ ++menuconfig IPROC_QSPI ++ tristate "QSPI support" ++ depends on ARCH_IPROC ++ select SPI ++ select SPI_MASTER ++ select MTD ++ select MTD_M25P80 ++ select M25PXX_USE_FAST_READ ++ default n ++ help ++ This selects a driver for the iProc QSPI Controller (for serial flash). ++ ++ If unsure, say N. ++ ++if IPROC_QSPI ++ ++choice ++ prompt "Multi I/O SPI support" ++ default IPROC_QSPI_SINGLE_MODE ++ help ++ Number of (multi I/O) data lanes supported by the SPI flash. ++ ++config IPROC_QSPI_SINGLE_MODE ++ bool "Single lane" ++ help ++ Single lane. ++ ++config IPROC_QSPI_DUAL_MODE ++ bool "Dual mode" ++ help ++ Dual mode. ++ ++config IPROC_QSPI_QUAD_MODE ++ bool "Quad mode" ++ help ++ Quad mode. ++ ++endchoice ++ ++config IPROC_QSPI_MULTI_LANE_ADDR ++ bool "Use multi lanes also for address" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ default y ++ help ++ Use multi lanes also for address. ++ ++config IPROC_QSPI_READ_CMD ++ hex "Flash opcode for multi I/O read" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ range 0x00 0xff ++ default 0xbb if IPROC_QSPI_DUAL_MODE ++ default 0xeb ++ help ++ Flash opcode to send to flash for multip I/O read. ++ ++config IPROC_QSPI_READ_DUMMY_CYCLES ++ int "Dummy cycles for multi I/O read operation" ++ depends on IPROC_QSPI_DUAL_MODE || IPROC_QSPI_QUAD_MODE ++ range 0 255 ++ default 8 if IPROC_QSPI_DUAL_MODE ++ default 10 ++ help ++ Dummy cycles for flash read operation ++ ++config IPROC_QSPI_MAX_HZ ++ int "Maximal SPI clock in HZ" ++ range 1 1000000000 ++ default 62500000 ++ help ++ The maximal SPI clock (in Hz) supported by the flash. ++ ++endif # IPROC_QSPI +diff --git a/drivers/bcmdrivers/qspi/Makefile b/drivers/bcmdrivers/qspi/Makefile +new file mode 100644 +index 0000000..be164d1 +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o ++iproc_qspi-objs := qspi_iproc.o +diff --git a/drivers/bcmdrivers/qspi/qspi_iproc.c b/drivers/bcmdrivers/qspi/qspi_iproc.c +new file mode 100755 +index 0000000..2643787 +--- /dev/null ++++ b/drivers/bcmdrivers/qspi/qspi_iproc.c +@@ -0,0 +1,1807 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DBG(...) /* */ ++ ++/* ++ * Interrupts ++ */ ++ ++#define QSPI_INTR_COUNT (7) ++ ++#define QSPI_INTR_MSPI_HALTED_MASK (0x00000040) ++#define QSPI_INTR_MSPI_DONE_MASK (0x00000020) ++#define QSPI_INTR_BSPI_LR_OVERREAD_MASK (0x00000010) ++#define QSPI_INTR_BSPI_LR_SESSION_DONE_MASK (0x00000008) ++#define QSPI_INTR_BSPI_LR_IMPATIENT_MASK (0x00000004) ++#define QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK (0x00000002) ++#define QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK (0x00000001) ++ ++#define BSPI_LR_INTERRUPTS_DATA \ ++ (QSPI_INTR_BSPI_LR_SESSION_DONE_MASK | \ ++ QSPI_INTR_BSPI_LR_FULLNESS_REACHED_MASK) ++ ++#define BSPI_LR_INTERRUPTS_ERROR \ ++ (QSPI_INTR_BSPI_LR_OVERREAD_MASK | \ ++ QSPI_INTR_BSPI_LR_IMPATIENT_MASK | \ ++ QSPI_INTR_BSPI_LR_SESSION_ABORTED_MASK) ++ ++#define BSPI_LR_INTERRUPTS_ALL \ ++ (BSPI_LR_INTERRUPTS_ERROR | \ ++ BSPI_LR_INTERRUPTS_DATA) ++ ++#define SPBR_MIN 8U ++#define SPBR_MAX 255U ++#define DEFAULT_SPEED_HZ 25000000UL ++#define MSPI_REFCLK_SOURCE "c_clk125" /* To be doubled */ ++#define MSPI_REFCLK_SOURCE_DEVID "iproc_slow" ++ ++/* ++ * Flash opcode and parameters ++ */ ++#define OPCODE_RDID 0x9f ++#define OPCODE_WREN 0x06 ++#define OPCODE_WRDI 0x04 ++#define OPCODE_WRR 0x01 ++#define OPCODE_RCR 0x35 ++#define OPCODE_READ 0x03 ++#define OPCODE_RDSR 0x05 ++#define OPCODE_WRSR 0x01 ++#define OPCODE_RDFSR 0x70 ++#define OPCODE_FAST_READ 0x0B ++#define OPCODE_FAST_READ_4B 0x0C ++#define OPCODE_EN4B 0xB7 ++#define OPCODE_EX4B 0xE9 ++#define OPCODE_BRWR 0x17 ++ ++#define BSPI_WIDTH_1BIT 1 ++#define BSPI_WIDTH_2BIT 2 ++#define BSPI_WIDTH_4BIT 4 ++ ++#define BSPI_ADDRLEN_3BYTES 3 ++#define BSPI_ADDRLEN_4BYTES 4 ++ ++#define BSPI_FLASH_TYPE_SPANSION 0 ++#define BSPI_FLASH_TYPE_MACRONIX 1 ++#define BSPI_FLASH_TYPE_NUMONYX 2 ++#define BSPI_FLASH_TYPE_SST 3 ++#define BSPI_FLASH_TYPE_UNKNOWN -1 ++ ++/* ++ * Register masks/fields/values ++ */ ++#define QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK (0x00000002) ++#define QSPI_BSPI_RAF_CONTROL_START_MASK (0x00000001) ++#define QSPI_BSPI_RAF_CONTROL_CLEAR_MASK (0x00000002) ++#define QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK (0x00010000) ++#define QSPI_BSPI_BPP_MODE_BPP_MASK (0x00000100) ++#define QSPI_BSPI_FLEX_MODE_ENABLE_MASK (0x00000001) ++ ++ ++/* ++ * Module parameters ++ */ ++ ++/* Mulit I/O for read: 0 - single, 1 - dual, 2 - quad */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int io_mode = 0; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++#ifdef CONFIG_IPROC_QSPI_DUAL_MODE ++static int io_mode = 1; ++#else /* !CONFIG_IPROC_QSPI_DUAL_MODE */ ++static int io_mode = 2; ++#endif /* !CONFIG_IPROC_QSPI_DUAL_MODE */ ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(io_mode, int, 0444); ++ ++/* Multi I/O for address (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_MULTI_LANE_ADDR ++static int addr_multi = 1; ++#else /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ ++static int addr_multi = 0; ++#endif /* !CONFIG_IPROC_QSPI_MULTI_LANE_ADDR */ ++module_param(addr_multi, int, 0444); ++ ++/* Read opcode (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int read_opcode = OPCODE_FAST_READ; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++static int read_opcode = CONFIG_IPROC_QSPI_READ_CMD; ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(read_opcode, int, 0444); ++ ++/* Dummy cycles for read (only if not in single mode) */ ++#ifdef CONFIG_IPROC_QSPI_SINGLE_MODE ++static int dummy_cycles = 8; ++#else /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++static int dummy_cycles = CONFIG_IPROC_QSPI_READ_DUMMY_CYCLES; ++#endif /* !CONFIG_IPROC_QSPI_SINGLE_MODE */ ++module_param(dummy_cycles, int, 0444); ++ ++/* Max SPI clock HZ */ ++static int max_hz = 0; ++module_param(max_hz, int, 0444); ++ ++/* Spansion high performance mode */ ++static int bspi_hp; ++module_param(bspi_hp, int, 0444); ++ ++struct bcmspi_parms { ++ u32 speed_hz; ++ u8 chip_select; ++ u8 mode; ++ u8 bits_per_word; ++}; ++ ++struct position { ++ struct spi_message *msg; ++ struct spi_transfer *trans; ++ int byte; ++ int mspi_16bit; ++}; ++ ++#define NUM_TXRAM 32 ++#define NUM_RXRAM 32 ++#define NUM_CDRAM 16 ++ ++struct bcm_mspi_hw { ++ u32 spcr0_lsb; /* 0x000 */ ++ u32 spcr0_msb; /* 0x004 */ ++ u32 spcr1_lsb; /* 0x008 */ ++ u32 spcr1_msb; /* 0x00c */ ++ u32 newqp; /* 0x010 */ ++ u32 endqp; /* 0x014 */ ++ u32 spcr2; /* 0x018 */ ++ u32 reserved0; /* 0x01c */ ++ u32 mspi_status; /* 0x020 */ ++ u32 cptqp; /* 0x024 */ ++ u32 reserved1[6]; /* 0x028 */ ++ u32 txram[NUM_TXRAM]; /* 0x040 */ ++ u32 rxram[NUM_RXRAM]; /* 0x0c0 */ ++ u32 cdram[NUM_CDRAM]; /* 0x140 */ ++ u32 write_lock; /* 0x180 */ ++ u32 disable_flush_gen; /* 0x184 */ ++}; ++ ++struct bcm_bspi_hw { ++ u32 revision_id; /* 0x000 */ ++ u32 scratch; /* 0x004 */ ++ u32 mast_n_boot_ctrl; /* 0x008 */ ++ u32 busy_status; /* 0x00c */ ++ u32 intr_status; /* 0x010 */ ++ u32 b0_status; /* 0x014 */ ++ u32 b0_ctrl; /* 0x018 */ ++ u32 b1_status; /* 0x01c */ ++ u32 b1_ctrl; /* 0x020 */ ++ u32 strap_override_ctrl; /* 0x024 */ ++ u32 flex_mode_enable; /* 0x028 */ ++ u32 bits_per_cycle; /* 0x02C */ ++ u32 bits_per_phase; /* 0x030 */ ++ u32 cmd_and_mode_byte; /* 0x034 */ ++ u32 flash_upper_addr_byte; /* 0x038 */ ++ u32 xor_value; /* 0x03C */ ++ u32 xor_enable; /* 0x040 */ ++ u32 pio_mode_enable; /* 0x044 */ ++ u32 pio_iodir; /* 0x048 */ ++ u32 pio_data; /* 0x04C */ ++}; ++ ++struct bcm_bspi_raf { ++ u32 start_address; /* 0x00 */ ++ u32 num_words; /* 0x04 */ ++ u32 ctrl; /* 0x08 */ ++ u32 fullness; /* 0x0C */ ++ u32 watermark; /* 0x10 */ ++ u32 status; /* 0x14 */ ++ u32 read_data; /* 0x18 */ ++ u32 word_cnt; /* 0x1C */ ++ u32 curr_addr; /* 0x20 */ ++}; ++ ++struct bcm_idm_qspi_ctrl { ++ u32 io_ctrl_direct; ++}; ++ ++struct bcm_cru_control { ++ u32 cru_control; ++}; ++ ++struct bcm_flex_mode { ++ int width; ++ int addrlen; ++ int hp; ++}; ++ ++#define STATE_IDLE 0 ++#define STATE_RUNNING 1 ++#define STATE_SHUTDOWN 2 ++ ++struct bcmspi_priv { ++ struct platform_device *pdev; ++ struct spi_master *master; ++ spinlock_t lock; ++ struct bcmspi_parms last_parms; ++ struct position pos; ++ struct list_head msg_queue; ++ int state; ++ int outstanding_bytes; ++ int next_udelay; ++ int cs_change; ++ unsigned int mspi_refclk; ++ unsigned int max_speed_hz; ++ volatile struct bcm_mspi_hw *mspi_hw; ++ int irq; ++ struct tasklet_struct tasklet; ++ int curr_cs; ++ ++ /* BSPI */ ++ volatile struct bcm_bspi_hw *bspi_hw; ++ volatile struct bcm_cru_control *cru_hw; ++ int bspi_enabled; ++ /* all chip selects controlled by BSPI */ ++ int bspi_chip_select; ++ ++ /* LR */ ++ volatile struct bcm_bspi_raf *bspi_hw_raf; ++ struct spi_transfer *cur_xfer; ++ u32 cur_xfer_idx; ++ u32 cur_xfer_len; ++ u32 xfer_status; ++ struct spi_message *cur_msg; ++ u32 actual_length; ++ u32 raf_next_addr; ++ u32 raf_next_len; ++ ++ /* Interrupts */ ++ volatile u32 *qspi_intr; ++ volatile struct bcm_idm_qspi_ctrl *idm_qspi; ++ ++ /* current flex mode settings */ ++ struct bcm_flex_mode flex_mode; ++}; ++ ++static void bcmspi_enable_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ priv->idm_qspi->io_ctrl_direct |= cpu_to_le32(mask << 2); ++} ++ ++static void bcmspi_disable_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ priv->idm_qspi->io_ctrl_direct &= cpu_to_le32(~(mask << 2)); ++} ++ ++static void bcmspi_clear_interrupt(struct bcmspi_priv *priv, u32 mask) ++{ ++ int i; ++ ++ for(i=0; iqspi_intr[i] = cpu_to_le32(1); ++ } ++ } ++} ++ ++static u32 bcmspi_read_interrupt(struct bcmspi_priv *priv) ++{ ++ int i; ++ u32 status = 0; ++ ++ for(i=0; iqspi_intr[i] & cpu_to_le32(1)) { ++ status |= 1UL << i; ++ } ++ } ++ ++ return status; ++} ++ ++static void bcmspi_flush_prefetch_buffers(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw->b0_ctrl = 0; ++ priv->bspi_hw->b1_ctrl = 0; ++ priv->bspi_hw->b0_ctrl = cpu_to_le32(1); ++ priv->bspi_hw->b1_ctrl = cpu_to_le32(1); ++} ++ ++static int bcmspi_lr_is_fifo_empty(struct bcmspi_priv *priv) ++{ ++ return priv->bspi_hw_raf->status & cpu_to_le32(QSPI_BSPI_RAF_STATUS_FIFO_EMPTY_MASK); ++} ++ ++static inline u32 bcmspi_lr_read_fifo(struct bcmspi_priv *priv) ++{ ++ /* for performance reasons return the raw data, rather than ++ * byte-swapped data. This works because the caller writes ++ * values 32-bits at a time to the destination buffer, giving ++ * an automatic byte-swap on big-endian machines. */ ++ ++ return priv->bspi_hw_raf->read_data; ++} ++ ++static inline void bcmspi_lr_start(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_START_MASK); ++} ++ ++static inline void bcmspi_lr_clear(struct bcmspi_priv *priv) ++{ ++ priv->bspi_hw_raf->ctrl = cpu_to_le32(QSPI_BSPI_RAF_CONTROL_CLEAR_MASK); ++ bcmspi_flush_prefetch_buffers(priv); ++} ++ ++static inline int bcmspi_is_4_byte_mode(struct bcmspi_priv *priv) ++{ ++ return priv->flex_mode.addrlen == BSPI_ADDRLEN_4BYTES; ++} ++ ++static int bcmbspi_flash_type(struct bcmspi_priv *priv); ++ ++static int bcmspi_set_flex_mode(struct bcmspi_priv *priv, ++ int width, int addrlen, int hp) ++{ ++ int bpc = 0, bpp = dummy_cycles, command = read_opcode; ++ int flex_mode = 1, error = 0; ++ ++ switch (width) { ++ case BSPI_WIDTH_1BIT: ++ if (addrlen == BSPI_ADDRLEN_3BYTES) { ++ /* default mode, does not need flex_cmd */ ++ flex_mode = 0; ++ } else { ++ bpp = 8; /* dummy cycles */ ++ if (bcmbspi_flash_type(priv) == BSPI_FLASH_TYPE_SPANSION) ++ command = OPCODE_FAST_READ_4B; ++ else ++ command = OPCODE_FAST_READ; ++ } ++ break; ++ case BSPI_WIDTH_2BIT: ++ bpc = 0x00000001; /* only data is 2-bit */ ++ if (addr_multi) { ++ bpc |= 0x00010000; ++ } ++ if (hp) { ++ bpc |= 0x00010100; /* address and mode are 2-bit too */ ++ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; ++ } ++ break; ++ case BSPI_WIDTH_4BIT: ++ bpc = 0x00000002; /* only data is 4-bit */ ++ if (addr_multi) { ++ bpc |= 0x00020000; ++ } ++ if (hp) { ++ bpc |= 0x00020200; /* address and mode are 4-bit too */ ++ bpp |= QSPI_BSPI_BPP_MODE_BPP_MASK; ++ } ++ break; ++ default: ++ error = 1; ++ break; ++ } ++ ++ if (addrlen == BSPI_ADDRLEN_4BYTES) { ++ bpp |= QSPI_BSPI_BPP_ADDR_BPP_SELECT_MASK; ++ } ++ ++ if (!error) { ++ priv->bspi_hw->flex_mode_enable = 0; ++ priv->bspi_hw->bits_per_cycle = cpu_to_le32(bpc); ++ priv->bspi_hw->bits_per_phase = cpu_to_le32(bpp); ++ priv->bspi_hw->cmd_and_mode_byte = cpu_to_le32(command); ++ priv->bspi_hw->flex_mode_enable = flex_mode ? ++ cpu_to_le32(QSPI_BSPI_FLEX_MODE_ENABLE_MASK) ++ : 0; ++ DBG("%s: width=%d addrlen=%d hp=%d\n", ++ __func__, width, addrlen, hp); ++ DBG("%s: fme=%08x bpc=%08x bpp=%08x cmd=%08x\n", __func__, ++ le32_to_cpu(priv->bspi_hw->flex_mode_enable), ++ le32_to_cpu(priv->bspi_hw->bits_per_cycle), ++ le32_to_cpu(priv->bspi_hw->bits_per_phase), ++ le32_to_cpu(priv->bspi_hw->cmd_and_mode_byte)); ++ } ++ ++ return error; ++} ++ ++static void bcmspi_set_mode(struct bcmspi_priv *priv, ++ int width, int addrlen, int hp) ++{ ++ int error = 0; ++ int show_info = 0; ++ ++ if (width != -1 || hp != -1) { ++ /* Don't print things if only for address mode change because it ++ * could be very frequent. */ ++ show_info = 1; ++ } ++ if (width == -1) ++ width = priv->flex_mode.width; ++ if (addrlen == -1) ++ addrlen = priv->flex_mode.addrlen; ++ if (hp == -1) ++ hp = priv->flex_mode.hp; ++ ++ error = bcmspi_set_flex_mode(priv, width, addrlen, hp); ++ ++ if (!error) { ++ priv->flex_mode.width = width; ++ priv->flex_mode.addrlen = addrlen; ++ priv->flex_mode.hp = hp; ++ if (show_info) { ++ dev_info(&priv->pdev->dev, ++ "%d-lane output, %d-byte address%s\n", ++ priv->flex_mode.width, ++ priv->flex_mode.addrlen, ++ priv->flex_mode.hp ? ", high-performance mode" : ""); ++ } ++ } else ++ dev_warn(&priv->pdev->dev, ++ "INVALID COMBINATION: width=%d addrlen=%d hp=%d\n", ++ width, addrlen, hp); ++} ++ ++static void bcmspi_set_chip_select(struct bcmspi_priv *priv, int cs) ++{ ++ if (priv->curr_cs != cs) { ++ DBG("Switching CS%1d => CS%1d\n", ++ priv->curr_cs, cs); ++ ++ /* We don't have multiple chip selects for now */ ++ } ++ priv->curr_cs = cs; ++ ++} ++ ++static inline int is_bspi_chip_select(struct bcmspi_priv *priv, u8 cs) ++{ ++ return priv->bspi_chip_select & (1 << cs); ++} ++ ++static void bcmspi_disable_bspi(struct bcmspi_priv *priv) ++{ ++ int i; ++ ++ if (!priv->bspi_hw || !priv->bspi_enabled) ++ return; ++ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 1) { ++ priv->bspi_enabled = 0; ++ return; ++ } ++ ++ DBG("disabling bspi\n"); ++ for (i = 0; i < 1000; i++) { ++ if ((priv->bspi_hw->busy_status & cpu_to_le32(1)) == 0) { ++ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); ++ priv->bspi_enabled = 0; ++ udelay(1); ++ return; ++ } ++ udelay(1); ++ } ++ dev_warn(&priv->pdev->dev, "timeout setting MSPI mode\n"); ++} ++ ++static void bcmspi_enable_bspi(struct bcmspi_priv *priv) ++{ ++ if (!priv->bspi_hw || priv->bspi_enabled) ++ return; ++ if ((priv->bspi_hw->mast_n_boot_ctrl & cpu_to_le32(1)) == 0) { ++ priv->bspi_enabled = 1; ++ return; ++ } ++ ++ DBG("enabling bspi\n"); ++ priv->bspi_hw->mast_n_boot_ctrl = 0; ++ priv->bspi_enabled = 1; ++} ++ ++static void bcmspi_hw_set_parms(struct bcmspi_priv *priv, ++ const struct bcmspi_parms *xp) ++{ ++ if (xp->speed_hz) { ++ unsigned int spbr = priv->mspi_refclk / (2 * xp->speed_hz); ++ ++ priv->mspi_hw->spcr0_lsb = cpu_to_le32(max(min(spbr, SPBR_MAX), SPBR_MIN)); ++ } else { ++ priv->mspi_hw->spcr0_lsb = cpu_to_le32(SPBR_MIN); ++ } ++ ++ if (priv->pos.msg == NULL || xp->bits_per_word > 8) { ++ /* Global hw init or 16bit spi_transfer */ ++ int bits = xp->bits_per_word; ++ bits = bits? (bits == 16? 0 : bits) : 8; ++ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ ++ (bits << 2) | ++ (xp->mode & 3)); ++ } else { ++ /* Configure for a new 8-bit spi_transfer */ ++ if (priv->pos.byte == 0) { ++ /* Use 16-bit MSPI transfer for performance if applicable */ ++ if (priv->pos.mspi_16bit ^ (!(priv->pos.trans->len & 1))) { ++ /* Update it only if needed */ ++ priv->pos.mspi_16bit = !priv->pos.mspi_16bit; ++ priv->mspi_hw->spcr0_msb = cpu_to_le32(0x80 | /* Master */ ++ ((priv->pos.mspi_16bit? 0 : 8) << 2) | ++ (xp->mode & 3)); ++ } ++ } ++ } ++ priv->last_parms = *xp; ++} ++ ++#define PARMS_NO_OVERRIDE 0 ++#define PARMS_OVERRIDE 1 ++ ++static int bcmspi_update_parms(struct bcmspi_priv *priv, ++ struct spi_device *spidev, struct spi_transfer *trans, int override) ++{ ++ struct bcmspi_parms xp; ++ ++ xp.speed_hz = min(trans->speed_hz ? trans->speed_hz : ++ (spidev->max_speed_hz ? spidev->max_speed_hz : DEFAULT_SPEED_HZ), ++ DEFAULT_SPEED_HZ); ++ xp.chip_select = spidev->chip_select; ++ xp.mode = spidev->mode; ++ xp.bits_per_word = trans->bits_per_word ? trans->bits_per_word : ++ (spidev->bits_per_word ? spidev->bits_per_word : 8); ++ ++ if ((override == PARMS_OVERRIDE) || ++ ((xp.speed_hz == priv->last_parms.speed_hz) && ++ (xp.chip_select == priv->last_parms.chip_select) && ++ (xp.mode == priv->last_parms.mode) && ++ (xp.bits_per_word == priv->last_parms.bits_per_word))) { ++ bcmspi_hw_set_parms(priv, &xp); ++ return 0; ++ } ++ /* no override, and parms do not match */ ++ return 1; ++} ++ ++ ++static int bcmspi_setup(struct spi_device *spi) ++{ ++ struct bcmspi_parms *xp; ++ struct bcmspi_priv *priv = spi_master_get_devdata(spi->master); ++ unsigned int speed_hz; ++ ++ DBG("%s\n", __func__); ++ ++ if (spi->bits_per_word > 16) ++ return -EINVAL; ++ ++ /* Module parameter override */ ++ if (max_hz != 0) { ++ speed_hz = max_hz; ++ } else { ++ speed_hz = spi->max_speed_hz; ++ } ++ ++ xp = spi_get_ctldata(spi); ++ if (!xp) { ++ xp = kzalloc(sizeof(struct bcmspi_parms), GFP_KERNEL); ++ if (!xp) ++ return -ENOMEM; ++ spi_set_ctldata(spi, xp); ++ } ++ if (speed_hz < priv->max_speed_hz) ++ xp->speed_hz = speed_hz; ++ else ++ xp->speed_hz = 0; ++ ++ priv->cru_hw->cru_control &= cpu_to_le32(~0x00000006); ++ (void)priv->cru_hw->cru_control; /* Need to read back */ ++ if (speed_hz >= 62500000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000006); ++ } else if (speed_hz >= 50000000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000002); ++ } else if (speed_hz >= 31250000) { ++ priv->cru_hw->cru_control |= cpu_to_le32(0x00000004); ++ } ++ (void)priv->cru_hw->cru_control; /* Need to read back */ ++ ++ xp->chip_select = spi->chip_select; ++ xp->mode = spi->mode; ++ xp->bits_per_word = spi->bits_per_word ? spi->bits_per_word : 8; ++ ++ return 0; ++} ++ ++/* stop at end of transfer, no other reason */ ++#define FNB_BREAK_NONE 0 ++/* stop at end of spi_message */ ++#define FNB_BREAK_EOM 1 ++/* stop at end of spi_transfer if delay */ ++#define FNB_BREAK_DELAY 2 ++/* stop at end of spi_transfer if cs_change */ ++#define FNB_BREAK_CS_CHANGE 4 ++/* stop if we run out of bytes */ ++#define FNB_BREAK_NO_BYTES 8 ++/* stop at end of spi_transfer */ ++#define FNB_BREAK_EOT 16 ++ ++/* events that make us stop filling TX slots */ ++#define FNB_BREAK_TX (FNB_BREAK_EOM | FNB_BREAK_DELAY | \ ++ FNB_BREAK_CS_CHANGE) ++ ++/* events that make us deassert CS */ ++#define FNB_BREAK_DESELECT (FNB_BREAK_EOM | FNB_BREAK_CS_CHANGE) ++ ++ ++static int find_next_byte(struct bcmspi_priv *priv, struct position *p, ++ struct list_head *completed, int flags) ++{ ++ int ret = FNB_BREAK_NONE; ++ ++ p->byte++; ++ ++ while (p->byte >= p->trans->len) { ++ /* we're at the end of the spi_transfer */ ++ ++ /* in TX mode, need to pause for a delay or CS change */ ++ if (p->trans->delay_usecs && (flags & FNB_BREAK_DELAY)) ++ ret |= FNB_BREAK_DELAY; ++ if (p->trans->cs_change && (flags & FNB_BREAK_CS_CHANGE)) ++ ret |= FNB_BREAK_CS_CHANGE; ++ if (ret) ++ return ret; ++ ++ /* advance to next spi_message? */ ++ if (list_is_last(&p->trans->transfer_list, ++ &p->msg->transfers)) { ++ struct spi_message *next_msg = NULL; ++ ++ /* TX breaks at the end of each message as well */ ++ if (!completed || (flags & FNB_BREAK_EOM)) { ++ DBG("find_next_byte: advance msg exit\n"); ++ return FNB_BREAK_EOM; ++ } ++ if (!list_is_last(&p->msg->queue, &priv->msg_queue)) { ++ next_msg = list_entry(p->msg->queue.next, ++ struct spi_message, queue); ++ } ++ /* delete from run queue, add to completion queue */ ++ list_del(&p->msg->queue); ++ list_add_tail(&p->msg->queue, completed); ++ ++ p->msg = next_msg; ++ p->byte = 0; ++ if (p->msg == NULL) { ++ p->trans = NULL; ++ ret = FNB_BREAK_NO_BYTES; ++ break; ++ } ++ ++ /* ++ * move on to the first spi_transfer of the new ++ * spi_message ++ */ ++ p->trans = list_entry(p->msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ } else { ++ /* or just advance to the next spi_transfer */ ++ p->trans = list_entry(p->trans->transfer_list.next, ++ struct spi_transfer, transfer_list); ++ p->byte = 0; ++ ++ /* Separate spi_transfers into MSPI transfers */ ++ ret = FNB_BREAK_EOT; ++ } ++ } ++ DBG("find_next_byte: msg %p trans %p len %d byte %d ret %x\n", ++ p->msg, p->trans, p->trans ? p->trans->len : 0, p->byte, ret); ++ return ret; ++} ++ ++static void read_from_hw(struct bcmspi_priv *priv, struct list_head *completed) ++{ ++ struct position p; ++ int slot = 0, n = priv->outstanding_bytes; ++ ++ DBG("%s\n", __func__); ++ ++ p = priv->pos; ++ ++ while (n > 0) { ++ BUG_ON(p.msg == NULL); ++ ++ if (p.trans->bits_per_word <= 8) { ++ u8 *buf = p.trans->rx_buf; ++ ++ if (buf) { ++ ++ if (p.mspi_16bit) { ++ /* Using 16-bit SPI transfers for performance */ ++ buf[p.byte] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); ++ buf[p.byte + 1] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte + 1] : 0xff); ++ } else { ++ buf[p.byte] = ++ le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff; ++ DBG("RD %02x\n", buf ? buf[p.byte] : 0xff); ++ } ++ } ++ } else { ++ u16 *buf = p.trans->rx_buf; ++ ++ if (buf) { ++ buf[p.byte] = ++ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 1]) & 0xff) << 0) | ++ ((le32_to_cpu(priv->mspi_hw->rxram[(slot << 1) + 0] & 0xff)) << 8); ++ DBG("RD %04x\n", buf ? buf[p.byte] : 0xffff); ++ } ++ } ++ slot++; ++ n--; ++ p.msg->actual_length++; ++ if (p.mspi_16bit) { ++ p.byte++; ++ p.msg->actual_length++; ++ } ++ ++ find_next_byte(priv, &p, completed, FNB_BREAK_NONE); ++ } ++ ++ priv->pos = p; ++ priv->outstanding_bytes = 0; ++} ++ ++static void write_to_hw(struct bcmspi_priv *priv) ++{ ++ struct position p; ++ int slot = 0, fnb = 0; ++ struct spi_message *msg = NULL; ++ ++ DBG("%s\n", __func__); ++ ++ bcmspi_disable_bspi(priv); ++ ++ p = priv->pos; ++ ++ while (1) { ++ if (p.msg == NULL) ++ break; ++ if (!msg) { ++ msg = p.msg; ++ bcmspi_update_parms(priv, msg->spi, p.trans, ++ PARMS_OVERRIDE); ++ } else { ++ /* break if the speed, bits, etc. changed */ ++ if (bcmspi_update_parms(priv, msg->spi, p.trans, ++ PARMS_NO_OVERRIDE)) { ++ DBG("parms don't match, breaking\n"); ++ break; ++ } ++ } ++ if (p.trans->bits_per_word <= 8) { ++ const u8 *buf = p.trans->tx_buf; ++ ++ priv->mspi_hw->txram[slot << 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); ++ ++ if (priv->pos.mspi_16bit) { ++ /* Using 16-bit SPI transfers for performance */ ++ p.byte++; ++ priv->mspi_hw->txram[(slot << 1) + 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %02x\n", buf ? buf[p.byte] : 0xff); ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); ++ } else { ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0x8e); ++ } ++ ++ } else { ++ const u16 *buf = p.trans->tx_buf; ++ ++ priv->mspi_hw->txram[(slot << 1) + 0] = cpu_to_le32(buf ? ++ (buf[p.byte] >> 8) : 0xff); ++ priv->mspi_hw->txram[(slot << 1) + 1] = cpu_to_le32(buf ? ++ (buf[p.byte] & 0xff) : 0xff); ++ DBG("WR %04x\n", buf ? buf[p.byte] : 0xffff); ++ priv->mspi_hw->cdram[slot] = cpu_to_le32(0xce); ++ } ++ slot++; ++ ++ fnb = find_next_byte(priv, &p, NULL, FNB_BREAK_TX); ++ ++ if (fnb & FNB_BREAK_CS_CHANGE) ++ priv->cs_change = 1; ++ if (fnb & FNB_BREAK_DELAY) ++ priv->next_udelay = p.trans->delay_usecs; ++ if (fnb || (slot == NUM_CDRAM)) ++ break; ++ } ++ ++ if (slot) { ++ DBG("submitting %d slots\n", slot); ++ priv->mspi_hw->newqp = 0; ++ priv->mspi_hw->endqp = cpu_to_le32(slot - 1); ++ ++ /* deassert CS on the final byte */ ++ if (fnb & FNB_BREAK_DESELECT) ++ priv->mspi_hw->cdram[slot - 1] &= cpu_to_le32(~0x80); ++ ++ /* tell HIF_MSPI which CS to use */ ++ bcmspi_set_chip_select(priv, msg->spi->chip_select); ++ ++ priv->mspi_hw->write_lock = cpu_to_le32(1); ++ priv->mspi_hw->spcr2 = cpu_to_le32(0xe0); /* cont | spe | spifie */ ++ ++ priv->state = STATE_RUNNING; ++ priv->outstanding_bytes = slot; ++ } else { ++ priv->mspi_hw->write_lock = 0; ++ priv->state = STATE_IDLE; ++ } ++} ++ ++#define DWORD_ALIGNED(a) (!(((unsigned long)(a)) & 3)) ++#define ACROSS_16MB(a, l) (((a) ^ ((a) + (l) - 1)) & 0xFF000000) ++ ++static int bcmspi_emulate_flash_read(struct bcmspi_priv *priv, ++ struct spi_message *msg) ++{ ++ u32 addr, len; ++ int idx = 0; /* Also used for checking continuation */ ++ unsigned long flags = 0; ++ ++ /* Check if it's a continuation */ ++ if (priv->raf_next_len != 0) { ++ ++ /* Continuation (read across 16MB boundary) */ ++ addr = priv->raf_next_addr; ++ len = priv->raf_next_len; ++ ++ /* Update upper address byte */ ++ if (bcmspi_is_4_byte_mode(priv)) { ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); ++ /* Flush prefecth buffers since upper byte changed */ ++ bcmspi_flush_prefetch_buffers(priv); ++ } ++ ++ } else { ++ ++ /* It's the first session of this transfer */ ++ struct spi_transfer *trans; ++ u8 *buf; ++ ++ /* acquire lock when the MSPI is idle */ ++ while (1) { ++ spin_lock_irqsave(&priv->lock, flags); ++ if (priv->state == STATE_IDLE) ++ break; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ if (priv->state == STATE_SHUTDOWN) ++ return -EIO; ++ udelay(1); ++ } ++ bcmspi_set_chip_select(priv, msg->spi->chip_select); ++ ++ /* first transfer - OPCODE_READ + 3-byte address */ ++ trans = list_entry(msg->transfers.next, struct spi_transfer, ++ transfer_list); ++ buf = (void *)trans->tx_buf; ++ ++ idx = 1; ++ ++ /* Check upper address byte for 4-byte mode */ ++ if (bcmspi_is_4_byte_mode(priv)) { ++ addr = buf[idx++] << 24; ++ } else { ++ addr = 0; ++ } ++ ++ /* ++ * addr coming into this function is a raw flash offset ++ * we need to convert it to the BSPI address ++ */ ++ addr |= (buf[idx] << 16) | (buf[idx+1] << 8) | buf[idx+2]; ++ ++ /* second transfer - read result into buffer */ ++ trans = list_entry(msg->transfers.next->next, struct spi_transfer, ++ transfer_list); ++ ++ buf = (void *)trans->rx_buf; ++ ++ len = trans->len; ++ ++ /* non-aligned and very short transfers are handled by MSPI */ ++ if (unlikely(!DWORD_ALIGNED(addr) || ++ !DWORD_ALIGNED(buf) || ++ len < sizeof(u32) || ++ !priv->bspi_hw_raf)) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return -1; ++ } ++ ++ /* Flush prefetch buffers only if upper address byte changed */ ++ if ((addr & 0xFF000000) != le32_to_cpu(priv->bspi_hw->flash_upper_addr_byte)) { ++ bcmspi_flush_prefetch_buffers(priv); ++ /* Update upper address byte */ ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(addr & 0xFF000000); ++ } ++ ++ /* Switching to BSPI */ ++ bcmspi_enable_bspi(priv); ++ ++ DBG("%s: dst %p src %p len %x addr BSPI %06x\n", ++ __func__, buf, addr, len, addr); ++ ++ /* initialize software parameters */ ++ priv->xfer_status = 0; ++ priv->cur_xfer = trans; ++ priv->cur_xfer_idx = 0; ++ priv->cur_msg = msg; ++ priv->actual_length = idx + 4 + trans->len; ++ } ++ ++ if (bcmspi_is_4_byte_mode(priv) && ACROSS_16MB(addr, len)) { ++ ++ /* Size for the first session */ ++ u32 bytes = 0x1000000 - (addr & 0x00FFFFFF); ++ ++ /* Address and size for remaining sessions */ ++ priv->raf_next_addr = addr + bytes; ++ priv->raf_next_len = len - bytes; ++ ++ len = bytes; ++ ++ } else { ++ priv->raf_next_len = 0; ++ } ++ ++ /* Length for this session */ ++ priv->cur_xfer_len = len; ++ ++ /* setup hardware */ ++ /* address must be 4-byte aligned */ ++ priv->bspi_hw_raf->start_address = cpu_to_le32(addr & 0x00FFFFFF); ++ priv->bspi_hw_raf->num_words = cpu_to_le32((len + 3) >> 2); ++ priv->bspi_hw_raf->watermark = 0; ++ ++ DBG("READ: %08x %08x (%08x)\n", addr, ((len + 3) >> 2), len); ++ ++ bcmspi_clear_interrupt(priv, 0xffffffff); ++ bcmspi_enable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ bcmspi_lr_start(priv); ++ ++ if (idx) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ } ++ ++ return 0; ++} ++ ++/* ++ * m25p80_read() calls wait_till_ready() before each read to check ++ * the flash status register for pending writes. ++ * ++ * This can be safely skipped if our last transaction was just an ++ * emulated BSPI read. ++ */ ++static int bcmspi_emulate_flash_rdsr(struct bcmspi_priv *priv, ++ struct spi_message *msg) ++{ ++ u8 *buf; ++ struct spi_transfer *trans; ++ ++ if (priv->bspi_enabled == 0) ++ return 1; ++ ++ trans = list_entry(msg->transfers.next->next, struct spi_transfer, ++ transfer_list); ++ ++ buf = (void *)trans->rx_buf; ++ *buf = 0x00; ++ ++ msg->actual_length = 2; ++ msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ spi_finalize_current_message(priv->master); ++#else ++ msg->complete(msg->context); ++#endif ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++static int bcmspi_prepare_transfer(struct spi_master *master) ++{ ++ return 0; ++} ++ ++static int bcmspi_unprepare_transfer(struct spi_master *master) ++{ ++ return 0; ++} ++#endif ++ ++static int bcmspi_transfer_one(struct spi_master *master, struct spi_message *msg) ++{ ++ struct bcmspi_priv *priv = spi_master_get_devdata(master); ++ unsigned long flags; ++ ++ if (is_bspi_chip_select(priv, msg->spi->chip_select)) { ++ struct spi_transfer *trans; ++ ++ trans = list_entry(msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ if (trans && trans->len && trans->tx_buf) { ++ u8 command = ((u8 *)trans->tx_buf)[0]; ++ switch (command) { ++ case OPCODE_FAST_READ: ++ if (bcmspi_emulate_flash_read(priv, msg) == 0) ++ return 0; ++ break; ++ case OPCODE_RDSR: ++ if (bcmspi_emulate_flash_rdsr(priv, msg) == 0) ++ return 0; ++ break; ++ case OPCODE_EN4B: ++ DBG("ENABLE 4-BYTE MODE\n"); ++ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_4BYTES, -1); ++ break; ++ case OPCODE_EX4B: ++ DBG("DISABLE 4-BYTE MODE\n"); ++ bcmspi_set_mode(priv, -1, BSPI_ADDRLEN_3BYTES, -1); ++ break; ++ case OPCODE_BRWR: ++ { ++ u8 enable = ((u8 *)trans->tx_buf)[1]; ++ DBG("%s 4-BYTE MODE\n", enable ? "ENABLE" : "DISABLE"); ++ bcmspi_set_mode(priv, -1, ++ enable ? BSPI_ADDRLEN_4BYTES : ++ BSPI_ADDRLEN_3BYTES, -1); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ /* Mark prefetch buffers dirty (by using upper byte) if needed */ ++ switch(command) { ++ case OPCODE_RDID: ++ case OPCODE_WREN: ++ case OPCODE_WRDI: ++ case OPCODE_RCR: ++ case OPCODE_READ: ++ case OPCODE_RDSR: ++ case OPCODE_WRSR: ++ case OPCODE_RDFSR: ++ case OPCODE_FAST_READ: ++ case OPCODE_FAST_READ_4B: ++ case OPCODE_EN4B: ++ case OPCODE_EX4B: ++ case OPCODE_BRWR: ++ /* These are known opcodes that are not writing/erasing */ ++ break; ++ default: ++ /* Could be writing/erasing; mark buffers dirty */ ++ priv->bspi_hw->flash_upper_addr_byte = cpu_to_le32(0x80); ++ break; ++ } ++ } ++ } ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->state == STATE_SHUTDOWN) { ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return -EIO; ++ } ++ ++ msg->actual_length = 0; ++ ++ list_add_tail(&msg->queue, &priv->msg_queue); ++ ++ if (priv->state == STATE_IDLE) { ++ BUG_ON(priv->pos.msg != NULL); ++ priv->pos.msg = msg; ++ priv->pos.trans = list_entry(msg->transfers.next, ++ struct spi_transfer, transfer_list); ++ priv->pos.byte = 0; ++ ++ write_to_hw(priv); ++ } ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) ++static int bcmspi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ return bcmspi_transfer_one(spi->master, msg); ++} ++#endif ++ ++static void bcmspi_cleanup(struct spi_device *spi) ++{ ++ struct bcmspi_parms *xp = spi_get_ctldata(spi); ++ ++ DBG("%s\n", __func__); ++ ++ kfree(xp); ++} ++ ++static irqreturn_t bcmspi_interrupt(int irq, void *dev_id) ++{ ++ struct bcmspi_priv *priv = dev_id; ++ ++ if (priv->bspi_enabled && priv->cur_xfer) { ++ int done = 0; ++ u32 status = bcmspi_read_interrupt(priv); ++ u32 *buf = (u32 *)priv->cur_xfer->rx_buf; ++ if (status & BSPI_LR_INTERRUPTS_DATA) { ++ while (!bcmspi_lr_is_fifo_empty(priv)) { ++ u32 data = bcmspi_lr_read_fifo(priv); ++ if (likely(priv->cur_xfer_len >= 4)) { ++ buf[priv->cur_xfer_idx++] = data; ++ priv->cur_xfer_len -= 4; ++ } else { ++ /* ++ * Read out remaining bytes, make sure ++ * we do not cross the buffer boundary ++ */ ++ u8 *cbuf = ++ (u8 *)&buf[priv->cur_xfer_idx]; ++ data = cpu_to_le32(data); ++ while (priv->cur_xfer_len) { ++ *cbuf++ = (u8)data; ++ data >>= 8; ++ priv->cur_xfer_len--; ++ } ++ } ++ } ++ } ++ if (status & BSPI_LR_INTERRUPTS_ERROR) { ++ dev_err(&priv->pdev->dev, "ERROR %02x\n", status); ++ priv->xfer_status = -EIO; ++ } else if ((status & QSPI_INTR_BSPI_LR_SESSION_DONE_MASK) && ++ priv->cur_xfer_len == 0) { ++ ++ if (priv->raf_next_len) { ++ ++ /* Continuation for reading across 16MB boundary */ ++ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ bcmspi_emulate_flash_read(priv, NULL); ++ return IRQ_HANDLED; ++ ++ } else { ++ done = 1; ++ } ++ } ++ ++ if (done) { ++ priv->cur_xfer = NULL; ++ bcmspi_disable_interrupt(priv, BSPI_LR_INTERRUPTS_ALL); ++ ++ if (priv->xfer_status) { ++ bcmspi_lr_clear(priv); ++ } else { ++ if (priv->cur_msg) { ++ priv->cur_msg->actual_length = priv->actual_length; ++ priv->cur_msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ spi_finalize_current_message(priv->master); ++#else ++ priv->cur_msg->complete(priv->cur_msg->context); ++#endif ++ } ++ } ++ priv->cur_msg = NULL; ++ } ++ bcmspi_clear_interrupt(priv, status); ++ return IRQ_HANDLED; ++ } ++ ++ if (priv->mspi_hw->mspi_status & cpu_to_le32(1)) { ++ /* clear interrupt */ ++ priv->mspi_hw->mspi_status &= cpu_to_le32(~1); ++ bcmspi_clear_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); ++ ++ tasklet_schedule(&priv->tasklet); ++ return IRQ_HANDLED; ++ } else ++ return IRQ_NONE; ++} ++ ++static void bcmspi_complete(void *arg) ++{ ++ complete(arg); ++} ++ ++static void bcmspi_tasklet(unsigned long param) ++{ ++ struct bcmspi_priv *priv = (void *)param; ++ struct list_head completed; ++ struct spi_message *msg; ++ unsigned long flags; ++ ++ INIT_LIST_HEAD(&completed); ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (priv->next_udelay) { ++ udelay(priv->next_udelay); ++ priv->next_udelay = 0; ++ } ++ ++ msg = priv->pos.msg; ++ ++ read_from_hw(priv, &completed); ++ if (priv->cs_change) { ++ udelay(10); ++ priv->cs_change = 0; ++ } ++ ++ write_to_hw(priv); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ while (!list_empty(&completed)) { ++ msg = list_first_entry(&completed, struct spi_message, queue); ++ list_del(&msg->queue); ++ msg->status = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ if (msg->complete == bcmspi_complete) ++ msg->complete(msg->context); ++ else ++ spi_finalize_current_message(priv->master); ++#else ++ if (msg->complete) ++ msg->complete(msg->context); ++#endif ++ ++ } ++} ++ ++static struct spi_master *default_master; ++ ++static int bcmspi_simple_transaction(struct bcmspi_parms *xp, ++ const void *tx_buf, int tx_len, void *rx_buf, int rx_len) ++{ ++ DECLARE_COMPLETION_ONSTACK(fini); ++ struct spi_message m; ++ struct spi_transfer t_tx, t_rx; ++ struct spi_device spi; ++ int ret; ++ ++ memset(&spi, 0, sizeof(spi)); ++ spi.max_speed_hz = xp->speed_hz; ++ spi.chip_select = xp->chip_select; ++ spi.mode = xp->mode; ++ spi.bits_per_word = xp->bits_per_word; ++ spi.master = default_master; ++ ++ spi_message_init(&m); ++ m.complete = bcmspi_complete; ++ m.context = &fini; ++ m.spi = &spi; ++ ++ memset(&t_tx, 0, sizeof(t_tx)); ++ memset(&t_rx, 0, sizeof(t_rx)); ++ t_tx.tx_buf = tx_buf; ++ t_tx.len = tx_len; ++ t_rx.rx_buf = rx_buf; ++ t_rx.len = rx_len; ++ ++ if (tx_len) ++ spi_message_add_tail(&t_tx, &m); ++ if (rx_len) ++ spi_message_add_tail(&t_rx, &m); ++ ++ ret = bcmspi_transfer_one(default_master, &m); ++ if (!ret) ++ wait_for_completion(&fini); ++ return ret; ++} ++ ++static void bcmspi_hw_init(struct bcmspi_priv *priv) ++{ ++ const struct bcmspi_parms bcmspi_default_parms_cs0 = { ++ .speed_hz = DEFAULT_SPEED_HZ, ++ .chip_select = 0, ++ .mode = SPI_MODE_3, ++ .bits_per_word = 8, ++ }; ++ ++ priv->mspi_hw->spcr1_lsb = 0; ++ priv->mspi_hw->spcr1_msb = 0; ++ priv->mspi_hw->newqp = 0; ++ priv->mspi_hw->endqp = 0; ++ priv->mspi_hw->spcr2 = cpu_to_le32(0x20); /* spifie */ ++ ++ bcmspi_hw_set_parms(priv, &bcmspi_default_parms_cs0); ++ ++ priv->bspi_enabled = 1; ++ bcmspi_disable_bspi(priv); ++} ++ ++static void bcmspi_hw_uninit(struct bcmspi_priv *priv) ++{ ++ priv->mspi_hw->spcr2 = 0x0; /* disable irq and enable bits */ ++ bcmspi_enable_bspi(priv); ++} ++ ++static int bcmbspi_flash_type(struct bcmspi_priv *priv) ++{ ++ char tx_buf[4]; ++ unsigned char jedec_id[5] = {0}; ++ int bspi_flash; ++ ++ /* Read ID */ ++ tx_buf[0] = OPCODE_RDID; ++ bcmspi_simple_transaction(&priv->last_parms, tx_buf, 1, &jedec_id, 5); ++ ++ switch (jedec_id[0]) { ++ case 0x01: /* Spansion */ ++ case 0xef: ++ bspi_flash = BSPI_FLASH_TYPE_SPANSION; ++ break; ++ case 0xc2: /* Macronix */ ++ bspi_flash = BSPI_FLASH_TYPE_MACRONIX; ++ break; ++ case 0xbf: /* SST */ ++ bspi_flash = BSPI_FLASH_TYPE_SST; ++ break; ++ case 0x89: /* Numonyx */ ++ bspi_flash = BSPI_FLASH_TYPE_NUMONYX; ++ break; ++ default: ++ bspi_flash = BSPI_FLASH_TYPE_UNKNOWN; ++ break; ++ } ++ return bspi_flash; ++} ++ ++static int bcmspi_set_quad_mode(struct bcmspi_priv *priv, int _enable) ++{ ++ char tx_buf[4]; ++ unsigned char cfg_reg, sts_reg; ++ ++ switch (bcmbspi_flash_type(priv)) { ++ case BSPI_FLASH_TYPE_SPANSION: ++ /* RCR */ ++ tx_buf[0] = OPCODE_RCR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ if (_enable) ++ cfg_reg |= 0x2; ++ else ++ cfg_reg &= ~0x2; ++ /* WREN */ ++ tx_buf[0] = OPCODE_WREN; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, NULL, 0); ++ /* WRR */ ++ tx_buf[0] = OPCODE_WRR; ++ tx_buf[1] = 0; /* status register */ ++ tx_buf[2] = cfg_reg; /* configuration register */ ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 3, NULL, 0); ++ /* wait till ready */ ++ do { ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &sts_reg, 1); ++ udelay(1); ++ } while (sts_reg & 1); ++ break; ++ case BSPI_FLASH_TYPE_MACRONIX: ++ /* RDSR */ ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ if (_enable) ++ cfg_reg |= 0x40; ++ else ++ cfg_reg &= ~0x40; ++ /* WREN */ ++ tx_buf[0] = OPCODE_WREN; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, NULL, 0); ++ /* WRSR */ ++ tx_buf[0] = OPCODE_WRSR; ++ tx_buf[1] = cfg_reg; /* status register */ ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 2, NULL, 0); ++ /* wait till ready */ ++ do { ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &sts_reg, 1); ++ udelay(1); ++ } while (sts_reg & 1); ++ /* RDSR */ ++ tx_buf[0] = OPCODE_RDSR; ++ bcmspi_simple_transaction(&priv->last_parms, ++ tx_buf, 1, &cfg_reg, 1); ++ break; ++ case BSPI_FLASH_TYPE_SST: ++ case BSPI_FLASH_TYPE_NUMONYX: ++ /* TODO - send Quad mode control command */ ++ break; ++ default: ++ return _enable ? -1 : 0; ++ } ++ ++ return 0; ++} ++ ++static int bcmspi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct brcmspi_platform_data *pdata; ++ struct bcmspi_priv *priv; ++ struct spi_master *master; ++ struct resource *res; ++ struct clk *clk; ++ int ret; ++ u32 irq; ++ ++ DBG("bcmspi_probe\n"); ++ ++ pdata = (struct brcmspi_platform_data *)pdev->dev.platform_data; ++ ++ master = spi_alloc_master(dev, sizeof(struct bcmspi_priv)); ++ if (!master) { ++ dev_err(&pdev->dev, "error allocating spi_master\n"); ++ return -ENOMEM; ++ } ++ ++ priv = spi_master_get_devdata(master); ++ ++ priv->pdev = pdev; ++ priv->state = STATE_IDLE; ++ priv->pos.msg = NULL; ++ priv->pos.mspi_16bit = 0; ++ priv->master = master; ++ priv->raf_next_len = 0; ++ ++ master->bus_num = pdev->id; ++ master->num_chipselect = 1; ++ master->mode_bits = SPI_MODE_3; ++ ++ master->setup = bcmspi_setup; ++ master->cleanup = bcmspi_cleanup; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ master->prepare_transfer_hardware = bcmspi_prepare_transfer; ++ master->unprepare_transfer_hardware = bcmspi_unprepare_transfer; ++ master->transfer_one_message = bcmspi_transfer_one; ++ master->transfer = NULL; ++#else ++ master->transfer = bcmspi_transfer; ++#endif ++ ++ priv->mspi_hw = NULL; ++ priv->bspi_hw = NULL; ++ priv->bspi_hw_raf = NULL; ++ priv->qspi_intr = NULL; ++ priv->idm_qspi = NULL; ++ priv->irq = -1; ++ ++#ifdef CONFIG_MACH_CYGNUS ++ /* Get MSPI reference clock and max speed hz */ ++ clk = clk_get_sys(NULL, MSPI_REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ MSPI_REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ ++ if(clk < 0xc0008000) ++ { ++ printk(KERN_INFO "ERROR-Cygnus: QSPI clk=0x%x \n"); ++ } ++ ++ priv->mspi_refclk = 310000 * 2 ;//(unsigned int)25000000 * 2; ++ ++#else ++ /* Get MSPI reference clock and max speed hz */ ++ clk = clk_get_sys(MSPI_REFCLK_SOURCE_DEVID, MSPI_REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ MSPI_REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ priv->mspi_refclk = (unsigned int)clk_get_rate(clk) * 2; ++#endif /* CONFIG_MACH_CYGNUS */ ++ ++ priv->max_speed_hz = priv->mspi_refclk / (2 * SPBR_MIN); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't get resource 0\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ /* MSPI register range */ ++ priv->mspi_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->mspi_hw) { ++ dev_err(&pdev->dev, "can't ioremap\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->mspi_hw=%p\n", priv->mspi_hw); ++ ++ /* BSPI register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (res) { ++ priv->bspi_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->bspi_hw) { ++ dev_err(&pdev->dev, "can't ioremap BSPI range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else ++ priv->bspi_hw = NULL; ++ DBG("priv->bspi_hw=%p\n", priv->bspi_hw); ++ ++ /* BSPI_RAF register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (res) { ++ priv->bspi_hw_raf = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->bspi_hw_raf) { ++ dev_err(&pdev->dev, "can't ioremap BSPI_RAF range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else ++ priv->bspi_hw_raf = NULL; ++ DBG("priv->bspi_hw_raf=%p\n", priv->bspi_hw_raf); ++ ++ /* QSPI interrupt register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 3); ++ if (res) { ++ priv->qspi_intr = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->qspi_intr) { ++ dev_err(&pdev->dev, "can't ioremap QSPI interrupt range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 3\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->qspi_intr=%p\n", priv->qspi_intr); ++ ++ /* IDM QSPI io ctrl register range */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 4); ++ if (res) { ++ priv->idm_qspi = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->idm_qspi) { ++ dev_err(&pdev->dev, "can't ioremap IDM QSPI range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 4\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->idm_qspi=%p\n", priv->idm_qspi); ++ ++ /* CRU control register */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 5); ++ if (res) { ++ priv->cru_hw = (volatile void *)ioremap(res->start, ++ res->end - res->start); ++ if (!priv->cru_hw) { ++ dev_err(&pdev->dev, "can't ioremap CRU range\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ } else { ++ dev_err(&pdev->dev, "can't get resource 4\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ DBG("priv->cru_hw=%p\n", priv->cru_hw); ++ ++ /* IRQ */ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no IRQ defined\n"); ++ ret = -ENODEV; ++ goto err2; ++ } ++ ++ /* Basic initialization (before enabling interrupts) */ ++ priv->bspi_hw->mast_n_boot_ctrl = cpu_to_le32(1); ++ bcmspi_disable_interrupt(priv, 0xffffffff); ++ bcmspi_clear_interrupt(priv, 0xffffffff); ++ bcmspi_enable_interrupt(priv, QSPI_INTR_MSPI_DONE_MASK); ++ ++ /* Request all IRQs */ ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ ret = request_irq(irq, bcmspi_interrupt, 0, "qspi_iproc", priv); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "unable to allocate IRQ\n"); ++ goto err1; ++ } ++ } ++ ++ bcmspi_hw_init(priv); ++ priv->curr_cs = -1; ++ ++ priv->bspi_chip_select = (priv->bspi_hw && pdata) ? (1 << pdata->flash_cs) : 0; ++ ++ INIT_LIST_HEAD(&priv->msg_queue); ++ spin_lock_init(&priv->lock); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ tasklet_init(&priv->tasklet, bcmspi_tasklet, (unsigned long)priv); ++ ++ ret = spi_register_master(master); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "can't register master\n"); ++ goto err0; ++ } ++ if (!default_master) ++ default_master = master; ++ ++ /* default values - undefined */ ++ priv->flex_mode.width = ++ priv->flex_mode.addrlen = ++ priv->flex_mode.hp = -1; ++ ++ if (priv->bspi_chip_select) { ++ int bspi_width = BSPI_WIDTH_1BIT; ++ ++ /* Module parameter validation */ ++ if (io_mode != 0) { ++ if (read_opcode < 0 || read_opcode > 255) { ++ dev_err(&pdev->dev, "invalid read_opcode\n"); ++ io_mode = 0; ++ } else if (dummy_cycles < 0 || dummy_cycles > 255) { ++ dev_err(&pdev->dev, "invalid dummy_cycles\n"); ++ io_mode = 0; ++ } ++ } ++ if (io_mode == 2) { ++ bspi_width = BSPI_WIDTH_4BIT; ++ } else if (io_mode == 1) { ++ bspi_width = BSPI_WIDTH_2BIT; ++ } else if (io_mode != 0) { ++ dev_err(&pdev->dev, "invalid io_mode (0/1/2)\n"); ++ } ++ ++ if (io_mode == 2) ++ bcmspi_set_quad_mode(priv, 1); ++ ++ bcmspi_set_mode(priv, bspi_width, BSPI_ADDRLEN_3BYTES, bspi_hp); ++ } ++ ++ return 0; ++ ++err0: ++ bcmspi_hw_uninit(priv); ++err1: ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ free_irq(irq, priv); ++ } ++err2: ++ if (priv->idm_qspi) { ++ iounmap(priv->idm_qspi); ++ } ++ if (priv->qspi_intr) { ++ iounmap(priv->qspi_intr); ++ } ++ if (priv->bspi_hw_raf) { ++ iounmap(priv->bspi_hw_raf); ++ } ++ if (priv->bspi_hw) { ++ iounmap(priv->bspi_hw); ++ } ++ if (priv->mspi_hw) { ++ iounmap(priv->mspi_hw); ++ } ++ spi_master_put(master); ++ return ret; ++} ++ ++static int bcmspi_remove(struct platform_device *pdev) ++{ ++ struct bcmspi_priv *priv = platform_get_drvdata(pdev); ++ unsigned long flags; ++ struct resource *res; ++ u32 irq; ++ ++ /* acquire lock when the MSPI is idle */ ++ while (1) { ++ spin_lock_irqsave(&priv->lock, flags); ++ if (priv->state == STATE_IDLE) ++ break; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ udelay(100); ++ } ++ priv->state = STATE_SHUTDOWN; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ tasklet_kill(&priv->tasklet); ++ platform_set_drvdata(pdev, NULL); ++ bcmspi_hw_uninit(priv); ++ if (priv->bspi_hw_raf) ++ iounmap(priv->bspi_hw_raf); ++ if (priv->bspi_hw) ++ iounmap((volatile void __iomem *)priv->bspi_hw); ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (res) { ++ for(irq=(u32)res->start; irq<=(u32)res->end; irq++) { ++ free_irq(irq, priv); ++ } ++ } ++ iounmap((volatile void __iomem *)priv->mspi_hw); ++ spi_unregister_master(priv->master); ++ ++ return 0; ++} ++ ++static struct platform_driver driver = { ++ .driver = { ++ .name = "qspi_iproc", ++ .bus = &platform_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .probe = bcmspi_probe, ++ .remove = __devexit_p(bcmspi_remove), ++}; ++ ++static int __init bcmspi_spi_init(void) ++{ ++ platform_driver_register(&driver); ++ return 0; ++} ++ ++static void __exit bcmspi_spi_exit(void) ++{ ++ platform_driver_unregister(&driver); ++} ++ ++module_init(bcmspi_spi_init); ++module_exit(bcmspi_spi_exit); ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("iProc QSPI driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/smbus/.gitignore b/drivers/bcmdrivers/smbus/.gitignore +new file mode 100644 +index 0000000..0f97013 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/.gitignore +@@ -0,0 +1,8 @@ ++/.built-in.o.cmd ++/.iproc_i2c.o.cmd ++/.iproc_smbus.o.cmd ++/built-in.o ++/iproc_i2c.o ++/iproc_smbus.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/smbus/Kconfig b/drivers/bcmdrivers/smbus/Kconfig +new file mode 100644 +index 0000000..9ae0f71 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/Kconfig +@@ -0,0 +1,8 @@ ++config IPROC_I2C ++ tristate "I2C support" ++ depends on ARCH_IPROC ++ default n ++ help ++ I2C support ++ ++ If unsure, say N. +diff --git a/drivers/bcmdrivers/smbus/Makefile b/drivers/bcmdrivers/smbus/Makefile +new file mode 100644 +index 0000000..812c7a1 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_IPROC_I2C) += iproc_i2c.o ++iproc_i2c-objs := iproc_smbus.o +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus.c b/drivers/bcmdrivers/smbus/iproc_smbus.c +new file mode 100644 +index 0000000..49e25d6 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus.c +@@ -0,0 +1,2043 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iproc_smbus_regs.h" ++#include "iproc_smbus_defs.h" ++#include "iproc_smbus.h" ++#include ++#include ++#include ++#include ++#include ++ ++//#define IPROC_SMB_DBG 1 ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 37) ++#define init_MUTEX(x) sema_init(x,1) ++#endif ++ ++int brcm_get_hx4_model(void); ++ ++static struct proc_dir_entry *gProcParent; ++static int use_svk_version; ++ ++static int smb_in_intr; ++ ++static struct iproc_smb_drv_int_data *iproc_smbus_list = NULL; ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev); ++ ++/* Function to read a value from specified register. */ ++static unsigned int iproc_smb_reg_read(unsigned long reg_addr) ++{ ++ unsigned int val; ++ ++ val = ioread32((void *)reg_addr); ++ ++#ifdef IPROC_SMB_DBG ++ if (!smb_in_intr) { ++ printk(KERN_DEBUG "\nRd: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); ++ } ++#endif ++ ++ return(val); ++} ++ ++/* Function to write a value ('val') in to a specified register. */ ++static int iproc_smb_reg_write(unsigned long reg_addr, unsigned int val) ++{ ++ iowrite32(val, (void *)reg_addr); ++ ++#ifdef IPROC_SMB_DBG ++ if (!smb_in_intr) { ++ printk(KERN_DEBUG "\nWr: addr:0x%08X, val:0x%08X", (unsigned int)reg_addr, val); ++ } ++#endif ++ ++ return (0); ++} ++ ++static int iproc_dump_smb_regs(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ ++ printk(KERN_DEBUG "\n----------------------------------------------"); ++ ++ printk(KERN_DEBUG "\nBase addr=0x%08X", (unsigned int)base_addr); ++ ++ printk(KERN_DEBUG "%s: Dumping SMBus registers... ", __func__); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_CFG_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_CFG_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_TIMGCFG_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_ADDR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_ADDR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRFIFOCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRFIFOCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVFIFOCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVFIFOCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_BITBANGCTL_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_BITBANGCTL_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRCMD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRCMD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVCMD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVCMD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_EVTEN_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_EVTSTS_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATAWR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATAWR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_MSTRDATARD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_MSTRDATARD_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATAWR_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVDATAWR_REG=0x%08X", regval); ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_SLVDATARD_REG); ++ printk(KERN_DEBUG "\nCCB_SMB_SLVDATARD_REG=0x%08X", regval); ++ ++ printk(KERN_DEBUG "\n----------------------------------------------\n\n"); ++ ++ return(0); ++} ++ ++static irqreturn_t iproc_smb_isr(int irq, void*devid) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)devid; ++ unsigned int intsts; ++ unsigned int regval; ++ ++ ++ smb_in_intr = 1; ++ ++ intsts = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTSTS_REG); ++ ++ dev->smb_counters.last_int_sts = intsts; ++ ++ if (!intsts) { ++ ++ /* Likely received a spurious interrupt */ ++ ++ return IRQ_NONE; ++ ++ } ++ ++ /* Clear interrupts */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTSTS_REG, intsts); ++ ++ /* Master read or write complete */ ++ if ((intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) || ++ (intsts & CCB_SMB_MSTRRXEVTSTS_MASK)) { ++ ++ if (intsts & CCB_SMB_MSTRSTARTBUSYEN_MASK) { ++ ++ dev->smb_counters.mstr_start_busy_cnt++; ++ ++ } ++ ++ if (intsts & CCB_SMB_MSTRRXEVTSTS_MASK) { ++ ++ dev->smb_counters.mstr_rx_evt_cnt++; ++ ++ } ++ ++ /* In case of a receive transaction, data will be copied in the recv ++ * function ++ */ ++ complete(&dev->ses_done); ++ ++ } ++ ++ /* If RX FIFO was full we can either read and then flush the FIFO. Or, only ++ * flush the FIFO (since the client process did not read the data on time), ++ * and then the client process can restart the transaction ++ * For now, we will flush the later action. ++ */ ++ if (intsts & CCB_SMB_MSTRRXFIFOFULLSTS_MASK) { ++ ++ dev->smb_counters.mstr_rx_fifo_full_cnt++; ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRFIFOCTL_REG); ++ ++ regval |= CCB_SMB_MSTRRXFIFOFLSH_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRFIFOCTL_REG, regval); ++ ++ complete(&dev->ses_done); ++ ++ } ++ ++ smb_in_intr = 0; ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Function to ensure that the previous transaction was completed before ++ * initiating a new transaction. It can also be used in polling mode to ++ * check status of completion of a command ++ */ ++static int iproc_smb_startbusy_wait(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* Check if an operation is in progress. During probe it won't be. ++ * But when shutdown/remove was called we want to make sure that ++ * the transaction in progress completed ++ */ ++ if (regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) { ++ unsigned int i = 0; ++ ++ do { ++ ++ msleep(1); /* Wait for 1 msec */ ++ ++ i++; ++ ++ regval = iproc_smb_reg_read( ++ (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG); ++ ++ /* If start-busy bit cleared, exit the loop */ ++ } while ((regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK) && ++ (i < IPROC_SMB_MAX_RETRIES)); ++ ++ if (i >= IPROC_SMB_MAX_RETRIES) { ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: %s START_BUSY bit didn't clear, exiting\n", ++ __func__, dev->adapter.name); ++#endif ++ return -ETIMEDOUT; ++ ++ } ++ ++ } ++ ++ return 0; ++} ++ ++ ++static unsigned int smbus0_sdaRecoveryCnt = 0, smbus0_sdaFailedCnt = 0, smbus0_startBusyCnt = 0; ++static unsigned int smbus1_sdaRecoveryCnt = 0, smbus1_sdaFailedCnt = 0, smbus1_startBusyCnt = 0; ++ ++/* ++ * Function to recover SMB hangs caused stuck master START_BUSY. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_startbusy_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ int rc = -1; ++ unsigned int recoveryCnt; ++ ++ if (dev->adapter.nr == 0) { ++ recoveryCnt = ++smbus0_startBusyCnt; ++ } ++ else { ++ recoveryCnt = ++smbus1_startBusyCnt; ++ } ++ ++ printk(KERN_INFO "%s: %s START_BUSY recovery #%d \n", __func__, dev->adapter.name, recoveryCnt); ++ ++ /* reset the SMBus block, wait a minimum of 50 uSecs and then re-initialize */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, CCB_SMB_CFG_RST_MASK); ++ udelay(60); ++ ++ if ( iproc_smbus_block_init(dev) == 0 ) { ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device holding SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++ ++static int iproc_smb_sda_low_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, cfgReg, cfgSave, recoveryCnt, failedCnt, i; ++ int rc = -1; ++ ++ ++ /* enable bit-bang */ ++ cfgSave = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ cfgReg = cfgSave; ++ cfgReg |= CCB_SMB_CFG_BITBANGEN_MASK; ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); ++ udelay(50); ++ ++ /* start with clock and SDA set high */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ ++ bbReg |= (CCB_SMB_SMBCLKOUTEN_MASK | CCB_SMB_SMBDATAOUTEN_MASK); ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); /* should be sufficient for 100 KHz bus */ ++ ++ /* set up to toggle the clock line with SDA out held high for 9 cycles */ ++ for (i=0; i<18; i++) ++ { ++ /* toggle CLK out */ ++ if ( (bbReg & CCB_SMB_SMBCLKOUTEN_MASK) == 0 ) { ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ } ++ else { ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ } ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); ++ } ++ ++ /* check bit 29 -- SMBDAT_IN and make sure SDA not being held low any more */ ++ for ( i=0; i<10; i++ ) ++ { ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= CCB_SMB_SMBDATAIN_MASK; ++ ++ if (bbReg) ++ break; ++ ++ udelay(1); ++ } ++ ++ if ( bbReg == 0 ) { ++ /* SDA is still low */ ++ if (dev->adapter.nr == 0) { ++ failedCnt = ++smbus0_sdaFailedCnt; ++ } ++ else { ++ failedCnt = ++smbus1_sdaFailedCnt; ++ } ++ printk(KERN_INFO "\n%s: %s SDA release #%d FAILED.\n", __func__, dev->adapter.name, failedCnt); ++ } ++ else { ++ if (dev->adapter.nr == 0) { ++ recoveryCnt = ++smbus0_sdaRecoveryCnt; ++ } ++ else { ++ recoveryCnt = ++smbus1_sdaRecoveryCnt; ++ } ++ ++ printk(KERN_INFO "%s: %s SDA release #%d SUCCESSFUL.\n", __func__, dev->adapter.name, recoveryCnt); ++ rc = 0; ++ } ++ ++ ++ /* manually issue a stop by transitioning SDA from low to high with clock held high */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ bbReg &= ~CCB_SMB_SMBCLKOUTEN_MASK; /* set clock low */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ bbReg &= ~CCB_SMB_SMBDATAOUTEN_MASK; /* drop SDA low */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ bbReg |= CCB_SMB_SMBCLKOUTEN_MASK; /* set clock high */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(5); ++ ++ bbReg |= CCB_SMB_SMBDATAOUTEN_MASK; /* pull SDA high */ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG, bbReg); ++ udelay(2); ++ ++ ++ /* disable bit-bang and then re-enable the SMB with the saved configuration */ ++ cfgReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ cfgReg &= ~CCB_SMB_CFG_BITBANGEN_MASK; ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgReg); ++ udelay(10); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, cfgSave); ++ ++ return rc; ++} ++ ++ ++/* ++ * Function to recover SMB hang caused by a slave device hold SDA low. ++ * Returns 0 if recovery procedure executed successfully. ++ * Returns -1 if recovery failed. ++ */ ++static int iproc_smb_timeout_recovery(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int bbReg, mCmdReg; ++ int rc = -1; ++ ++ /* read bit-bang control. If SDA low, attempt SDA release recovery */ ++ bbReg = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_BITBANGCTL_REG); ++ ++ if ( (bbReg & CCB_SMB_SMBDATAIN_MASK) == 0 ) { ++ if ( iproc_smb_sda_low_recovery( dev ) == 0 ) { ++ rc = 0; ++ } ++ } ++ ++ /* regardless of whether there was an SDA hang or not, see if START_BUSY stuck high */ ++ mCmdReg = iproc_smb_reg_read( (unsigned long)dev->block_base_addr + CCB_SMB_MSTRCMD_REG ); ++ if ( mCmdReg & CCB_SMB_MSTRSTARTBUSYCMD_MASK ) { ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) == 0) { ++ rc = 0; ++ } ++ } ++ ++ return rc; ++ ++} ++ ++/* ++ * This function copies data to SMBus's Tx FIFO. Valid for write transactions ++ * only ++ * ++ * base_addr: Mapped address of this SMBus instance ++ * dev_addr: SMBus (I2C) device address. We are assuming 7-bit addresses ++ * initially ++ * info: Data to copy in to Tx FIFO. For read commands, the size should be ++ * set to zero by the caller ++ * ++ */ ++static void iproc_smb_write_trans_data(unsigned long base_addr, ++ unsigned short dev_addr, ++ struct iproc_xact_info *info) ++{ ++ unsigned int regval; ++ unsigned int i; ++ unsigned int num_data_bytes = 0; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: dev_addr=0x%X, offset=%u, cmd_valid=%u, size=%u\n", __func__, dev_addr, info->command, info->cmd_valid, info->size); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Write SMBus device address first */ ++ /* Note, we are assuming 7-bit addresses for now. For 10-bit addresses, ++ * we may have one more write to send the upper 3 bits of 10-bit addr ++ */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, dev_addr); ++ ++ /* If the protocol needs command code, copy it */ ++ if (info->cmd_valid == true) { ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->command); ++ ++ } ++ ++ /* Depending on the SMBus protocol, we need to write additional transaction ++ * data in to Tx FIFO. Refer to section 5.5 of SMBus spec for sequence for a ++ * transaction ++ */ ++ switch (info->smb_proto) { ++ ++ case SMBUS_PROT_RECV_BYTE: ++ /* No additional data to be written */ ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_SEND_BYTE: ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_RD_BYTE: ++ case SMBUS_PROT_RD_WORD: ++ case SMBUS_PROT_BLK_RD: ++ /* Write slave address with R/W~ set (bit #0) */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, ++ dev_addr | 0x1); ++ num_data_bytes = 0; ++ break; ++ ++ case SMBUS_PROT_WR_BYTE: ++ case SMBUS_PROT_WR_WORD: ++ /* No additional bytes to be written. Data portion is written in the ++ * 'for' loop below ++ */ ++ num_data_bytes = info->size; ++ ++ /* Note for hx4 eeprom (at24c64). the low addr bytes can be passed ++ * in to 1st byte of info->data ++ */ ++ break; ++ ++ case SMBUS_PROT_BLK_WR: ++ /* 3rd byte is byte count */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); ++ num_data_bytes = info->size; ++ break; ++ ++ case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: ++ /* Write byte count */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, info->size); ++ num_data_bytes = info->size; ++ break; ++ ++ default: ++ break; ++ ++ } ++ ++ /* Copy actual data from caller, next. In general, for reads, no data is ++ * copied ++ */ ++ for (i = 0; num_data_bytes; --num_data_bytes, i++) { ++ ++ /* For the last byte, set MASTER_WR_STATUS bit. For block rd/wr process ++ * call, we need to program slave addr after copying data byte(s), so ++ * master status bit is set later, after the loop ++ */ ++ if ((num_data_bytes == 1) && ++ (info->smb_proto != SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ regval = info->data[i] | CCB_SMB_MSTRWRSTS_MASK; ++ } ++ else { ++ regval = info->data[i]; ++ } ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, regval); ++ ++ } ++ ++ if (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL) { ++ /* Write device address needed during repeat start condition */ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRDATAWR_REG, ++ CCB_SMB_MSTRWRSTS_MASK | dev_addr | 0x1); ++ } ++ ++ return; ++} ++ ++static int iproc_smb_data_send(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: Send: %s bus is busy, attempt recovery \n", ++ __func__, dev->adapter.name); ++#endif ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) { ++ ++ return rc; ++ ++ } ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* Enable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval |= CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ /* Mark as incomplete before sending the data */ ++ INIT_COMPLETION(dev->ses_done); ++ ++ } ++ ++ /* Write transaction bytes to Tx FIFO */ ++ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG, regval); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* ++ * Block waiting for the transaction to finish. When it's finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); ++ ++ /* Disable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval &= ~CCB_SMB_MSTRSTARTBUSYEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ if (time_left == 0) { ++ ++ printk (KERN_INFO "%s: Send: %s timeout accessing device x%02x\n", ++ __func__, dev->adapter.name, addr); ++ ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if ( rc != 0 ) { ++ ++ return -ETIMEDOUT; ++ ++ } ++ else { ++ return -ECOMM; ++ } ++ ++ } ++ ++ } ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++ ++ /* We can flush Tx FIFO here */ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n\n%s:Send: %s Error in transaction %d to device x%02x, exiting\n", ++ __func__, dev->adapter.name, regval, addr); ++#endif ++ return -EREMOTEIO; ++ ++ } ++ } ++ ++ return(0); ++} ++ ++static int iproc_smb_data_recv(struct i2c_adapter *adapter, ++ unsigned short addr, ++ struct iproc_xact_info *info, ++ unsigned int *num_bytes_read) ++{ ++ int rc; ++ unsigned int regval; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(adapter); ++ unsigned long time_left; ++ ++ /* Make sure the previous transaction completed */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: Receive: %s bus is busy, attempt recovery \n", __func__, dev->adapter.name); ++#endif ++ /* attempt to recover the bus */ ++ if (iproc_smb_startbusy_recovery(dev) != 0) { ++ return rc; ++ } ++ } ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* Enable start_busy interrupt */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ /* Set Rx_event_en bit for notification of reception event */ ++ regval |= (CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ /* Mark as incomplete before sending the data */ ++ INIT_COMPLETION(dev->ses_done); ++ ++ } ++ ++ /* Program all transaction bytes into master Tx FIFO */ ++ iproc_smb_write_trans_data((unsigned long)dev->block_base_addr, addr, info); ++ ++ /* Program master command register (0x30) with protocol type and set ++ * start_busy_command bit to initiate the write transaction ++ */ ++ regval = (info->smb_proto << CCB_SMB_MSTRSMBUSPROTO_SHIFT) | ++ CCB_SMB_MSTRSTARTBUSYCMD_MASK | info->size; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG, regval); ++ ++ if (dev->enable_evts == ENABLE_INTR) { ++ ++ /* ++ * Block waiting for the transaction to finish. When it's finished, ++ * we'll be signaled by an interrupt ++ */ ++ time_left = wait_for_completion_timeout(&dev->ses_done, XACT_TIMEOUT); ++ ++ /* Disable start_busy and rx_event interrupts. Above call has handled ++ * the interrupt ++ */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG); ++ ++ regval &= ~(CCB_SMB_MSTRSTARTBUSYEN_MASK); ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + ++ CCB_SMB_EVTEN_REG, regval); ++ ++ if (time_left == 0) { ++ ++ printk (KERN_INFO "\n%s: Receive: %s timeout accessing device 0x%02x\n", ++ __func__, dev->adapter.name, addr); ++ ++ /* attempt to recover the bus */ ++ rc = iproc_smb_timeout_recovery(dev); ++ if ( rc != 0 ) { ++ return -ETIMEDOUT; ++ } ++ else { ++ return -ECOMM; ++ } ++ } ++ ++ } ++ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRCMD_REG); ++ ++ /* If start_busy bit cleared, check if there are any errors */ ++ if (!(regval & CCB_SMB_MSTRSTARTBUSYCMD_MASK)) { ++ ++ /* start_busy bit cleared, check master_status field now */ ++ regval &= CCB_SMB_MSTRSTS_MASK; ++ regval >>= CCB_SMB_MSTRSTS_SHIFT; ++ ++ if (regval != MSTR_STS_XACT_SUCCESS) { ++#ifdef IPROC_SMB_DBG ++ /* We can flush Tx FIFO here */ ++ printk(KERN_INFO "\n%s: %s Error in transaction %d to device x%02x, exiting\n", ++ __func__, dev->adapter.name, regval, addr); ++#endif ++ return -EREMOTEIO; ++ ++ } ++ ++ } ++ ++ /* In the isr we will read the received byte, and also deal with ++ * rx fifo full event. The above check is for timeout error. If needed ++ * we may move it to rx isr ++ */ ++ ++ /* Read received byte(s) */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ /* For block read, protocol (hw) returns byte count, as the first byte */ ++ if ((info->smb_proto == SMBUS_PROT_BLK_RD) || ++ (info->smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ ++ int i; ++ ++ *num_bytes_read = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ /* Limit to reading a max of 32 bytes only; just a safeguard. If ++ * # bytes read is a number > 32, check transaction set up, and contact ++ * hw engg. Assumption: PEC is disabled ++ */ ++ for (i = 0; (i < *num_bytes_read) && (i < I2C_SMBUS_BLOCK_MAX); i++) { ++ ++ /* Read Rx FIFO for data bytes */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ info->data[i] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ } ++ ++ } ++ else { ++ ++ *info->data = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ *num_bytes_read = 1; ++ ++ if (info->smb_proto == SMBUS_PROT_RD_WORD) { ++ /* Read Rx FIFO for data bytes */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + ++ CCB_SMB_MSTRDATARD_REG); ++ ++ info->data[1] = regval & CCB_SMB_MSTRRDDATA_MASK; ++ ++ *num_bytes_read = 2; ++ } ++ } ++ ++ return(0); ++} ++ ++static int iproc_smb_xfer(struct i2c_adapter *i2c_adap, u16 addr, ++ unsigned short flags, char read_write, ++ u8 command, int size, union i2c_smbus_data *data) ++{ ++ int rc; ++ struct iproc_smb_drv_int_data *dev = i2c_get_adapdata(i2c_adap); ++ struct iproc_xact_info info; ++ unsigned int num_bytes_read = 0; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: dev=0x%08X\n", __func__, (unsigned int)dev); ++#endif ++ ++ down(&dev->xfer_lock); ++ ++ addr <<= 1; ++ ++ switch (size /* protocol */) { ++ ++ case I2C_SMBUS_QUICK: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ info.smb_proto = SMBUS_PROT_QUICK_CMD; ++ info.data = &data->byte; /* not used */ ++ info.size = 0; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ addr |= 0x1; /* read operation */ ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE: ++ info.cmd_valid = false; ++ info.command = command; /* not used */ ++ if (read_write == I2C_SMBUS_WRITE) { ++ ++ info.data = &command; ++ ++ } ++ else { ++ ++ info.data = &data->byte; ++ ++ } ++ info.size = 1; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ addr |= 0x1; /* Read operation */ ++ ++ info.smb_proto = SMBUS_PROT_RECV_BYTE; ++ info.data = &data->byte; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_SEND_BYTE; ++ ++ } ++ break; ++ ++ case I2C_SMBUS_BYTE_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->byte; ++ info.size = 1; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ info.smb_proto = SMBUS_PROT_RD_BYTE; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_WR_BYTE; ++ //info.smb_proto = SMBUS_PROT_WR_WORD; /* TEMP chg. remove later */ ++ ++ } ++ break; ++ ++ case I2C_SMBUS_WORD_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = (unsigned char *)(&data->word); ++ info.size = 2; ++ info.flags = flags; ++ if (read_write == I2C_SMBUS_READ) { ++ info.smb_proto = SMBUS_PROT_RD_WORD; ++ } ++ else { ++ info.smb_proto = SMBUS_PROT_WR_WORD; ++ } ++ ++ break; ++ ++ case I2C_SMBUS_BLOCK_DATA: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ ++ if (read_write == I2C_SMBUS_READ) { ++ ++ info.smb_proto = SMBUS_PROT_BLK_RD; ++ ++ /* Protocol(hw) returns data byte count as part of response */ ++ info.size = 0; ++ ++ } ++ else { ++ ++ info.smb_proto = SMBUS_PROT_BLK_WR; ++ ++ info.size = data->block[0]; /* i2c-core passes the length in ++ this field */ ++ ++ } ++ ++ break; ++ ++ case I2C_SMBUS_BLOCK_PROC_CALL: ++ info.cmd_valid = true; ++ info.command = command; ++ info.data = &data->block[1]; ++ info.flags = flags; ++ info.smb_proto = SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: Unsupported transaction %d\n", __func__, size); ++ up(&dev->xfer_lock); ++ return -EINVAL; ++ ++ } ++ ++ ++ if (read_write == I2C_SMBUS_READ) { ++ /* Refer to i2c_smbus_read_byte for params passed. */ ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); ++ ++ /* if failed due to bus hang, but recovered, retry once */ ++ if (rc == -ECOMM) { ++ rc = iproc_smb_data_recv(i2c_adap, addr, &info, &num_bytes_read); ++ } ++ ++ /* For block read call, we pass the actual amount of data sent by ++ * slave, as expected by std Linux API ++ */ ++ if ((info.smb_proto == SMBUS_PROT_BLK_RD) || ++ (info.smb_proto == SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL)) { ++ ++ if (rc == 0) { ++ ++ data->block[0] = num_bytes_read; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_ERR "%s: num bytes read=%u\n", ++ __func__, data->block[0]); ++#endif ++ ++ } ++ } ++ ++ } ++ else { ++ ++ /* Refer to i2c_smbus_write_byte params passed. */ ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ ++ /* if failed due to bus hang, but recovered, retry */ ++ if (rc == -ECOMM) { ++ rc = iproc_smb_data_send(i2c_adap, addr, &info); ++ } ++ ++ } ++ ++ if (rc < 0) { ++#ifdef PROC_SMB_DBG ++ printk(KERN_INFO "%s %s: %s error accessing device 0x%X rc=%d", __func__, dev->adapter.name, ++ (read_write == I2C_SMBUS_READ) ? "Read" : "Write", addr, rc); ++#endif ++ up(&dev->xfer_lock); ++ ++ return -EREMOTEIO; ++ ++ } ++ ++ up(&dev->xfer_lock); ++ ++ return (rc); ++} ++ ++static int ++proc_debug_read(char *buffer, ++ char **start, ++ off_t off, ++ int count, ++ int *eof, ++ void *data) ++{ ++ unsigned int len = 0; ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ ++ if (off > 0) ++ return 0; ++ ++ len += sprintf(buffer + len, "Debug print is %s\n", ++ dev->debug ? "enabled" : "disabled"); ++ ++ return len; ++} ++ ++/* Command interface for reading/writing to various I2C/SMBus devices */ ++static int ++proc_debug_write(struct file *file, ++ const char __user *buffer, ++ unsigned long count, ++ void *data) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ unsigned char kbuf[MAX_PROC_BUF_SIZE]; ++ union i2c_smbus_data i2cdata; ++ unsigned int val, i2cdev_addr, rd_wr_op; ++ int addr; ++ ++ if (count > MAX_PROC_BUF_SIZE) { ++ ++ count = MAX_PROC_BUF_SIZE; ++ ++ } ++ ++ rc = copy_from_user(kbuf, buffer, count); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); ++ ++ return -EFAULT; ++ ++ } ++ ++ rc = sscanf(kbuf, "%u %u %d %u", &rd_wr_op, &i2cdev_addr, &addr, &val); ++ ++ if (rc != 4) { ++ ++ printk(KERN_ERR "\necho args > %s", PROC_ENTRY_DEBUG); ++ printk(KERN_ERR "\nargs (all values should be in decimal)):"); ++ printk(KERN_ERR "\nrd_wr_op: 1 = read, 0 = write"); ++ printk(KERN_ERR "\ni2cdev_addr: I2C device address in decimal"); ++ printk(KERN_ERR "\noffset: offset of location within I2C device"); ++ printk(KERN_ERR "\naddr -1 if offset not applicable"); ++ printk(KERN_ERR "\nval: For write op: 8-bit value.\n" ++ " For read op: not used, may be 0\n\n"); ++ ++ return count; ++ ++ } ++ ++ printk(KERN_DEBUG "\n\nArg values :"); ++ printk(KERN_DEBUG "\nrd_wr_op = %u", rd_wr_op); ++ printk(KERN_DEBUG "\ni2cdev_addr = 0x%X", i2cdev_addr); ++ printk(KERN_DEBUG "\noffset = %d", addr); ++ printk(KERN_DEBUG "\nval = %u", val); ++ ++ if (rd_wr_op > 1) { ++ ++ printk(KERN_ERR "\nError: Invalid rd_wr_op value %u\n\n", rd_wr_op); ++ return count; ++ ++ } ++ ++ if (i2cdev_addr > 127) { ++ ++ printk(KERN_ERR "\nError: i2cdev_addr must be 7-bit value\n\n"); ++ return count; ++ ++ } ++ ++ if (addr > 255) { ++ ++ printk(KERN_ERR "\nError: offset out of range for this device\n\n"); ++ return count; ++ ++ } ++ ++ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ if (rd_wr_op == 0) { /* Write operation */ ++ ++ i2cdata.byte = val; ++ ++ if (addr == -1) { ++ ++ /* Device does not support, or require an offset to write to the ++ * location ++ */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, ++ I2C_SMBUS_WRITE, (unsigned char)0, ++ I2C_SMBUS_BYTE, &i2cdata); ++ ++ } ++ else { ++ ++ /* Address required for write access */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, ++ I2C_SMBUS_WRITE, addr, I2C_SMBUS_BYTE_DATA, ++ &i2cdata); ++ } ++ ++ if (rc) { ++ ++ printk (KERN_ERR "\n%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X\n", __func__, rc, addr, val); ++ ++ /* return -EFAULT; */ ++ ++ } ++ else { ++ ++ printk(KERN_ERR "\nWrite OK.\nWrote 0x%X at addr %u\n\n", ++ val, addr); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ if (rd_wr_op == 1) { /* Read operation */ ++ ++ if (addr == -1) { ++ ++ /* Device does not support, or require an offset to read from the ++ * location ++ */ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, ++ (unsigned char)0, I2C_SMBUS_BYTE, &i2cdata); ++ ++ } ++ else { ++ ++ rc = iproc_smb_xfer(&dev->adapter, i2cdev_addr, 0x0, I2C_SMBUS_READ, ++ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ } ++ ++ if (rc) { ++ ++ printk (KERN_ERR "\n%s: iproc_smb_xfer failed status=%d\n", ++ __func__, rc); ++ ++ /* return -EFAULT; */ ++ ++ } ++ else { ++ ++ printk(KERN_ERR "\nRead OK.\n--------Value read at %u = 0x%X\n\n", ++ addr, i2cdata.byte); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", ++ dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return count; ++} ++ ++/* Written for SVK boards */ ++static int ++proc_debug_write_svk(struct file *file, ++ const char __user *buffer, ++ unsigned long count, ++ void *data) ++{ ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ unsigned int debug; ++ unsigned char kbuf[MAX_PROC_BUF_SIZE]; ++ union i2c_smbus_data i2cdata; ++ unsigned int val, addr; ++ ++ if (count > MAX_PROC_BUF_SIZE) { ++ ++ count = MAX_PROC_BUF_SIZE; ++ ++ } ++ ++ rc = copy_from_user(kbuf, buffer, count); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: copy_from_user failed status=%d", __func__, rc); ++ ++ return -EFAULT; ++ ++ } ++ ++ if (sscanf(kbuf, "%u", &debug) != 1) { ++ ++ printk(KERN_ERR "%s: echo > %s\n", __func__, PROC_ENTRY_DEBUG); ++ ++ return count; ++ ++ } ++ ++ if (debug) { ++ ++ dev->debug = 1; ++ ++ } ++ else { ++ ++ dev->debug = 0; ++ ++ } ++ ++ printk (KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ if (!dev->debug) { ++ ++ val = 0xFF; /* Initial value to write */ ++ ++ for(addr = 0x0; addr < 256; val--, addr++) { ++ ++ i2cdata.byte = val; ++ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, ++ addr, I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X", __func__, rc, addr, val); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nWrite OK.\nWrote 0x%X at addr %u\n\n", ++ val, addr); ++ ++ } ++ ++ msleep(1); /* Delay required, since smb(i2c) interface is slow */ ++ ++ } ++ ++ } ++ else { ++ ++ int i; ++ ++ /* Note about address expected by AT24C02: To write in correct order ++ * to AT24C02 using block write, refer bottom of page 9 (Write ++ * Operations) of the data sheet regarding internal incrementing of ++ * address. Based on that explanation, we program the addr value below. ++ * Select the 'highest' address in that page (7, 15, 23, and so on) to ++ * write to that page ++ */ ++ addr = debug - 1; ++ ++ val = jiffies % 256; ++ ++ printk(KERN_DEBUG "\nEEPROM page write. Page start addr = %u," ++ " write data: \n\n", debug - 8); ++ ++ for (i = 1; i <= 8; i++) { ++ ++ i2cdata.block[i] = val % 256; /* Fill a sequence pattern */ ++ ++ val++; ++ ++ printk(KERN_DEBUG "\nbyte%d = 0x%02X\n", i, i2cdata.block[i]); ++ ++ } ++ ++ i2cdata.block[0] = 8; ++ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_WRITE, ++ addr, I2C_SMBUS_BLOCK_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer:write failed status=%d," ++ " addr=%u, val = 0x%X", __func__, rc, addr, val); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nBlock Write OK.\n\n"); ++ ++ } ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", ++ dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return count; ++} ++ ++/* Written for SVK boards */ ++static int ++proc_debug_read_svk(char *buffer, ++ char **start, ++ off_t off, ++ int count, ++ int *eof, ++ void *data) ++{ ++ unsigned int len = 0; ++ struct iproc_smb_drv_int_data *dev = ++ (struct iproc_smb_drv_int_data *)data; ++ int rc; ++ union i2c_smbus_data i2cdata; ++ unsigned int addr; ++ ++ if (off > 0) { ++ ++ return 0; ++ ++ } ++ ++ len += sprintf(buffer + len, "Read\n"); ++ ++ printk(KERN_ERR "\nCommand can execute slow, please wait...\n"); ++ ++ for(addr = 0x0; addr < 256; addr++) { ++ ++ /* Read operation */ ++ rc = iproc_smb_xfer(&dev->adapter, 0xA0 >> 1, 0x0, I2C_SMBUS_READ, addr, ++ I2C_SMBUS_BYTE_DATA, &i2cdata); ++ ++ if (rc) { ++ ++ printk (KERN_ERR "%s: iproc_smb_xfer failed status=%d", __func__, rc); ++ ++ } ++ else { ++ ++ printk(KERN_DEBUG "\nRead OK.\n--------Value read at %u = 0x%X\n", ++ addr, i2cdata.byte); ++ ++ } ++ ++ msleep(1); ++ ++ } ++ ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "\n\nLast intr sts = 0x%08X", dev->smb_counters.last_int_sts); ++ ++ printk(KERN_DEBUG "mstr_start_busy_cnt = %u, mstr_rx_evt_cnt = %u, rx fifo full cnt = %u\n\n", ++ dev->smb_counters.mstr_start_busy_cnt, ++ dev->smb_counters.mstr_rx_evt_cnt, ++ dev->smb_counters.mstr_rx_fifo_full_cnt); ++ ++ return len; ++} ++ ++static int proc_init(struct platform_device *pdev) ++{ ++ int rc, id; ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct procfs *proc = &dev->proc; ++ struct proc_dir_entry *proc_debug; ++ ++ if (pdev->dev.of_node) { ++ id = of_alias_get_id(pdev->dev.of_node, "i2c-controller");; ++ } else { ++ id = pdev->id; ++ } ++ snprintf(proc->name, sizeof(proc->name), "%s%d", PROC_GLOBAL_PARENT_DIR, id); ++ ++ /* sub directory */ ++ proc->parent = proc_mkdir(proc->name, gProcParent); ++ ++ if (proc->parent == NULL) { ++ ++ return -ENOMEM; ++ ++ } ++ ++ proc_debug = create_proc_entry(PROC_ENTRY_DEBUG, 0644, proc->parent); ++ ++ if (proc_debug == NULL) { ++ ++ rc = -ENOMEM; ++ ++ goto err_del_parent; ++ } ++ ++ use_svk_version = 0; /* Do not use SVK version */ ++ ++ if (use_svk_version) { ++ ++ proc_debug->read_proc = proc_debug_read_svk; ++ proc_debug->write_proc = proc_debug_write_svk; ++ ++ } ++ else { ++ ++ proc_debug->read_proc = proc_debug_read; ++ proc_debug->write_proc = proc_debug_write; ++ ++ } ++ ++ proc_debug->data = dev; ++ ++ return 0; ++ ++err_del_parent: ++ remove_proc_entry(proc->name, gProcParent); ++ ++ return rc; ++} ++ ++static int proc_term(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct procfs *proc = &dev->proc; ++ ++ remove_proc_entry(PROC_ENTRY_DEBUG, proc->parent); ++ remove_proc_entry(proc->name, gProcParent); ++ ++ return 0; ++} ++ ++/* ++ * This function set clock frequency for SMBus block. As per hardware ++ * engineering, the clock frequency can be changed dynamically. ++ */ ++static int iproc_smb_set_clk_freq(struct iproc_smb_drv_int_data *iproc_i2c) ++{ ++ /* Default clock frequency is 100KHz */ ++ unsigned int bus_speed = 100000; ++ unsigned long base_addr = (unsigned long)iproc_i2c->block_base_addr; ++ unsigned int regval; ++ unsigned int val; ++ int ret; ++ ++ if (iproc_i2c->dev->of_node) { ++ /* DT based instantiation */ ++ ret = of_property_read_u32(iproc_i2c->dev->of_node, ++ "clock-frequency", &bus_speed); ++ if (ret < 0) { ++ dev_info(iproc_i2c->dev, ++ "unable to interpret clock-frequency DT property\n"); ++ bus_speed = 100000; ++ } ++ } else { ++ /* Non-DT based instantiation */ ++ bus_speed = 100000; ++ } ++ ++ if (bus_speed < 100000) { ++ dev_err(iproc_i2c->dev, "%d Hz bus speed not supported\n", ++ bus_speed); ++ dev_err(iproc_i2c->dev, ++ "valid speeds are 100khz and 400khz\n"); ++ return -EINVAL; ++ } else if (bus_speed < 400000) { ++ bus_speed = 100000; ++ } else { ++ bus_speed = 400000; ++ } ++ ++ switch (bus_speed) { ++ case 100000: ++ val = 0; ++ break; ++ ++ case 400000: ++ val = 1; ++ break; ++ ++ default: ++ return -EINVAL; ++ break; ++ ++ } ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_TIMGCFG_REG); ++ ++ SETREGFLDVAL(regval, val, CCB_SMB_TIMGCFG_MODE400_MASK, ++ CCB_SMB_TIMGCFG_MODE400_SHIFT); ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_TIMGCFG_REG, regval); ++ ++ dev_info(iproc_i2c->dev, "bus set to %u Hz\n", bus_speed); ++ return(0); ++} ++ ++static int iproc_smbus_block_init(struct iproc_smb_drv_int_data *dev) ++{ ++ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ /* Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. ++ * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts ++ */ ++ regval = CCB_SMB_MSTRRXFIFOFLSH_MASK | CCB_SMB_MSTRTXFIFOFLSH_MASK; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_MSTRFIFOCTL_REG, regval); ++ ++ /* Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero ++ * since there will be only one master ++ */ ++ regval = CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_CFG_REG, regval); ++ ++ /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ ++ udelay(100); ++ ++ ++ /* Set default clock frequency baed on device tree */ ++ iproc_smb_set_clk_freq(dev); ++ ++ /* Disable intrs */ ++ regval = 0x0; ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Clear intrs (W1TC) */ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTSTS_REG); ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTSTS_REG, regval); ++ ++ return(0); ++} ++ ++/* This function enables interrupts */ ++static int iproc_intr_enable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) ++{ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ ++ regval |= bmap; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Store all interrupts enabled so far. Note bmap can have only 'incremental' ++ * set of events ++ */ ++ dev->evt_enable_bmap = regval; ++ ++ return(0); ++} ++ ++/* This function disables interrupts */ ++static int iproc_intr_disable(struct iproc_smb_drv_int_data *dev, unsigned int bmap) ++{ ++ unsigned long base_addr = (unsigned long)dev->block_base_addr; ++ unsigned int regval; ++ ++ regval = iproc_smb_reg_read(base_addr + CCB_SMB_EVTEN_REG); ++ ++ regval &= ~bmap; ++ ++ iproc_smb_reg_write(base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ dev->evt_enable_bmap = regval; ++ ++ return(0); ++} ++ ++/* Verify this sequence with hw engg */ ++static int iproc_smbus_block_deinit(struct iproc_smb_drv_int_data *dev) ++{ ++ unsigned int regval; ++ int rc; ++ ++ /* Disable all interrupts */ ++ regval = 0x0; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_EVTEN_REG, regval); ++ ++ /* Check if a transaction is in progress */ ++ rc = iproc_smb_startbusy_wait(dev); ++ ++ if (rc < 0) { ++ ++ /* Do not exit the function, since we are most likely shutting down */ ++ printk(KERN_ERR "%s: A transaction is still in progress," ++ "but still continuing ", __func__); ++ ++ } ++ ++ /* Disable SMBus block */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ ++ /* Wait for some time */ ++ udelay(100); ++ ++ /* Put the block under reset. Note the RESET bit in reg 0x0 is ++ * self clearing ++ */ ++ regval = CCB_SMB_CFG_RST_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ return(0); ++} ++ ++static u32 iproc_smb_funcs(struct i2c_adapter *adapter) ++{ ++ /* Note: Other SMBus commands can be supported if we know the requirements ++ * more precisely ++ */ ++ return (I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_QUICK | ++ I2C_FUNC_SMBUS_READ_BYTE); ++} ++ ++static struct i2c_algorithm iproc_smb_algorithm = { ++ /* .name = "iproc-smb", */ ++ .smbus_xfer = iproc_smb_xfer, ++ .master_xfer = NULL, ++ .functionality = iproc_smb_funcs, ++}; ++ ++enum { ++ HX4_NONE = 0, ++ HX4_DNI_3448P, ++ HX4_ACCTON_AS4610_54 ++}; ++ ++static int __devinit iproc_smb_probe(struct platform_device *pdev) ++{ ++ int rc=0, irq, id; ++ struct iproc_smb_drv_int_data *dev; ++ struct i2c_adapter *adap; ++ struct resource *iomem; ++ struct resource *ioarea; ++ ++ if (pdev->dev.of_node) { ++ id = of_alias_get_id(pdev->dev.of_node, "i2c-controller");; ++ } else { ++ id = pdev->id; ++ } ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: Entering probe\n", __func__); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Get register memory resource */ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (!iomem) { ++ ++ printk(KERN_ERR "%s: No mem resource\n", __func__); ++ ++ return -ENODEV; ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot iomem 0x%p\n", iomem); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Get the interrupt number */ ++ irq = platform_get_irq(pdev, 0); ++ ++ if (irq == -ENXIO) { ++ if (brcm_get_hx4_model() == 0) { ++ printk(KERN_ERR "%s: No irq resource\n", __func__); ++ return -ENODEV; ++ } ++ /* Accton AS4610-54 or DNI-3448P */ ++ if (id == 0) { ++ irq = 127; ++ } else if (id == 1) { ++ irq = 128; ++ } else { ++ printk(KERN_ERR "%s: No irq resource\n", __func__); ++ return -ENODEV; ++ } ++ } ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot irqnum %d\n", irq); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Mark the memory region as used */ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), ++ pdev->name); ++ if (!ioarea) { ++ ++ printk(KERN_ERR "%s: SMBus region already claimed\n", __func__); ++ ++ return -EBUSY; ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot ioarea 0x%p\n", ioarea); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* Allocate memory for driver's internal data structure */ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ ++ if (!dev) { ++ ++ printk(KERN_ERR "%s: Couldn't allocate memory for driver's internaldb\n", __func__); ++ ++ rc = -ENOMEM; ++ ++ goto err_release_mem_region; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nGot dev 0x%p\n", dev); ++#endif /* IPROC_SMB_DBG */ ++ ++ dev->dev = &pdev->dev; ++ init_MUTEX(&dev->xfer_lock); ++ init_completion(&dev->ses_done); ++ dev->irq = irq; ++ ++ dev->block_base_addr = ioremap(iomem->start, resource_size(iomem)); ++ ++ if (!dev->block_base_addr) { ++ ++ printk(KERN_ERR "%s: ioremap of register space failed\n", __func__); ++ ++ rc = -ENOMEM; ++ ++ goto err_free_dev_mem; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n ==== Got block_base_addr=0x%08X\n", (unsigned int)dev->block_base_addr); ++ /* iproc_dump_smb_regs(dev); */ ++#endif /* IPROC_SMB_DBG */ ++ ++ dev->enable_evts = ENABLE_INTR; /* Default value, can be changed after ++ initial testing */ ++ ++ platform_set_drvdata(pdev, dev); ++ ++ adap = &dev->adapter; ++ i2c_set_adapdata(adap, dev); /* Verify if this place is OK */ ++ adap->owner = THIS_MODULE; ++ adap->class = UINT_MAX; /* Can be used by any I2C device */ ++ snprintf(adap->name, sizeof(adap->name), "iproc-smb%d", id); ++ adap->algo = &iproc_smb_algorithm; ++ adap->dev.parent = &pdev->dev; /* */ ++ adap->nr = id; ++ adap->dev.of_node = pdev->dev.of_node; ++ ++ /* Init internal regs, disable intrs (and then clear intrs), set fifo ++ * thresholds, etc. ++ */ ++ iproc_smbus_block_init(dev); ++ ++ /* Register ISR handler */ ++ rc = request_irq(dev->irq, iproc_smb_isr, IRQF_SHARED, pdev->name, dev); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: failed to request irq %d, rc=%d\n", __func__, dev->irq, rc); ++ ++ goto err_smb_deinit; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nrequest_irq succeeded\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ /* ++ * I2C device drivers may be active on return from ++ * i2c_add_numbered_adapter() ++ */ ++ rc = i2c_add_numbered_adapter(adap); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: Failed to add I2C adapter, rc=%d\n", ++ __func__, rc); ++ ++ goto err_free_irq; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\ni2c_add_numbered_adapter succeeded\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ of_i2c_register_devices(adap); ++ /* Turn on default set of interrupts */ ++ /* For Rx, enable RX fifo full, threshold hit interrupts. Other rx ++ * interrupts will be set in the read/recv transactions, as required ++ * For Tx, enable fifo under run intr. Other intrs will be set in send ++ * write access functions ++ */ ++ iproc_intr_enable(dev, CCB_SMB_MSTRRXFIFOFULLEN_MASK); ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\niproc_intr_enable complete, intrs enabled\n"); ++#endif /* IPROC_SMB_DBG */ ++ ++ rc = proc_init(pdev); ++ ++ if (rc) { ++ ++ printk(KERN_ERR "%s: Failed to install procfs entry, rc=%d\n", ++ __func__, rc); ++ ++ goto err_proc_term; ++ ++ } ++ ++ dev->next = iproc_smbus_list; ++ iproc_smbus_list = dev; ++ ++#ifdef IPROC_SMB_DBG ++ iproc_dump_smb_regs(dev); ++ ++ printk(KERN_DEBUG "%s: probe successful", __func__); ++ ++#endif /* IPROC_SMB_DBG */ ++ ++ return 0; ++ ++err_proc_term: ++ proc_term(pdev); ++ ++err_free_irq: ++ free_irq(dev->irq, dev); ++ ++err_smb_deinit: ++ iproc_smbus_block_deinit(dev); ++ ++ iounmap(dev->block_base_addr); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++err_free_dev_mem: ++ kfree(dev); ++ ++err_release_mem_region: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ printk(KERN_ERR "%s: probe failed, error=%d", __func__, rc); ++ ++ return (rc); ++} ++ ++static int iproc_smb_remove(struct platform_device *pdev) ++{ ++ struct iproc_smb_drv_int_data *dev = platform_get_drvdata(pdev); ++ struct resource *iomem; ++ unsigned int regval; ++ ++ /* Disable interrupts. */ ++ /* Verify: Should we wait for any in-progress xact to complete? */ ++ iproc_intr_disable(dev, ~0); ++ ++ /* Disable SMbus block */ ++ regval = iproc_smb_reg_read((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG); ++ ++ regval &= ~CCB_SMB_CFG_SMBEN_MASK; ++ ++ iproc_smb_reg_write((unsigned long)dev->block_base_addr + CCB_SMB_CFG_REG, regval); ++ ++ i2c_del_adapter(&dev->adapter); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ free_irq(dev->irq, dev); ++ ++ iproc_smbus_block_deinit(dev); ++ ++ iounmap(dev->block_base_addr); ++ ++ kfree(dev); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ return 0; ++} ++ ++static int iproc_smb_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return (0); ++} ++ ++static int iproc_smb_resume(struct platform_device *pdev) ++{ ++ return (0); ++} ++ ++static struct platform_device_id iproc_smb_id_table[] = { ++ { .name = "iproc-smb", 0 }, ++}; ++MODULE_DEVICE_TABLE(platform, iproc_smb_id_table); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id bcm_iproc_smb_of_match[] = { ++ { .compatible = "iproc-smb" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, bcm_iproc_smb_of_match); ++#endif ++ ++static struct platform_driver iproc_smb_driver = { ++ .driver = { ++ .name = "iproc-smb", ++ .owner = THIS_MODULE, ++ .of_match_table = bcm_iproc_smb_of_match, ++ }, ++ .probe = iproc_smb_probe, ++ .remove = iproc_smb_remove, ++ .suspend = iproc_smb_suspend, ++ .resume = iproc_smb_resume, ++ .id_table = iproc_smb_id_table, ++}; ++ ++ ++static int __init iproc_smb_init(void) ++{ ++ int rc; ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "%s: Entering init", __func__); ++#endif /* IPROC_SMB_DBG */ ++ ++ gProcParent = proc_mkdir(PROC_GLOBAL_PARENT_DIR, NULL); ++ ++ if (gProcParent == NULL) { ++ ++ printk(KERN_ERR "%s: SMBus driver procfs failed\n", __func__); ++ ++ return -ENOMEM; ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\nproc_mkdir succeeded, gProcParent=0x%08X\n", (unsigned int)gProcParent); ++#endif /* IPROC_SMB_DBG */ ++ ++ rc = platform_driver_register(&iproc_smb_driver); ++ ++ if (rc < 0) { ++ ++ printk(KERN_ERR "%s: SMBus driver init failed, error %d\n", __func__, rc); ++ ++ } ++ ++#ifdef IPROC_SMB_DBG ++ printk(KERN_DEBUG "\n%s: Called platform_driver_register, rc=%d\n", __func__, rc); ++#endif /* IPROC_SMB_DBG */ ++ ++ ++ iproc_smbus_list = NULL; ++ ++ /* Should we set RESET bit (reg 0x0) here?: Not necessary as per hw engg */ ++ ++ return rc; ++} ++ ++static void __exit iproc_smb_exit(void) ++{ ++ platform_driver_unregister(&iproc_smb_driver); ++ ++ remove_proc_entry(PROC_GLOBAL_PARENT_DIR, NULL); ++} ++ ++module_init(iproc_smb_init); ++module_exit(iproc_smb_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("IPROC I2C (SMBus) Bus Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus.h b/drivers/bcmdrivers/smbus/iproc_smbus.h +new file mode 100644 +index 0000000..d2c4973 +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus.h +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_H__ ++#define __IPROC_SMBUS_H__ ++ ++#define IPROC_I2C_INVALID_ADDR 0xFF ++ ++#define MAX_PROC_BUF_SIZE 256 ++#define MAX_PROC_NAME_SIZE 15 ++#define PROC_GLOBAL_PARENT_DIR "iproc-i2c" ++#define PROC_ENTRY_DEBUG "iproc-i2c-dbg" ++ ++#define IPROC_SMB_MAX_RETRIES 35 ++ ++#define GETREGFLDVAL(regval, mask, startbit) (((regval) & (mask)) >> (startbit)) ++ ++#define SETREGFLDVAL(regval, fldval, mask, startbit) regval = \ ++ (regval & ~(mask)) | \ ++ ((fldval) << (startbit)) ++ ++/* Enum to specify clock speed. The user will provide it during initialization. ++ * If needed, it can be changed dynamically ++ */ ++typedef enum iproc_smb_clk_freq { ++ I2C_SPEED_100KHz = 0, ++ I2C_SPEED_400KHz = 1, ++ I2C_SPEED_INVALID = 255 ++} smb_clk_freq_t; ++ ++/* This enum will be used to notify the user of status of a data transfer ++ * request ++ */ ++typedef enum iproc_smb_error_code { ++ I2C_NO_ERR = 0, ++ I2C_TIMEOUT_ERR = 1, ++ I2C_INVALID_PARAM_ERR = 2, /* Invalid parameter(s) passed to the driver */ ++ I2C_OPER_IN_PROGRESS = 3, /* The driver API was called before the present ++ transfer was completed */ ++ I2C_OPER_ABORT_ERR = 4, /* Transfer aborted unexpectedly, for example a NACK ++ received, before last byte was read/written */ ++ I2C_FUNC_NOT_SUPPORTED = 5, /* Feature or function not supported ++ (e.g., 10-bit addresses, or clock speeds ++ other than 100KHz, 400KHz) */ ++} iproc_smb_error_code_t; ++ ++/* Counters will be used mainly for testing and debugging */ ++struct iproc_smb_counters { ++ unsigned int num_read_requests; ++ unsigned int num_write_requests; ++ unsigned int num_read_errors; ++ unsigned int num_write_errors; ++ unsigned int mstr_rx_evt_cnt; /* ISR counter to check recv event */ ++ unsigned int mstr_start_busy_cnt; /* ISR counter to checking xact sts */ ++ unsigned int mstr_rx_fifo_full_cnt; /* ISR counter to detect rx fifo full */ ++ unsigned int last_int_sts; /* last value of intr status reg */ ++}; ++ ++ ++/* This enum may be used in a call back function to provide the user of the ++ * type of request sent by the user. It can also be used for testing and ++ * debugging purposes ++ */ ++typedef enum iproc_smb_message_type { ++ I2C_DISABLE_MSG = 0, /* To be used after hardware initialization. ++ Driver will _not_ respond to API calls */ ++ I2C_ENABLE_MSG = 1, /* Used after hardware initialization, if required. ++ Driver will start responding to API calls. ++ Will not (re-)program the hardware. */ ++ I2C_READ_MSG = 2, /* I2C read request from application */ ++ I2C_WRITE_MSG = 3 /* I2C write request from application */ ++} iproc_smb_message_type_t; ++ ++/* For debugging purposes, we will store the information about the last ++ * (latest) transfer request from the client application ++ */ ++struct iproc_smb_dbg_trans_info ++{ ++ iproc_smb_message_type_t i2c_last_mesg_type; ++ unsigned int i2c_last_dev_addr; ++ unsigned int i2c_last_num_bytes_xfer_req; ++}; ++ ++struct procfs { ++ char name[MAX_PROC_NAME_SIZE]; ++ struct proc_dir_entry *parent; ++}; ++ ++/* This structure will be used internally by the driver to maintain its ++ * configuration information as well as information programmed in to the ++ * hardware ++ */ ++struct iproc_smb_drv_int_data { ++ struct device *dev; ++ struct iproc_smb_drv_int_data *next; ++ ++ int irq; ++ ++ unsigned int drv_state_init; /* 1 = Initialized, 0 = not initialized */ ++ ++ unsigned int drv_state_open; /* 1 = Accepting transaction requests, ++ 0 = Not accepting transaction requests */ ++ smb_clk_freq_t clk_speed; ++ ++ void __iomem *block_base_addr; /* iomapped virtual base address for ++ register access */ ++ ++ struct i2c_adapter adapter; ++ ++ unsigned int i2c_slave_addr; /* Up to four 7-bit SMB slave addresses can be ++ assigned, we will assume only one for now. ++ Valid only if SMBus will act as a slave ++ device */ ++ ++ struct semaphore xfer_lock; /* Lock for data transfer */ ++ ++ struct completion ses_done; /* To signal the command completion */ ++ ++ struct procfs proc; ++ ++ volatile int debug; ++ ++ unsigned int master_rx_fifo_thr; /* Master FIFO threshold. Interrupt will be ++ generated if the threshold is exceeded */ ++ ++ unsigned int slave_rx_fifo_thr; /* Slave FIFO threshold. Interrupt will be ++ generated if the threshold is exceeded */ ++ ++ unsigned int enable_evts; /* If true, enable interrupts. If false, ++ disable interrupts. Default is false */ ++ unsigned int evt_enable_bmap; /* Bit map of events enabled by the driver */ ++ ++ struct iproc_smb_counters smb_counters; /* Statistics maintained by driver. A caller ++ can request them through an API */ ++}; ++ ++/* Data to be supplied by the platform to initialise the IPROC SMBus (I2C). ++ * block ++ * init: Function called during driver initialization. Used by platform to ++ * configure GPIO functions and similar. ++ */ ++struct iproc_smb_platform_data { ++ int (*init)(struct iproc_smb_drv_int_data *iproc_i2c_info_ptr, int flags); ++ ++ unsigned int flags; ++}; ++ ++/* This structure will be used by the user during driver initialization to pass ++ * initial configuration information to the driver ++ */ ++struct iproc_smb_init_params { ++ unsigned int intr_mode; /* TRUE (1) for enabling interrupt mode, ++ FALSE (0) for polling mode */ ++ unsigned int clock_freq; /* 0=100KHz, 1=400KHz */ ++ void (*i2c_callback_func)(unsigned char *data); /* Application can ++ register a callback ++ function for driver to ++ notify the application ++ of any asynchronous ++ event(s), or exception. ++ Can be NULL */ ++}; ++ ++/* Structure used to pass information to read/write functions. */ ++struct iproc_xact_info { ++ bool cmd_valid; /* true if command field below is valid. Otherwise, false */ ++ unsigned short command; /* Passed by caller to send SMBus command code */ ++ unsigned char *data; /* actual data pased by the caller */ ++ unsigned int size; /* Size of data buffer passed */ ++ unsigned short flags; /* Sent by caller specifying PEC, 10-bit addresses */ ++ unsigned char smb_proto; /* SMBus protocol to use to perform transaction */ ++}; ++ ++#define XACT_TIMEOUT (msecs_to_jiffies(100)) /* Verify if 100 is OK */ ++ ++#endif /* __IPROC_SMBUS_H__ */ +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus_defs.h b/drivers/bcmdrivers/smbus/iproc_smbus_defs.h +new file mode 100644 +index 0000000..856418a +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus_defs.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_DEFS_H__ ++#define __IPROC_SMBUS_DEFS_H__ ++ ++/* Transaction error codes defined in Master command register (0x30) */ ++#define MSTR_STS_XACT_SUCCESS 0 ++#define MSTR_STS_LOST_ARB 1 ++#define MSTR_STS_NACK_FIRST_BYTE 2 ++#define MSTR_STS_NACK_NON_FIRST_BYTE 3 /* NACK on a byte other than ++ the first byte */ ++#define MSTR_STS_TTIMEOUT_EXCEEDED 4 ++#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5 ++#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6 ++ ++/* SMBUS protocol values defined in register 0x30 */ ++#define SMBUS_PROT_QUICK_CMD 0 ++#define SMBUS_PROT_SEND_BYTE 1 ++#define SMBUS_PROT_RECV_BYTE 2 ++#define SMBUS_PROT_WR_BYTE 3 ++#define SMBUS_PROT_RD_BYTE 4 ++#define SMBUS_PROT_WR_WORD 5 ++#define SMBUS_PROT_RD_WORD 6 ++#define SMBUS_PROT_BLK_WR 7 ++#define SMBUS_PROT_BLK_RD 8 ++#define SMBUS_PROT_PROC_CALL 9 ++#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10 ++ ++#define BUS_BUSY_COUNT 100000 /* Number can be changed later */ ++ ++#define DISABLE_INTR 0 ++#define ENABLE_INTR 1 ++#endif /* __IPROC_SMBUS_DEFS_H__ */ +diff --git a/drivers/bcmdrivers/smbus/iproc_smbus_regs.h b/drivers/bcmdrivers/smbus/iproc_smbus_regs.h +new file mode 100644 +index 0000000..197be7d +--- /dev/null ++++ b/drivers/bcmdrivers/smbus/iproc_smbus_regs.h +@@ -0,0 +1,290 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __IPROC_SMBUS_REGS_H__ ++#define __IPROC_SMBUS_REGS_H__ ++ ++/* --- */ ++#define CCB_SMB_CFG_REG 0x0 ++ ++#define CCB_SMB_CFG_RST_MASK 0x80000000 ++#define CCB_SMB_CFG_RST_SHIFT 31 ++ ++#define CCB_SMB_CFG_SMBEN_MASK 0x40000000 ++#define CCB_SMB_CFG_SMBEN_SHIFT 30 ++ ++#define CCB_SMB_CFG_BITBANGEN_MASK 0x20000000 ++#define CCB_SMB_CFG_BITBANGEN_SHIFT 29 ++ ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000 ++#define CCB_SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28 ++ ++#define CCB_SMB_CFG_PROMISCMODE_MASK 0x08000000 ++#define CCB_SMB_CFG_PROMISCMODE_SHIFT 27 ++ ++#define CCB_SMB_CFG_TSTMPCNTEN_MASK 0x04000000 ++#define CCB_SMB_CFG_TSTMPCNTEN_SHIFT 26 ++ ++#define CCB_SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000 ++#define CCB_SMB_CFG_MSTRRTRYCNT_SHIFT 16 ++ ++ ++/* --- */ ++#define CCB_SMB_TIMGCFG_REG 0x4 ++ ++#define CCB_SMB_TIMGCFG_MODE400_MASK 0x80000000 ++#define CCB_SMB_TIMGCFG_MODE400_SHIFT 31 ++ ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000 ++#define CCB_SMB_TIMGCFG_RNDSLVSTR_SHIFT 24 ++ ++#define CCB_SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000 ++#define CCB_SMB_TIMGCFG_PERSLVSTR_SHIFT 16 ++ ++#define CCB_SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00 ++#define CCB_SMB_TIMGCFG_IDLTIME_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_ADDR_REG 0x8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR3_MASK 0x80000000 ++#define CCB_SMB_EN_NIC_SMBADDR3_SHIFT 31 ++ ++#define CCB_SMB_NIC_SMBADDR3_MASK 0x7F000000 ++#define CCB_SMB_NIC_SMBADDR3_SHIFT 24 ++ ++#define CCB_SMB_EN_NIC_SMBADDR2_MASK 0x00800000 ++#define CCB_SMB_EN_NIC_SMBADDR2_SHIFT 23 ++ ++#define CCB_SMB_NIC_SMBADDR2_MASK 0x007F0000 ++#define CCB_SMB_NIC_SMBADDR2_SHIFT 16 ++ ++#define CCB_SMB_EN_NIC_SMBADDR1_MASK 0x00008000 ++#define CCB_SMB_EN_NIC_SMBADDR1_SHIFT 15 ++ ++#define CCB_SMB_NIC_SMBADDR1_MASK 0x00007F00 ++#define CCB_SMB_NIC_SMBADDR1_SHIFT 8 ++ ++#define CCB_SMB_EN_NIC_SMBADDR0_MASK 0x00000080 ++#define CCB_SMB_EN_NIC_SMBADDR0_SHIFT 7 ++ ++#define CCB_SMB_NIC_SMBADDR0_MASK 0x0000007F ++#define CCB_SMB_NIC_SMBADDR0_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_MSTRFIFOCTL_REG 0xC ++ ++#define CCB_SMB_MSTRRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_MSTRTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_MSTRTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_MSTRRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_MSTRRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_MSTRRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_SLVFIFOCTL_REG 0x10 ++ ++#define CCB_SMB_SLVRXFIFOFLSH_MASK 0x80000000 ++#define CCB_SMB_SLVRXFIFOFLSH_SHIFT 31 ++ ++#define CCB_SMB_SLVTXFIFOFLSH_MASK 0x40000000 ++#define CCB_SMB_SLVTXFIFOFLSH_SHIFT 30 ++ ++#define CCB_SMB_SLVRXPKTCNT_MASK 0x007F0000 ++#define CCB_SMB_SLVRXPKTCNT_SHIFT 16 ++ ++#define CCB_SMB_SLVRXFIFOTHR_MASK 0x00003F00 ++#define CCB_SMB_SLVRXFIFOTHR_SHIFT 8 ++ ++/* --- */ ++#define CCB_SMB_BITBANGCTL_REG 0x14 ++ ++#define CCB_SMB_SMBCLKIN_MASK 0x80000000 ++#define CCB_SMB_SMBCLKIN_SHIFT 31 ++ ++#define CCB_SMB_SMBCLKOUTEN_MASK 0x40000000 ++#define CCB_SMB_SMBCLKOUTEN_SHIFT 30 ++ ++#define CCB_SMB_SMBDATAIN_MASK 0x20000000 ++#define CCB_SMB_SMBDATAIN_SHIFT 29 ++ ++#define CCB_SMB_SMBDATAOUTEN_MASK 0x10000000 ++#define CCB_SMB_SMBDATAOUTEN_SHIFT 28 ++ ++/* --- */ ++#define CCB_SMB_MSTRCMD_REG 0x30 ++ ++#define CCB_SMB_MSTRSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_MSTRSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_MSTRABORT_MASK 0x40000000 ++#define CCB_SMB_MSTRABORT_SHIFT 30 ++ ++#define CCB_SMB_MSTRSTS_MASK 0x0E000000 ++#define CCB_SMB_MSTRSTS_SHIFT 25 ++ ++#define CCB_SMB_MSTRSMBUSPROTO_MASK 0x00001E00 ++#define CCB_SMB_MSTRSMBUSPROTO_SHIFT 9 ++ ++#define CCB_SMB_MSTRPEC_MASK 0x00000100 ++#define CCB_SMB_MSTRPEC_SHIFT 8 ++ ++#define CCB_SMB_MSTRRDBYTECNT_MASK 0x000000FF ++#define CCB_SMB_MSTRRDBYTECNT_SHIFT 0 ++ ++/* --- */ ++#define CCB_SMB_SLVCMD_REG 0x34 ++ ++#define CCB_SMB_SLVSTARTBUSYCMD_MASK 0x80000000 ++#define CCB_SMB_SLVSTARTBUSYCMD_SHIFT 31 ++ ++#define CCB_SMB_SLVABORT_MASK 0x40000000 ++#define CCB_SMB_SLVABORT_SHIFT 30 ++ ++#define CCB_SMB_SLVSTS_MASK 0x03800000 ++#define CCB_SMB_SLVSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVPEC_MASK 0x00000100 ++#define CCB_SMB_SLVPEC_SHIFT 8 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTEN_REG 0x38 ++ ++#define CCB_SMB_MSTRRXFIFOFULLEN_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLEN_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITEN_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTEN_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTEN_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYEN_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYEN_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDEN_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDEN_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLEN_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLEN_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITEN_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTEN_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTEN_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYEN_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYEN_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDEN_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDEN_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTEN_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTEN_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_EVTSTS_REG 0x3C ++ ++#define CCB_SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRRXFIFOFULLSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000 ++#define CCB_SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRXEVTSTS_MASK 0x20000000 ++#define CCB_SMB_MSTRRXEVTSTS_SHIFT 29 ++ ++#define CCB_SMB_MSTRSTARTBUSYSTS_MASK 0x10000000 ++#define CCB_SMB_MSTRSTARTBUSYSTS_SHIFT 28 ++ ++#define CCB_SMB_MSTRTXUNDSTS_MASK 0x08000000 ++#define CCB_SMB_MSTRTXUNDSTS_SHIFT 27 ++ ++ ++#define CCB_SMB_SLVRXFIFOFULLSTS_MASK 0x04000000 ++#define CCB_SMB_SLVRXFIFOFULLSTS_SHIFT 26 ++ ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000 ++#define CCB_SMB_SLVRXFIFOTHRHITSTS_SHIFT 25 ++ ++#define CCB_SMB_SLVRXEVTSTS_MASK 0x01000000 ++#define CCB_SMB_SLVRXEVTSTS_SHIFT 24 ++ ++#define CCB_SMB_SLVSTARTBUSYSTS_MASK 0x00800000 ++#define CCB_SMB_SLVSTARTBUSYSTS_SHIFT 23 ++ ++#define CCB_SMB_SLVTXUNDSTS_MASK 0x00400000 ++#define CCB_SMB_SLVTXUNDSTS_SHIFT 22 ++ ++#define CCB_SMB_SLVRDEVTSTS_MASK 0x00200000 ++#define CCB_SMB_SLVRDEVTSTS_SHIFT 21 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATAWR_REG 0x40 ++ ++#define CCB_SMB_MSTRWRSTS_MASK 0x80000000 ++#define CCB_SMB_MSTRWRSTS_SHIFT 31 ++ ++#define CCB_SMB_MSTRWRDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_MSTRDATARD_REG 0x44 ++ ++#define CCB_SMB_MSTRRDSTS_MASK 0xC0000000 ++#define CCB_SMB_MSTRRDSTS_SHIFT 30 ++ ++#define CCB_SMB_MSTRRDPECERR_MASK 0x20000000 ++#define CCB_SMB_MSTRRDPECERR_SHIFT 29 ++ ++#define CCB_SMB_MSTRRDDATA_MASK 0x000000FF ++#define CCB_SMB_MSTRRDDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATAWR_REG 0x48 ++ ++#define CCB_SMB_SLVWRSTS_MASK 0x80000000 ++#define CCB_SMB_SLVWRSTS_SHIFT 31 ++ ++#define CCB_SMB_SLVWRDATA_MASK 0x000000FF ++#define CCB_SMB_SLVWRDATA_SHIFT 0 ++ ++ ++/* --- */ ++#define CCB_SMB_SLVDATARD_REG 0x4C ++ ++#define CCB_SMB_SLVRDSTS_MASK 0xC0000000 ++#define CCB_SMB_SLVRDSTS_SHIFT 30 ++ ++#define CCB_SMB_SLVRDERRSTS_MASK 0x30000000 ++#define CCB_SMB_SLVRDERRSTS_SHIFT 28 ++ ++#define CCB_SMB_SLVRDDATA_MASK 0x000000FF ++#define CCB_SMB_SLVRDDATA_SHIFT 0 ++ ++#endif /* __IPROC_SMBUS_REGS_H__ */ +diff --git a/drivers/bcmdrivers/timer/.gitignore b/drivers/bcmdrivers/timer/.gitignore +new file mode 100644 +index 0000000..d741861 +--- /dev/null ++++ b/drivers/bcmdrivers/timer/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/timer/Kconfig b/drivers/bcmdrivers/timer/Kconfig +new file mode 100644 +index 0000000..9dc584f +--- /dev/null ++++ b/drivers/bcmdrivers/timer/Kconfig +@@ -0,0 +1,6 @@ ++config IPROC_CCB_TIMER ++ tristate "ChipcommonB Timer support" ++ depends on ARCH_IPROC ++ help ++ This selects a driver for the ChipcommonB SP804 Timer on Broadcom ++ iProc chips. +diff --git a/drivers/bcmdrivers/timer/Makefile b/drivers/bcmdrivers/timer/Makefile +new file mode 100644 +index 0000000..630ff37 +--- /dev/null ++++ b/drivers/bcmdrivers/timer/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_IPROC_CCB_TIMER) += iproc_timer.o +diff --git a/drivers/bcmdrivers/timer/iproc_timer.c b/drivers/bcmdrivers/timer/iproc_timer.c +new file mode 100644 +index 0000000..b9d11fc +--- /dev/null ++++ b/drivers/bcmdrivers/timer/iproc_timer.c +@@ -0,0 +1,479 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iproc_timer.h" ++ ++/* ++ * Configurations ++ */ ++#define DRV_NAME "iproc_ccb_timer" ++#define REFCLK_SOURCE "c_clk125" ++#define REFCLK_SOURCE_DEVID "iproc_slow" ++#define MAX_NUMBER_OF_TIMERS (4) ++ ++/* ++ * Register offset ++ */ ++#define TIMER_LOAD_OFFSET 0x00 ++#define TIMER_VALUE_OFFSET 0x04 ++#define TIMER_CONTROL_OFFSET 0x08 ++#define TIMER_INTCLR_OFFSET 0x0c ++#define TIMER_RIS_OFFSET 0x10 ++#define TIMER_MIS_OFFSET 0x14 ++ ++/* ++ * Timer Control Register Bits ++ */ ++#define TIMER_CTRL_16BIT (0 << 1) /* 16-bit counter mode */ ++#define TIMER_CTRL_32BIT (1 << 1) /* 32-bit counter mode */ ++#define TIMER_CTRL_IE (1 << 5) /* Interrupt enable */ ++#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic mode */ ++#define TIMER_CTRL_EN (1 << 7) /* Timer enable */ ++#define TIMER_CTRL_ONESHOTMODE (1 << 0) ++#define TIMER_CTRL_DIV1 (0 << 2) ++#define TIMER_CTRL_PREBY16 (1 << 2) ++#define TIMER_CTRL_PREBY256 (2 << 2) ++ ++/* In case we use physical addresses */ ++#define IO_ADDRESS(x) (x) ++ ++/* Timer instance */ ++typedef struct { ++ int32_t id; /* id for this timer */ ++ uint32_t base; /* timer base address */ ++ uint32_t vec; /* interrupt vector */ ++ int started; /* Whether it has started */ ++ uint64_t interval; /* Interval in ticks; 0 if not inited */ ++ int periodic; /* 1 for periodic; 0 for one-shot */ ++ uint32_t load; /* Actual value to load */ ++ iproc_timer_isr_t isr; /* User interrupt handler */ ++ void * cookie; /* Cookie for user isr */ ++ uint32_t prescale; /* Prescale bits */ ++} timer_map_t; ++ ++/* Actual number of timers */ ++static int timer_count; ++ ++/* Mapping from logical timer to physical timer */ ++static timer_map_t timers_map[MAX_NUMBER_OF_TIMERS]; ++ ++/* Reference clock */ ++static uint32_t timer_refclk; ++ ++/* ++ * Disable timer ++ */ ++static inline void ++hw_timer_disable(timer_map_t *ptimer) ++{ ++ register uint32_t timer_base; ++ ++ timer_base = ptimer->base; ++ writel( ++ readl(IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET)) & ~TIMER_CTRL_EN, ++ IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET) ++ ); ++ ++ /* Clear pending interrupt */ ++ writel(1, IO_ADDRESS(timer_base + TIMER_INTCLR_OFFSET)); ++} ++ ++/* ++ * Configure timer ++ */ ++int ++iproc_timer_configure(int timer_id, int periodic, uint64_t interval, ++ iproc_timer_isr_t isr, void *cookie) ++{ ++ timer_map_t *ptimer; ++ uint32_t ctrl = TIMER_CTRL_32BIT; ++ ++ if (timer_id < 0 || timer_id >= timer_count || ++ interval == 0 || interval > iproc_timer_get_max_interval()) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ /* Cannot configure while it's started */ ++ if (ptimer->started) { ++ return -EBUSY; ++ } ++ ++ /* Check how much we need to prescale */ ++ if ((interval >> 32) == 0) { ++ ptimer->prescale = 0; ++ ctrl |= TIMER_CTRL_DIV1; ++ } else { ++ if ((interval >> 36) == 0) { ++ ptimer->prescale = 4; ++ ctrl |= TIMER_CTRL_PREBY16; ++ } else { ++ ptimer->prescale = 8; ++ ctrl |= TIMER_CTRL_PREBY256; ++ } ++ } ++ ++ /* Actual value to load */ ++ ptimer->load = (uint32_t)(interval >> ptimer->prescale); ++ ++ /* Configure periodic/one-shot mode */ ++ ptimer->periodic = periodic; ++ if (periodic) { ++ ++ /* ++ * For periodic mode, don't enable interrupt if user isr is not set ++ * This is to avoid frequent IRQs and degrade system performance. ++ */ ++ if (isr) { ++ ctrl |= TIMER_CTRL_IE; ++ } ++ ctrl |= TIMER_CTRL_PERIODIC; ++ ++ } else { ++ /* For one-shot mode, interrupt must be enabled (to mark it stopped) */ ++ ctrl |= TIMER_CTRL_ONESHOTMODE | TIMER_CTRL_IE; ++ } ++ ++ /* Write to control register */ ++ writel(ctrl, IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET)); ++ ++ /* Record user specified arguments */ ++ ptimer->interval = interval; ++ ptimer->isr = isr; ++ ptimer->cookie = cookie; ++ ++ return 0; ++} ++ ++/* ++ * Start timer ++ */ ++int ++iproc_timer_start(int timer_id) ++{ ++ timer_map_t *ptimer; ++ register uint32_t timer_base; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ if (ptimer->interval == 0) { ++ return -EPERM; ++ } ++ ++ if (ptimer->started) { ++ return -EBUSY; ++ } ++ ++ ptimer->started = 1; ++ timer_base = ptimer->base; ++ writel(ptimer->load, IO_ADDRESS(timer_base + TIMER_LOAD_OFFSET)); ++ writel( ++ readl(IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET)) | TIMER_CTRL_EN, ++ IO_ADDRESS(timer_base + TIMER_CONTROL_OFFSET) ++ ); ++ ++ return 0; ++} ++ ++/* ++ * Stop timer ++ */ ++int ++iproc_timer_stop(int timer_id) ++{ ++ timer_map_t *ptimer; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ ++ if (ptimer->started == 0) { ++ return 0; ++ } ++ ++ ptimer->started = 0; ++ hw_timer_disable(ptimer); ++ ++ return 0; ++} ++ ++/* ++ * Returns timer's counter ++ */ ++uint64_t ++iproc_timer_get_current_ticks(int timer_id) ++{ ++ timer_map_t *ptimer; ++ uint64_t ticks; ++ ++ if (timer_id < 0 || timer_id >= timer_count) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ if (!ptimer->interval || !ptimer->started) { ++ return 0; ++ } ++ ++ /* To return the elapsed ticks, not remaining ticks */ ++ ticks = ++ ptimer->load - readl(IO_ADDRESS(ptimer->base + TIMER_VALUE_OFFSET)); ++ ++ /* Scale back */ ++ return ticks << ptimer->prescale; ++} ++ ++/* ++ * Timer info ++ */ ++int ++iproc_timer_get_info(int timer_id, iproc_timer_info_t *info) ++{ ++ timer_map_t *ptimer; ++ ++ if (timer_id < 0 || timer_id >= timer_count || info == NULL) { ++ return -EINVAL; ++ } ++ ptimer = &timers_map[timer_id]; ++ info->configured = ptimer->interval? 1 : 0; ++ info->started = ptimer->started; ++ info->periodic = ptimer->periodic; ++ info->interval = ptimer->interval; ++ info->isr = ptimer->isr; ++ info->cookie = ptimer->cookie; ++ ++ return 0; ++} ++ ++/* ++ * Ticking rate (reference clock frequency): ticks per second ++ */ ++uint32_t ++iproc_timer_get_ticking_rate(void) ++{ ++ return timer_refclk; ++} ++ ++/* ++ * Get max interval in ticks ++ */ ++uint64_t ++iproc_timer_get_max_interval(void) ++{ ++ return (uint64_t)0xFFFFFFFFULL << 8; ++} ++ ++/* ++ * Get number of timers ++ */ ++uint32_t ++iproc_timer_count(void) ++{ ++ return timer_count; ++} ++ ++/* ++ * IRQ handler for the timer ++ */ ++static irqreturn_t ++hw_timer_interrupt(int irq, void *dev_id) ++{ ++ timer_map_t *ptimer = (timer_map_t *)dev_id; ++ ++ /* Check if it's for us */ ++ if (!(readl(IO_ADDRESS(ptimer->base + TIMER_MIS_OFFSET)) & 1)) { ++ return IRQ_NONE; ++ } ++ ++ /* clear the interrupt */ ++ writel(1, IO_ADDRESS(ptimer->base + TIMER_INTCLR_OFFSET)); ++ ++ /* Double confirm if it's enabled by user */ ++ if (ptimer->interval && ptimer->started) { ++ ++ /* If it's one-shot, mark it 'stopped' first */ ++ if (ptimer->periodic == 0) { ++ ptimer->started = 0; ++ ++ /* It doesn't clear the EN bit automatically */ ++ writel( ++ readl( ++ IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET)) & ++ ~TIMER_CTRL_EN, ++ IO_ADDRESS(ptimer->base + TIMER_CONTROL_OFFSET) ++ ); ++ } ++ ++ /* Call user specified ISR */ ++ if (ptimer->isr) { ++ (*ptimer->isr)(ptimer->id, ptimer->cookie); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/*********************************************************************** ++ * Platform driver setup ++ ***********************************************************************/ ++ ++static int __devinit ++iproc_timer_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int i; ++ int ret = 0; ++ struct clk *clk; ++ ++ /* Retrieve reference clock frequency */ ++ clk = clk_get_sys(REFCLK_SOURCE_DEVID, REFCLK_SOURCE); ++ if (!clk) { ++ dev_err(&pdev->dev, "can't get reference clock frequency by %s\n", ++ REFCLK_SOURCE); ++ ret = -EIO; ++ goto err2; ++ } ++ timer_refclk = (uint32_t)clk_get_rate(clk); ++ ++ /* Retrieve IRQ from resources (also determine number of timers) */ ++ timer_count = 0; ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no IRQ defined\n"); ++ ret = -ENODEV; ++ goto err2; ++ } ++ for(i = (int)res->start; i <= (int)res->end; i++) { ++ timers_map[timer_count].vec = i; ++ timer_count++; ++ } ++ ++ /* Retrieve register space (in virtual addresses) from resources */ ++ for(i=0; idev, "can't get resource for register space\n"); ++ ret = -EIO; ++ goto err2; ++ } ++ timers_map[i].base = (uint32_t)res->start; ++ } ++ ++ /* Perform basic initialization */ ++ for(i=0; idev, "unable to allocate IRQ\n"); ++ goto err1; ++ } ++ } ++ ++ printk(KERN_INFO "iProc Timer driver: %u timers running at %uHz\n", ++ timer_count, timer_refclk); ++ ++ return 0; ++ ++err1: ++ for(i=0; i ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "usbh_cfg.h" ++ ++#include "bcm_usbh.h" ++ ++#define DEBUG ++#ifdef DEBUG ++#define dbg_printk(fmt, args...) printk(KERN_INFO "%s: " fmt, __func__, ## args) ++#else ++#define dbg_printk(fmt, args...) ++#endif ++ ++#define IPROC_USB2_CLK_CONTROL_ENABLE (0x1800C180) ++#define IPROC_USB2_CLK_CONTROL_ENABLE_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2_CLK_CONTROL_ENABLE) ++#define IPROC_USB2_CLK_CONTROL_PLL (0x1800C164) ++#define IPROC_USB2_CLK_CONTROL_PLL_VA HW_IO_PHYS_TO_VIRT(IPROC_USB2_CLK_CONTROL_PLL) ++#define IPROC_STRAP_SKU_VECTOR (0x1810D500) ++#define IPROC_STRAP_SKU_VECTOR_VA HW_IO_PHYS_TO_VIRT(IPROC_STRAP_SKU_VECTOR) ++#define IPROC_IDM_USB2_RESET_CONTROL (0x18115800) ++#define IPROC_IDM_USB2_RESET_CONTROL_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_USB2_RESET_CONTROL) ++ ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_NSP) || \ ++ defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++#define IPROC_IDM_USB2_IO_CONTROL_DIRECT USB2_IDM_IDM_IO_CONTROL_DIRECT ++#define IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA HW_IO_PHYS_TO_VIRT(IPROC_IDM_USB2_IO_CONTROL_DIRECT) ++#endif ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++#define IPROC_XGPLL 0x1803fc2c ++#define IPROC_XGPLL_VA HW_IO_PHYS_TO_VIRT(IPROC_XGPLL) ++#define IPROC_USB_PHY_CTRL IPROC_WRAP_USBPHY_CTRL ++#define IPROC_USB_PHY_CTRL_VA HW_IO_PHYS_TO_VIRT(IPROC_USB_PHY_CTRL) ++#define IPROC_WRAP_MISC_STATUS 0x1803fc28 ++#define IPROC_WRAP_MISC_STATUS_VA HW_IO_PHYS_TO_VIRT(IPROC_WRAP_MISC_STATUS) ++#define IPROC_CLK_NDIV_40 0x80 ++#define IPROC_CLK_NDIV_20 0x8C ++#define USB_CLK_NDIV_MASK 0xFE7FFE00 ++#define USB_CLK_PLL_RESET_MASK 0xFF7FFE00 ++#define USB_CLK_PHY_RESET_MASK 0xFFFFFE00 ++#define USB_CLK_NDIV_40 0x30 ++#define USB_CLK_NDIV_20 0x60 ++#define ChipcommonA_GPIOIn_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOInput) ++#define ChipcommonA_GPIOOut_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOOut) ++#define ChipcommonA_GPIOOutEn_VA HW_IO_PHYS_TO_VIRT(ChipcommonA_GPIOOutEn) ++#define SUPPLY_USBD_POWER 0xfffffffd ++#endif ++ ++#define IPROC_SKU_STRAP_MASK 0xC ++ ++struct usbh_ctrl_regs { ++ u32 mode; ++#define MODE_ULPI_TTL (1<<0) ++#define MODE_ULPI_PHY (1<<1) ++#define MODE_UTMI_TTL (1<<2) ++#define MODE_UTMI_PHY (1<<3) ++#define MODE_PORT_CFG(port, mode) ((mode) << (4 * port)) ++ ++ u32 strap_q; ++#define STRAP_PWR_STATE_VALID (1 << 7) /* ss_power_state_valid */ ++#define STRAP_SIM_MODE (1 << 6) /* ss_simulation_mode */ ++#define STRAP_OHCI_CNTSEL_SIM (1 << 5) /* ohci_0_cntsel_i_n */ ++#define STRAP_PWR_STATE_NXT_VALID (1 << 4) /* ss_nxt_power_state_valid_i */ ++#define STRAP_PWR_STATE_NXT_SHIFT 2 /* ss_next_power_state_i */ ++#define STRAP_PWR_STATE_NXT_MASK (3 << STRAP_PWR_STATE_NXT_SHIFT) ++#define STRAP_PWR_STATE_SHIFT 0 /* ss_power_state_i */ ++#define STRAP_PWR_STATE_MASK (3 << STRAP_PWR_STATE_SHIFT) ++ ++ u32 framelen_adj_q; ++ u32 framelen_adj_qx[USBH_NUM_PORTS]; ++ u32 misc; ++#define MISC_RESUME_R23_ENABLE (1 << 4) /* ss_utmi_backward_enb_i */ ++#define MISC_RESUME_R23_UTMI_PLUS_DISABLE (1 << 3) /* ss_resume_utmi_pls_dis_i */ ++#define MISC_ULPI_BYPASS_ENABLE (1 << 2) /* ulpi_bypass_en_i */ ++#define MISC_PORT_PWRDWN_OVERCURRENT (1 << 1) /* ss_autoppd_on_overcur_en_i */ ++#define MISC_OHCI_CLK_RESTART (1 << 0) /* app_start_clk_i */ ++ ++}; ++ ++struct usbh_priv { ++ atomic_t probe_done; ++ volatile int init_cnt; ++ struct mutex lock; ++ struct device *dev; ++ struct usbh_cfg hw_cfg; ++ struct clk *peri_clk; ++ struct clk *ahb_clk; ++ struct clk *opt_clk; ++ struct usbh_ctrl_regs __iomem *ctrl_regs; ++}; ++ ++static struct usbh_priv usbh_data; ++ ++int bcm_usbh_suspend(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_suspend); ++ ++int bcm_usbh_resume(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_resume); ++ ++/* ++ * Function to initialize USB host related low level hardware including PHY, ++ * clocks, etc. ++ * ++ * TODO: expand support for more than one host in the future if needed ++ */ ++int bcm_usbh_init(unsigned int host_index) ++{ ++#ifdef CONFIG_MACH_NS ++ int usb2_clk_cntrl, usb2_clk_enable, sku_vect; ++ ++ sku_vect = readl_relaxed(IPROC_STRAP_SKU_VECTOR_VA); ++ if ((sku_vect & IPROC_SKU_STRAP_MASK) != 0x0) ++ { ++ /* enable clocks */ ++ writel_relaxed(0xEA68, IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ ++ usb2_clk_cntrl = readl_relaxed(IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ // printk("USB clk control enable register is: %08x\n", usb2_clk_cntrl); ++ writel_relaxed(0xDD10C3, IPROC_USB2_CLK_CONTROL_PLL_VA); ++ ++ usb2_clk_enable = readl_relaxed(IPROC_USB2_CLK_CONTROL_PLL_VA); ++ // printk("USB clk enable register is: %08x\n", usb2_clk_enable); ++ writel_relaxed(0x0, IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ ++ usb2_clk_cntrl = readl_relaxed(IPROC_USB2_CLK_CONTROL_ENABLE_VA); ++ // printk("USB clk control enable register is: %08x\n", usb2_clk_cntrl); ++ } ++#endif ++ return 0; ++} ++ ++EXPORT_SYMBOL(bcm_usbh_init); ++ ++/* ++ * Function to terminate USB host related low level hardware including PHY, ++ * clocks, etc. ++ * ++ * TODO: expand support for more than one host in the future if needed ++ */ ++int bcm_usbh_term(unsigned int host_index) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(bcm_usbh_term); ++ ++int InUSBDMode(void) ++{ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ int usbd_detect; ++ usbd_detect = readl_relaxed(ChipcommonA_GPIOIn_VA); ++ if (usbd_detect & 1) ++ { ++ printk("%s: %d gpioin val %08x, ohci host mode will not be functional since in USBD mode\n", __FUNCTION__, __LINE__, usbd_detect); ++ printk("%s: %d to make ohci host mode work, appropriate jumper is needed on the board. Please refer to board schematics.\n", ++ __FUNCTION__, __LINE__); ++ } ++ ++ return (usbd_detect & 1); ++#else ++ return 0; ++#endif ++} ++ ++static int __devinit usbh_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct resource *iomem, *ioarea; ++ ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ ++ if (pdev->dev.platform_data == NULL) { ++ dev_err(&pdev->dev, "platform_data missing\n"); ++ ret = -EFAULT; ++ goto err_exit; ++ } ++ memcpy(&usbh_data.hw_cfg, pdev->dev.platform_data, ++ sizeof(usbh_data.hw_cfg)); ++ usbh_data.dev = &pdev->dev; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ dev_err(&pdev->dev, "no mem resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ /* mark the memory region as used */ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), ++ pdev->name); ++ if (!ioarea) { ++ dev_err(&pdev->dev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ /* now map the I/O memory */ ++ usbh_data.ctrl_regs = (struct usbh_ctrl_regs __iomem *) ++ ioremap(iomem->start, sizeof(usbh_data.ctrl_regs)); ++ if (!usbh_data.ctrl_regs) { ++ dev_err(&pdev->dev, "failed to remap registers\n"); ++ ret = -ENOMEM; ++ goto err_free_mem_region; ++ } ++ ++ platform_set_drvdata(pdev, &usbh_data); ++ mutex_init(&usbh_data.lock); ++ usbh_data.init_cnt = 0; ++ atomic_set(&usbh_data.probe_done, 1); ++ ++ return 0; ++ ++err_free_mem_region: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ return ret; ++} ++ ++static int __devexit usbh_remove(struct platform_device *pdev) ++{ ++ struct usbh_priv *drv_data = platform_get_drvdata(pdev); ++ struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ atomic_set(&drv_data->probe_done, 0); ++ platform_set_drvdata(pdev, NULL); ++ iounmap(drv_data->ctrl_regs); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ memset(&usbh_data, 0, sizeof(usbh_data)); ++ ++ return 0; ++} ++ ++static struct platform_driver usbh_driver = ++{ ++ .driver = { ++ .name = "usbh", ++ .owner = THIS_MODULE, ++ }, ++ .probe = usbh_probe, ++ .remove = usbh_remove, ++}; ++ ++static int __init usbh_init(void) ++{ ++ int usb2_reset_state; ++ ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || \ ++ defined(CONFIG_MACH_DNI_3448P) || defined(CONFIG_MACH_ACCTON_AS4610_54)) ++ int clk_enable, k; ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ unsigned int iClk; ++#endif ++ unsigned int USBClk, usbdgpiopwr, pllStatus; ++ ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ /* turn off power for USB device connected to the host */ ++ usbdgpiopwr = readl_relaxed(ChipcommonA_GPIOOut_VA); ++ usbdgpiopwr |= 0x2; ++ writel_relaxed(usbdgpiopwr, ChipcommonA_GPIOOut_VA); ++ writel_relaxed(0x2, ChipcommonA_GPIOOutEn_VA); ++#endif ++ ++ /* Do USB PHY reset */ ++ mdelay(100); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ /* bring phy pll out of reset if not done already */ ++ if ((USBClk & 0x01000000) == 0 ) ++ { ++ USBClk |= 0x01000000; ++ writel_relaxed(USBClk, IPROC_USB_PHY_CTRL_VA); ++ pllStatus = readl_relaxed(IPROC_WRAP_MISC_STATUS_VA); ++ for (k = 0; k < 100000; k++) ++ { ++ if ((pllStatus & 2) == 2) ++ { ++ printk("USB phy pll locked\n"); ++ break; ++ } ++ pllStatus = readl_relaxed(IPROC_WRAP_MISC_STATUS_VA); ++ } ++ } ++ writel_relaxed(USBClk & (~(1<<23)), IPROC_USB_PHY_CTRL_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock is: %08x\n", clk_enable); ++ clk_enable |= 1; ++ writel_relaxed(clk_enable, IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock now is: %08x\n", clk_enable); ++#if defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_DNI_3448P) || \ ++ defined(CONFIG_MACH_ACCTON_AS4610_54) ++ iClk = readl_relaxed(IPROC_XGPLL_VA); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ if ((iClk & 0xff) == IPROC_CLK_NDIV_40) ++ { ++ writel_relaxed((USBClk & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_40, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ } ++ else if ((iClk & 0xff) == IPROC_CLK_NDIV_20) ++ { ++ writel_relaxed((USBClk & USB_CLK_NDIV_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PLL_RESET_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ writel_relaxed((USBClk & USB_CLK_PHY_RESET_MASK) | USB_CLK_NDIV_20, IPROC_USB_PHY_CTRL_VA); ++ udelay(10); ++ USBClk = readl_relaxed(IPROC_USB_PHY_CTRL_VA); ++ printk("iClk = %08x, USBClk = %08x\n", iClk, USBClk); ++ } ++#endif ++ mdelay(100); ++ writel_relaxed(USBClk | (1<<23), IPROC_USB_PHY_CTRL_VA); ++ udelay(100); ++#endif ++#if defined(CONFIG_MACH_NSP) ++ int clk_enable; ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock is: %08x\n", clk_enable); ++ clk_enable |= 1; ++ writel_relaxed(clk_enable, IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ clk_enable = readl_relaxed(IPROC_IDM_USB2_IO_CONTROL_DIRECT_VA); ++ printk("Initial usb2h clock now is: %08x\n", clk_enable); ++#endif ++ ++ usb2_reset_state = readl_relaxed(IPROC_IDM_USB2_RESET_CONTROL_VA); ++ printk("Initial usb2_reset_state is: %08x\n", usb2_reset_state); ++ if ((usb2_reset_state & 1) == 1) ++ { ++ writel_relaxed(0x0, IPROC_IDM_USB2_RESET_CONTROL_VA); ++ usb2_reset_state = readl_relaxed(IPROC_IDM_USB2_RESET_CONTROL_VA); ++ printk("usb2_reset_state is set and now it is: %08x\n", usb2_reset_state); ++ } ++#if (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2)) ++ /* supply power for USB device connected to the host */ ++ mdelay(100); ++ usbdgpiopwr = readl_relaxed(ChipcommonA_GPIOOut_VA); ++ usbdgpiopwr &= SUPPLY_USBD_POWER; ++ writel_relaxed(usbdgpiopwr, ChipcommonA_GPIOOut_VA); ++ writel_relaxed(0x2, ChipcommonA_GPIOOutEn_VA); ++#endif ++ return platform_driver_register(&usbh_driver); ++} ++ ++static void __exit usbh_exit(void) ++{ ++ platform_driver_unregister(&usbh_driver); ++} ++ ++module_init(usbh_init); ++module_exit(usbh_exit); ++ ++MODULE_AUTHOR("Broadcom"); ++MODULE_DESCRIPTION("Broadcom USB host low-level driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/bcmdrivers/usb2h/bcm_usbh.h b/drivers/bcmdrivers/usb2h/bcm_usbh.h +new file mode 100644 +index 0000000..019589a +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/bcm_usbh.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _BCM_USBH_H_ ++#define _BCM_USBH_H_ ++ ++extern int bcm_usbh_init(unsigned int host_index); ++extern int bcm_usbh_term(unsigned int host_index); ++extern int bcm_usbh_suspend(unsigned int host_index); ++extern int bcm_usbh_resume(unsigned int host_index); ++ ++#endif +diff --git a/drivers/bcmdrivers/usb2h/ehci-bcm.c b/drivers/bcmdrivers/usb2h/ehci-bcm.c +new file mode 100644 +index 0000000..62534b8 +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/ehci-bcm.c +@@ -0,0 +1,383 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "bcm_usbh.h" ++ ++#define BCM_USBEHCI_MODULE_DESCRIPTION "Broadcom USB EHCI driver" ++#define BCM_USBEHCI_MODULE_VERSION "1.0.0" ++ ++#define BCM_USBEHCI_IRQF_FLAGS (IRQF_DISABLED | IRQF_SHARED) ++#define BCM_USBEHCI_NAME "bcm-ehci" ++ ++#define EHCI_INFO(pdev, fmt, args...) dev_info(&pdev->dev, fmt, ## args) ++#define EHCI_ERR(pdev, fmt, args...) dev_err(&pdev->dev, fmt, ## args) ++#define BCM_USB_FIFO_THRESHOLD 0x00800040 ++ ++struct usb_cfg ++{ ++ void *virt_reg_base; ++ struct usb_hcd *hcd; ++}; ++ ++extern int usb_disabled(void); ++static int hcd_init(struct usb_hcd *hcd); ++ ++static const struct hc_driver ehci_hcd_driver = ++{ ++ .description = hcd_name, ++ .product_desc = BCM_USBEHCI_NAME, ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ehci_irq, ++ .flags = HCD_USB2 | HCD_MEMORY | HCD_LOCAL_MEM, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .reset = hcd_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ehci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++#ifdef CONFIG_PM ++ .bus_suspend = ehci_bus_suspend, ++ .bus_resume = ehci_bus_resume, ++#endif ++ .relinquish_port = ehci_relinquish_port, ++ .port_handed_over = ehci_port_handed_over, ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++int hcd_init(struct usb_hcd *hcd) ++{ ++ struct ehci_hcd *ehci; ++ int err; ++ ++ if (!hcd) { ++ printk(KERN_ERR "invalid hcd pointer in %s\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ ehci = hcd_to_ehci(hcd); ++ ++ if ((err = ehci_halt(ehci)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_halt() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ if ((err = ehci_init(hcd)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_init() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ /* ++ * Not sure why this is not set by ehci_init(). Convention seems to be ++ * to do it here for reasons unknown. This is a "packed release number". ++ */ ++ ehci->sbrn = 0x20; ++ ++ if ((err = ehci_reset(ehci)) < 0) { ++ printk(KERN_ERR "busnum %d: ehci_reset() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int bcm_ehci_probe(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb; ++ struct usb_hcd *hcd; ++ struct ehci_hcd *ehci; ++ struct resource *iomem, *ioarea; ++ int ret, irq; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ EHCI_ERR(pdev, "no mem resource\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* get the irq info */ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ EHCI_ERR(pdev, "no irq resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), pdev->name); ++ if (!ioarea) { ++ EHCI_ERR(pdev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ usb = kzalloc(sizeof(*usb), GFP_KERNEL); ++ if (!usb) { ++ EHCI_ERR(pdev, "unable to allocate memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_iomem; ++ } ++ ++ usb->virt_reg_base = ioremap(iomem->start, resource_size(iomem)); ++ if (!usb->virt_reg_base) { ++ EHCI_ERR(pdev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_free_private_mem; ++ } ++ ++ /* enable clock and PHY */ ++ ret = bcm_usbh_init(pdev->id); ++ if (ret < 0) { ++ EHCI_ERR(pdev, "clock and PHY initialization failed\n"); ++ goto err_io_unmap; ++ } ++ ++ hcd = usb_create_hcd(&ehci_hcd_driver, &pdev->dev, (char *)pdev->name); ++ if (!hcd) { ++ EHCI_ERR(pdev, "usb_create_hcd failed\n"); ++ ret = -ENOMEM; ++ goto err_usb_term; ++ } ++ ++ /* struct ehci_regs def'd in Linux ehci.h which is included by Linux ehci-hcd.c */ ++ usb->hcd = hcd; ++ hcd->rsrc_start = (unsigned int)usb->virt_reg_base; ++ hcd->rsrc_len = sizeof(struct ehci_regs); ++ hcd->regs = usb->virt_reg_base; ++ ++ ehci = hcd_to_ehci(hcd); ++ ehci->caps = hcd->regs; ++ ehci->regs = hcd->regs + HC_LENGTH(ehci,ehci_readl(ehci, &ehci->caps->hc_capbase)); ++ ++ /* cache this readonly data; minimize chip reads */ ++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ++ ++ ret = usb_add_hcd(hcd, irq, BCM_USBEHCI_IRQF_FLAGS); ++ if (ret) { ++ EHCI_ERR(pdev, "usb_add_hcd failed\n"); ++ goto err_remove_hcd; ++ } ++ ++ ehci_writel(ehci,BCM_USB_FIFO_THRESHOLD, &ehci->regs->reserved4[6]); ++ ++ ++ platform_set_drvdata(pdev, usb); ++ ++ EHCI_INFO(pdev, "probe done\n"); ++ return 0; ++ ++err_remove_hcd: ++ //usb_remove_hcd(hcd); ++ //usb_put_hcd(hcd); ++ ++err_usb_term: ++ bcm_usbh_term(pdev->id); ++ ++err_io_unmap: ++ iounmap(usb->virt_reg_base); ++ ++err_free_private_mem: ++ kfree(usb); ++ ++err_free_iomem: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ EHCI_ERR(pdev, "probe failed: %d\n", ret); ++ return ret; ++} ++ ++int bcm_ehci_remove(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct resource *iomem; ++ ++ usb_remove_hcd(hcd); ++ usb_put_hcd(hcd); ++ ++ bcm_usbh_term(pdev->id); ++ iounmap(usb->virt_reg_base); ++ kfree(usb); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void bcm_ehci_shutdown(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++#ifdef CONFIG_PM ++static int bcm_ehci_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ if (time_before(jiffies, ehci->next_statechange)) ++ msleep(10); ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave (&ehci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ehci_writel(ehci, 0, &ehci->regs->intr_enable); ++ (void)ehci_readl(ehci, &ehci->regs->intr_enable); ++ ++ /* make sure snapshot being resumed re-enumerates everything */ ++ if (message.event == PM_EVENT_PRETHAW) { ++ ehci_halt(ehci); ++ ehci_reset(ehci); ++ } ++ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ rc = bcm_usbh_suspend(pdev->id); ++ ++bail: ++ spin_unlock_irqrestore (&ehci->lock, flags); ++ ++ return rc; ++} ++ ++static int bcm_ehci_resume(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ int rc; ++ ++ if (time_before(jiffies, ehci->next_statechange)) ++ msleep(100); ++ ++ rc = bcm_usbh_resume(pdev->id); ++ ++ /* Mark hardware accessible again as we are out of D3 state by now */ ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ++ /* If CF is still set, we maintained PCI Vaux power. ++ * Just undo the effect of ehci_pci_suspend(). ++ */ ++ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { ++ int mask = INTR_MASK; ++ ++ if (!hcd->self.root_hub->do_remote_wakeup) ++ mask &= ~STS_PCD; ++ ehci_writel(ehci, mask, &ehci->regs->intr_enable); ++ ehci_readl(ehci, &ehci->regs->intr_enable); ++ return 0; ++ } ++ ++ ehci_dbg(ehci, "lost power, restarting\n"); ++ usb_root_hub_lost_power(hcd->self.root_hub); ++ ++ /* ++ * Else reset, to cope with power loss or flush-to-storage ++ * style "resume" having let BIOS kick in during reboot. ++ */ ++ (void)ehci_halt(ehci); ++ (void)ehci_reset(ehci); ++ ++ /* emptying the schedule aborts any urbs */ ++ spin_lock_irq(&ehci->lock); ++#warning "TODO: ehci->reclaim no longer part of struct ehci_hcd" ++ ehci_work(ehci); ++ spin_unlock_irq(&ehci->lock); ++ ++ ehci_writel(ehci, ehci->command, &ehci->regs->command); ++ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); ++ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ ++ ++ /* here we "know" root ports should always stay powered */ ++ ehci_port_power(ehci, 1); ++ ++ hcd->state = HC_STATE_SUSPENDED; ++ ++ return 0; ++} ++ ++#else ++#define bcm_ehci_suspend NULL ++#define bcm_ehci_resume NULL ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver ehci_bcm_driver = ++{ ++ .probe = bcm_ehci_probe, ++ .remove = bcm_ehci_remove, ++ .shutdown = bcm_ehci_shutdown, ++ .suspend = bcm_ehci_suspend, ++ .resume = bcm_ehci_resume, ++ .driver = { ++ .name = BCM_USBEHCI_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_DESCRIPTION(BCM_USBEHCI_MODULE_DESCRIPTION); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(BCM_USBEHCI_MODULE_VERSION); +diff --git a/drivers/bcmdrivers/usb2h/ohci-bcm.c b/drivers/bcmdrivers/usb2h/ohci-bcm.c +new file mode 100644 +index 0000000..24b21fe +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/ohci-bcm.c +@@ -0,0 +1,314 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include ++#include "bcm_usbh.h" ++ ++#define BCM_USBOHCI_MODULE_DESCRIPTION "Broadcom USB OHCI driver" ++#define BCM_USBOHCI_MODULE_VERSION "1.0.0" ++ ++#define BCM_USBOHCI_IRQF_FLAGS (IRQF_DISABLED | IRQF_SHARED) ++#define BCM_USBOHCI_NAME "bcm-ohci" ++ ++#define OHCI_INFO(pdev, fmt, args...) dev_info(&pdev->dev, fmt, ## args) ++#define OHCI_ERR(pdev, fmt, args...) dev_err(&pdev->dev, fmt, ## args) ++ ++struct usb_cfg ++{ ++ void *virt_reg_base; ++ struct usb_hcd *hcd; ++}; ++ ++extern int usb_disabled(void); ++extern int InUSBDMode(void); ++static int bcm_ohci_start(struct usb_hcd *hcd); ++ ++static const struct hc_driver ohci_hcd_driver = ++{ ++ .description = hcd_name, ++ .product_desc = BCM_USBOHCI_NAME, ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .start = bcm_ohci_start, ++ .stop = ohci_stop, ++ .shutdown = ohci_shutdown, ++#ifdef CONFIG_PM ++ .bus_suspend = ohci_bus_suspend, ++ .bus_resume = ohci_bus_resume, ++#endif ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ohci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++}; ++ ++static int bcm_ohci_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci; ++ int err; ++ ++ if (!hcd) { ++ printk(KERN_ERR "invalid hcd pointer in %s\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ ohci = hcd_to_ohci(hcd); ++ ++ if ((err = ohci_init(ohci)) < 0) { ++ printk(KERN_ERR "busnum %d: ohci_init() failed, err=%d\n", hcd->self.busnum, err); ++ return err; ++ } ++ ++ if ((err = ohci_run(ohci)) < 0) { ++ printk(KERN_ERR "busnum %d: ohci_run() failed, err=%d\n", hcd->self.busnum, err); ++ ohci_stop(hcd); ++ return err; ++ } ++ ++ return 0; ++} ++ ++int bcm_ohci_probe(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb; ++ struct usb_hcd *hcd; ++ struct resource *iomem, *ioarea; ++ int ret, irq; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ if (InUSBDMode()) ++ return -ENODEV; ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ OHCI_ERR(pdev, "no mem resource\n"); ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ /* get the irq info */ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ OHCI_ERR(pdev, "no irq resource\n"); ++ ret = -ENODEV; ++ goto err_exit; ++ } ++ ++ ioarea = request_mem_region(iomem->start, resource_size(iomem), pdev->name); ++ if (!ioarea) { ++ OHCI_ERR(pdev, "memory region already claimed\n"); ++ ret = -EBUSY; ++ goto err_exit; ++ } ++ ++ usb = kzalloc(sizeof(*usb), GFP_KERNEL); ++ if (!usb) { ++ OHCI_ERR(pdev, "unable to allocate memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_iomem; ++ } ++ ++ usb->virt_reg_base = ioremap(iomem->start, resource_size(iomem)); ++ if (!usb->virt_reg_base) { ++ OHCI_ERR(pdev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_free_private_mem; ++ } ++ ++ /* enable clock and PHY */ ++ ret = bcm_usbh_init(pdev->id); ++ if (ret < 0) { ++ OHCI_ERR(pdev, "clock and PHY initialization failed\n"); ++ goto err_io_unmap; ++ } ++ ++ hcd = usb_create_hcd(&ohci_hcd_driver, &pdev->dev, (char *)pdev->name); ++ if (!hcd) { ++ OHCI_ERR(pdev, "usb_create_hcd failed\n"); ++ ret = -ENOMEM; ++ goto err_usb_term; ++ } ++ ++ /* struct ohci_regs def'd in Linux ohci.h which is included by Linux ohci-hcd.c */ ++ usb->hcd = hcd; ++ hcd->rsrc_start = (unsigned int)usb->virt_reg_base; ++ hcd->rsrc_len = sizeof(struct ohci_regs); ++ hcd->regs = usb->virt_reg_base; ++ ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ ret = usb_add_hcd(hcd, irq, BCM_USBOHCI_IRQF_FLAGS); ++ if (ret) { ++ OHCI_ERR(pdev, "usb_add_hcd failed\n"); ++ goto err_remove_hcd; ++ } ++ ++ platform_set_drvdata(pdev, usb); ++ ++ OHCI_INFO(pdev, "probe done\n"); ++ return 0; ++ ++err_remove_hcd: ++ //usb_remove_hcd(hcd); ++ //usb_put_hcd(hcd); ++ ++err_usb_term: ++ bcm_usbh_term(pdev->id); ++ ++err_io_unmap: ++ iounmap(usb->virt_reg_base); ++ ++err_free_private_mem: ++ kfree(usb); ++ ++err_free_iomem: ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++err_exit: ++ OHCI_ERR(pdev, "probe failed: %d\n", ret); ++ return ret; ++} ++ ++int bcm_ohci_remove(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct resource *iomem; ++ ++ usb_remove_hcd(hcd); ++ usb_put_hcd(hcd); ++ ++ bcm_usbh_term(pdev->id); ++ iounmap(usb->virt_reg_base); ++ kfree(usb); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static void bcm_ohci_shutdown(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++#ifdef CONFIG_PM ++static int bcm_ohci_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ unsigned long flags; ++ int rc = 0; ++ ++ /* Root hub was already suspended. Disable irq emission and ++ * mark HW unaccessible, bail out if RH has been resumed. Use ++ * the spinlock to properly synchronize with possible pending ++ * RH suspend or resume activity. ++ * ++ * This is still racy as hcd->state is manipulated outside of ++ * any locks =P But that will be a different fix. ++ */ ++ spin_lock_irqsave(&ohci->lock, flags); ++ if (hcd->state != HC_STATE_SUSPENDED) { ++ rc = -EINVAL; ++ goto bail; ++ } ++ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); ++ (void)ohci_readl(ohci, &ohci->regs->intrdisable); ++ ++ /* make sure snapshot being resumed re-enumerates everything */ ++ if (message.event == PM_EVENT_PRETHAW) ++ ohci_usb_reset(ohci); ++ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ rc = bcm_usbh_suspend(pdev->id); ++ ++bail: ++ spin_unlock_irqrestore(&ohci->lock, flags); ++ return rc; ++} ++ ++static int bcm_ohci_resume(struct platform_device *pdev) ++{ ++ struct usb_cfg *usb = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = usb->hcd; ++ ++ bcm_usbh_resume(pdev->id); ++ ++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ ohci_finish_controller_resume(hcd); ++ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++/* ++ * Generic platform device driver definition. ++ */ ++static struct platform_driver ohci_bcm_driver = ++{ ++ .probe = bcm_ohci_probe, ++ .remove = bcm_ohci_remove, ++ .shutdown = bcm_ohci_shutdown, ++#ifdef CONFIG_PM ++ .suspend = bcm_ohci_suspend, ++ .resume = bcm_ohci_resume, ++#endif ++ .driver = { ++ .name = BCM_USBOHCI_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_DESCRIPTION(BCM_USBOHCI_MODULE_DESCRIPTION); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(BCM_USBOHCI_MODULE_VERSION); +diff --git a/drivers/bcmdrivers/usb2h/usbh_cfg.h b/drivers/bcmdrivers/usb2h/usbh_cfg.h +new file mode 100644 +index 0000000..c00b0ae +--- /dev/null ++++ b/drivers/bcmdrivers/usb2h/usbh_cfg.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef __ISLAND_USBH_CFG_H ++#define __ISLAND_USBH_CFG_H ++ ++#define USBH_NUM_PORTS 3 ++ ++struct usbh_port_cfg { ++ /* GPIO for host power */ ++ int pwr_gpio; ++ ++ /* GPIO for power fault (over-current) detection */ ++ int pwr_flt_gpio; ++ ++ /* GPIO for PHY reset */ ++ int reset_gpio; ++}; ++ ++/* ++ * USB Host related HW parameters ++ */ ++struct usbh_cfg { ++ /* peripheral clock name string */ ++ char *peri_clk_name; ++ ++ /* AHB bus clock name string */ ++ char *ahb_clk_name; ++ ++ /* the block might require optional clock to be enabled */ ++ char *opt_clk_name; ++ ++ unsigned int num_ports; ++ ++ struct usbh_port_cfg port[USBH_NUM_PORTS]; ++}; ++ ++#endif +diff --git a/drivers/bcmdrivers/wdt/.gitignore b/drivers/bcmdrivers/wdt/.gitignore +new file mode 100644 +index 0000000..d741861 +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/.gitignore +@@ -0,0 +1,4 @@ ++/.built-in.o.cmd ++/built-in.o ++/modules.builtin ++/modules.order +diff --git a/drivers/bcmdrivers/wdt/Kconfig b/drivers/bcmdrivers/wdt/Kconfig +new file mode 100644 +index 0000000..ad0b803 +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/Kconfig +@@ -0,0 +1,7 @@ ++config IPROC_WDT ++ tristate "Watchdog Timer support" ++ select WATCHDOG ++ depends on ARCH_IPROC && MACH_NS ++ help ++ This selects a driver for the hardware watchdog on Broadcom ++ iProc chips. +diff --git a/drivers/bcmdrivers/wdt/Makefile b/drivers/bcmdrivers/wdt/Makefile +new file mode 100644 +index 0000000..aefed3e +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_IPROC_WDT) += iproc_wdt.o +diff --git a/drivers/bcmdrivers/wdt/iproc_wdt.c b/drivers/bcmdrivers/wdt/iproc_wdt.c +new file mode 100755 +index 0000000..33812fa +--- /dev/null ++++ b/drivers/bcmdrivers/wdt/iproc_wdt.c +@@ -0,0 +1,491 @@ ++/* ++ * Copyright (C) 2013, Broadcom Corporation. All Rights Reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++#include ++#endif ++ ++/* Chip specific */ ++#define IPROC_WATCHDOG_CLK_HZ 125000000UL ++#define IPROC_WATCHDOG_COUNTER_BITS (28) ++ ++/* Default values */ ++#define TIMEOUT_MAX \ ++ ((int)((1 << IPROC_WATCHDOG_COUNTER_BITS) - 1) / IPROC_WATCHDOG_CLK_HZ) ++#define TIMEOUT_DEFAULT (TIMEOUT_MAX > 60? (int)60 : (int)TIMEOUT_MAX) ++ ++/* module parameters */ ++static int timeout = TIMEOUT_DEFAULT; ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout, ++ "Timeout value. (default=" ++ __MODULE_STRING(TIMEOUT_DEFAULT) ")"); ++ ++static int nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++/* Watchdog register offsets and field */ ++#define IPROC_REG_WDT_INTSTATUS 0x20 ++#define IPROC_FLD_WDT_INTSTATUS_WDT_RESET_MASK 0x80000000 ++#define IPROC_REG_WDT_WATCHDOG_COUNTER 0x80 ++ ++/* Register access macro */ ++#define wdt_readl(dev, reg) \ ++ readl_relaxed((dev)->regs + (reg)) ++#define wdt_writel(dev, reg, value) \ ++ writel_relaxed((value), (dev)->regs + (reg)) ++ ++/* Driver specific data */ ++struct wdt_iproc { ++ volatile void *regs; ++ spinlock_t io_lock; ++ int timeout; ++ int boot_status; ++ unsigned long users; ++ struct miscdevice miscdev; ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ SWRR_HANDLE swrr; ++#endif ++}; ++static struct wdt_iproc *wdt; ++static char expect_release; ++ ++/* ++ * Disable the watchdog. ++ */ ++static inline void ++iproc_wdt_stop(void) ++{ ++ spin_lock(&wdt->io_lock); ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) ++ swreset_record_set(wdt->swrr, 0); ++#endif ++ wdt_writel(wdt, ++ IPROC_REG_WDT_WATCHDOG_COUNTER, ++ 0 ++ ); ++ spin_unlock(&wdt->io_lock); ++} ++ ++/* ++ * Enable and reset the watchdog. ++ */ ++static inline void ++iproc_wdt_start(void) ++{ ++ spin_lock(&wdt->io_lock); ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) ++ swreset_record_set(wdt->swrr, 1); ++#endif ++ wdt_writel(wdt, ++ IPROC_REG_WDT_WATCHDOG_COUNTER, ++ wdt->timeout * IPROC_WATCHDOG_CLK_HZ ++ ); ++ spin_unlock(&wdt->io_lock); ++} ++ ++/* ++ * Pat the watchdog timer. ++ */ ++static inline void ++iproc_wdt_pat(void) ++{ ++ iproc_wdt_start(); ++} ++ ++/* ++ * Watchdog device is opened, and watchdog starts running. ++ */ ++static int ++iproc_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(1, &wdt->users)) ++ return -EBUSY; ++ ++ iproc_wdt_start(); ++ return nonseekable_open(inode, file); ++} ++ ++/* ++ * Close the watchdog device. ++ */ ++static int ++iproc_wdt_close(struct inode *inode, struct file *file) ++{ ++ if (expect_release == 1) { ++ iproc_wdt_stop(); ++ } else { ++ dev_dbg(wdt->miscdev.parent, ++ "unexpected close, not stopping watchdog!\n"); ++ iproc_wdt_pat(); ++ } ++ clear_bit(1, &wdt->users); ++ expect_release = 0; ++ return 0; ++} ++ ++/* ++ * Change the watchdog time interval. ++ */ ++static int ++iproc_wdt_settimeout(int time) ++{ ++ if (time < 0 || time > TIMEOUT_MAX) { ++ return -EINVAL; ++ } ++ ++ /* ++ * Set new watchdog time. It will be used when iproc_wdt_start() is ++ * called. ++ */ ++ wdt->timeout = time; ++ return 0; ++} ++ ++/* ++ * Get the watchdog status. ++ */ ++static int ++iproc_wdt_get_status(void) ++{ ++ if (wdt_readl(wdt, IPROC_REG_WDT_INTSTATUS) & ++ IPROC_FLD_WDT_INTSTATUS_WDT_RESET_MASK) { ++ return WDIOF_CARDRESET; ++ } ++ ++ return 0; ++} ++ ++static const struct watchdog_info iproc_wdt_info = { ++ .identity = "iproc watchdog", ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++}; ++ ++/* ++ * Handle commands from user-space. ++ */ ++static long ++iproc_wdt_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret = -ENOTTY; ++ int time; ++ void __user *argp = (void __user *)arg; ++ int __user *p = argp; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user(argp, &iproc_wdt_info, ++ sizeof(iproc_wdt_info)) ? -EFAULT : 0; ++ break; ++ case WDIOC_GETSTATUS: ++ ret = put_user(0, p); ++ break; ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(wdt->boot_status, p); ++ break; ++ case WDIOC_SETOPTIONS: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ if (time & WDIOS_DISABLECARD) ++ iproc_wdt_stop(); ++ if (time & WDIOS_ENABLECARD) ++ iproc_wdt_start(); ++ ret = 0; ++ break; ++ case WDIOC_KEEPALIVE: ++ iproc_wdt_pat(); ++ ret = 0; ++ break; ++ case WDIOC_SETTIMEOUT: ++ ret = get_user(time, p); ++ if (ret) ++ break; ++ ret = iproc_wdt_settimeout(time); ++ if (ret) ++ break; ++ /* Enable new time value */ ++ iproc_wdt_start(); ++ /* fall through */ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(wdt->timeout, p); ++ break; ++ } ++ ++ return ret; ++} ++ ++static ssize_t ++iproc_wdt_write(struct file *file, const char __user *data, ++ size_t len, loff_t *ppos) ++{ ++ /* See if we got the magic character 'V' and reload the timer */ ++ if (len) { ++ if (!nowayout) { ++ size_t i; ++ ++ /* ++ * note: just in case someone wrote the magic ++ * character five months ago... ++ */ ++ expect_release = 0; ++ ++ /* ++ * scan to see whether or not we got the magic ++ * character ++ */ ++ for (i = 0; i != len; i++) { ++ char c; ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ if (c == 'V') ++ expect_release = 1; ++ } ++ } ++ /* someone wrote to us, we should pat the watchdog */ ++ iproc_wdt_pat(); ++ } ++ return len; ++} ++ ++static int ++iproc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) ++{ ++ if (code == SYS_DOWN || code == SYS_HALT) { ++ /* Turn the watchdog off */ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) { ++ swreset_record_set(wdt->swrr, 0); ++ } ++#endif ++ iproc_wdt_stop(); ++ } ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block iproc_wdt_notifier = { ++ .notifier_call = iproc_wdt_notify_sys, ++}; ++ ++static const struct file_operations iproc_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = iproc_wdt_ioctl, ++ .open = iproc_wdt_open, ++ .release = iproc_wdt_close, ++ .write = iproc_wdt_write, ++}; ++ ++static int __init ++iproc_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ int ret; ++ ++ if (wdt) { ++ dev_dbg(&pdev->dev, "only 1 wdt instance supported.\n"); ++ return -EBUSY; ++ } ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ dev_dbg(&pdev->dev, "missing resource 0\n"); ++ return -ENXIO; ++ } ++ ++ wdt = kzalloc(sizeof(struct wdt_iproc), GFP_KERNEL); ++ if (!wdt) { ++ dev_dbg(&pdev->dev, "no memory for wdt structure\n"); ++ return -ENOMEM; ++ } ++ ++ wdt->regs = ioremap(regs->start, resource_size(regs)); ++ if (!wdt->regs) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "could not map I/O memory\n"); ++ goto err_free; ++ } ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (swreset_record_get_record_count() == 0) { ++ /* No software reset record support */ ++ wdt->swrr = NULL; ++ wdt->boot_status = iproc_wdt_get_status(); ++ } else { ++ wdt->swrr = swreset_record_register("iproc_cca_watchdog"); ++ if (wdt->swrr == NULL) { ++ /* All software reset records are used (unlikely) */ ++ dev_warn(&pdev->dev, "Boot status is not available!\n"); ++ /* Still try to use original watchdog reset status */ ++ wdt->boot_status = iproc_wdt_get_status(); ++ } else { ++ /* Get previous value */ ++ swreset_record_get(wdt->swrr, &wdt->boot_status); ++ /* Clear it */ ++ swreset_record_set(wdt->swrr, 0); ++ } ++ } ++#else ++ wdt->boot_status = iproc_wdt_get_status(); ++#endif ++ ++ /* To avoid treating manual reboot as a watchdog reset */ ++ ret = register_reboot_notifier(&iproc_wdt_notifier); ++ if (ret) { ++ /* In this case, manual reboot could be mistaken as watchdog reset */ ++ dev_dbg(&pdev->dev, "could not register reboot notifier\n"); ++ } ++ ++ expect_release = 0; ++ spin_lock_init(&wdt->io_lock); ++ wdt->users = 0; ++ ++ wdt->miscdev.minor = WATCHDOG_MINOR; ++ wdt->miscdev.name = "watchdog"; ++ wdt->miscdev.fops = &iproc_wdt_fops; ++ wdt->miscdev.parent = &pdev->dev; ++ ++ platform_set_drvdata(pdev, wdt); ++ ++ if (iproc_wdt_settimeout(timeout)) { ++ iproc_wdt_settimeout(TIMEOUT_DEFAULT); ++ dev_dbg(&pdev->dev, ++ "default timeout invalid, set to %d sec.\n", ++ TIMEOUT_DEFAULT); ++ } ++ ++ ret = misc_register(&wdt->miscdev); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); ++ goto err_register; ++ } ++ ++ dev_info(&pdev->dev, ++ "iProc Watchdog Timer - timeout=%d sec, nowayout=%d\n", ++ wdt->timeout, nowayout); ++ ++ return 0; ++ ++err_register: ++ platform_set_drvdata(pdev, NULL); ++ iounmap(wdt->regs); ++err_free: ++ kfree(wdt); ++ wdt = NULL; ++ return ret; ++} ++ ++static int __exit ++iproc_wdt_remove(struct platform_device *pdev) ++{ ++ if (wdt && platform_get_drvdata(pdev) == wdt) { ++ /* Stop the timer before we leave */ ++ if (!nowayout) ++ iproc_wdt_stop(); ++ ++#ifdef CONFIG_IPROC_SW_RESET_RECORD ++ if (wdt->swrr != NULL) { ++ swreset_record_set(wdt->swrr, 0); ++ swreset_record_unregister(wdt->swrr); ++ wdt->swrr = NULL; ++ } ++#endif ++ unregister_reboot_notifier(&iproc_wdt_notifier); ++ misc_deregister(&wdt->miscdev); ++ iounmap(wdt->regs); ++ kfree(wdt); ++ wdt = NULL; ++ platform_set_drvdata(pdev, NULL); ++ } ++ return 0; ++} ++ ++static void ++iproc_wdt_shutdown(struct platform_device *pdev) ++{ ++ iproc_wdt_stop(); ++} ++ ++#ifdef CONFIG_PM ++static int ++iproc_wdt_suspend(struct platform_device *pdev, pm_message_t message) ++{ ++ iproc_wdt_stop(); ++ return 0; ++} ++ ++static int ++iproc_wdt_resume(struct platform_device *pdev) ++{ ++ if (wdt->users) ++ iproc_wdt_start(); ++ return 0; ++} ++#else ++#define iproc_wdt_suspend NULL ++#define iproc_wdt_resume NULL ++#endif ++ ++/* work with hotplug and coldplug */ ++MODULE_ALIAS("platform:iproc_wdt"); ++ ++static struct platform_driver iproc_wdt_driver = { ++ .remove = __exit_p(iproc_wdt_remove), ++ .suspend = iproc_wdt_suspend, ++ .resume = iproc_wdt_resume, ++ .driver = { ++ .name = "iproc_wdt", ++ .owner = THIS_MODULE, ++ }, ++ .shutdown = iproc_wdt_shutdown, ++}; ++ ++static int __init ++iproc_wdt_init(void) ++{ ++ return platform_driver_probe(&iproc_wdt_driver, iproc_wdt_probe); ++} ++module_init(iproc_wdt_init); ++ ++static void __exit ++iproc_wdt_exit(void) ++{ ++ platform_driver_unregister(&iproc_wdt_driver); ++} ++module_exit(iproc_wdt_exit); ++ ++MODULE_AUTHOR("Broadcom Corporation"); ++MODULE_DESCRIPTION("Watchdog driver for Broadcom iProc chips"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index e9e8f3b..1d2ae23 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch new file mode 100644 index 00000000..06004175 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-hi-lo.h.patch @@ -0,0 +1,34 @@ +--- /dev/null ++++ b/include/asm-generic/io-64-nonatomic-hi-lo.h +@@ -0,0 +1,28 @@ ++#ifndef _ASM_IO_64_NONATOMIC_HI_LO_H_ ++#define _ASM_IO_64_NONATOMIC_HI_LO_H_ ++ ++#include ++#include ++ ++#ifndef readq ++static inline __u64 readq(const volatile void __iomem *addr) ++{ ++ const volatile u32 __iomem *p = addr; ++ u32 low, high; ++ ++ high = readl(p + 1); ++ low = readl(p); ++ ++ return low + ((u64)high << 32); ++} ++#endif ++ ++#ifndef writeq ++static inline void writeq(__u64 val, volatile void __iomem *addr) ++{ ++ writel(val >> 32, addr + 4); ++ writel(val, addr); ++} ++#endif ++ ++#endif /* _ASM_IO_64_NONATOMIC_HI_LO_H_ */ +diff --git a/include/asm-generic/io-64-nonatomic-lo-hi.h b/include/asm-generic/io-64-nonatomic-lo-hi.h +new file mode 100644 +index 0000000..ca546b1 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch new file mode 100644 index 00000000..28c861d3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_asm-generic_io-64-nonatomic-lo-hi.h.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/include/asm-generic/io-64-nonatomic-lo-hi.h +@@ -0,0 +1,28 @@ ++#ifndef _ASM_IO_64_NONATOMIC_LO_HI_H_ ++#define _ASM_IO_64_NONATOMIC_LO_HI_H_ ++ ++#include ++#include ++ ++#ifndef readq ++static inline __u64 readq(const volatile void __iomem *addr) ++{ ++ const volatile u32 __iomem *p = addr; ++ u32 low, high; ++ ++ low = readl(p); ++ high = readl(p + 1); ++ ++ return low + ((u64)high << 32); ++} ++#endif ++ ++#ifndef writeq ++static inline void writeq(__u64 val, volatile void __iomem *addr) ++{ ++ writel(val, addr); ++ writel(val >> 32, addr + 4); ++} ++#endif ++ ++#endif /* _ASM_IO_64_NONATOMIC_LO_HI_H_ */ +diff --git a/include/drm/Kbuild b/include/drm/Kbuild +index 3a60ac8..1e38a19 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch new file mode 100644 index 00000000..9e834fe1 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_amba_bus.h.patch @@ -0,0 +1,42 @@ +--- a/include/linux/amba/bus.h ++++ b/include/linux/amba/bus.h +@@ -94,4 +94,37 @@ void amba_release_regions(struct amba_device *); + #define amba_manf(d) AMBA_MANF_BITS((d)->periphid) + #define amba_part(d) AMBA_PART_BITS((d)->periphid) + ++#define __AMBA_DEV(busid, data, mask) \ ++ { \ ++ .coherent_dma_mask = mask, \ ++ .init_name = busid, \ ++ .platform_data = data, \ ++ } ++ ++/* ++ * APB devices do not themselves have the ability to address memory, ++ * so DMA masks should be zero (much like USB peripheral devices.) ++ * The DMA controller DMA masks should be used instead (much like ++ * USB host controllers in conventional PCs.) ++ */ ++#define AMBA_APB_DEVICE(name, busid, id, base, irqs, data) \ ++struct amba_device name##_device = { \ ++ .dev = __AMBA_DEV(busid, data, 0), \ ++ .res = DEFINE_RES_MEM(base, SZ_4K), \ ++ .irq = irqs, \ ++ .periphid = id, \ ++} ++ ++/* ++ * AHB devices are DMA capable, so set their DMA masks ++ */ ++#define AMBA_AHB_DEVICE(name, busid, id, base, irqs, data) \ ++struct amba_device name##_device = { \ ++ .dev = __AMBA_DEV(busid, data, ~0ULL), \ ++ .res = DEFINE_RES_MEM(base, SZ_4K), \ ++ .dma_mask = ~0ULL, \ ++ .irq = irqs, \ ++ .periphid = id, \ ++} ++ + #endif +diff --git a/include/linux/ata_platform.h b/include/linux/ata_platform.h +index 9a26c83..b38ab9c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch new file mode 100644 index 00000000..bb9d33c9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_audit.h.patch @@ -0,0 +1,30 @@ +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -129,6 +129,7 @@ + #define AUDIT_LAST_KERN_ANOM_MSG 1799 + #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ + #define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */ ++#define AUDIT_ANOM_LINK 1702 /* Suspicious use of file links */ + #define AUDIT_INTEGRITY_DATA 1800 /* Data integrity verification */ + #define AUDIT_INTEGRITY_METADATA 1801 /* Metadata integrity verification */ + #define AUDIT_INTEGRITY_STATUS 1802 /* Integrity enable status */ +@@ -611,6 +612,8 @@ extern void audit_log_d_path(struct audit_buffer *ab, + struct path *path); + extern void audit_log_key(struct audit_buffer *ab, + char *key); ++extern void audit_log_link_denied(const char *operation, ++ struct path *link); + extern void audit_log_lost(const char *message); + #ifdef CONFIG_SECURITY + extern void audit_log_secctx(struct audit_buffer *ab, u32 secid); +@@ -640,6 +643,7 @@ extern int audit_enabled; + #define audit_log_untrustedstring(a,s) do { ; } while (0) + #define audit_log_d_path(b, p, d) do { ; } while (0) + #define audit_log_key(b, k) do { ; } while (0) ++#define audit_log_link_denied(o, l) do { ; } while (0) + #define audit_log_secctx(b,s) do { ; } while (0) + #define audit_enabled 0 + #endif +diff --git a/include/linux/aufs_type.h b/include/linux/aufs_type.h +new file mode 100644 +index 0000000..2e829a4 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch new file mode 100644 index 00000000..708fdc2c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_bitops.h.patch @@ -0,0 +1,28 @@ +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -26,6 +26,23 @@ extern unsigned long __sw_hweight64(__u64 w); + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + ++/* same as for_each_set_bit() but use bit as value to start with */ ++#define for_each_set_bit_from(bit, addr, size) \ ++ for ((bit) = find_next_bit((addr), (size), (bit)); \ ++ (bit) < (size); \ ++ (bit) = find_next_bit((addr), (size), (bit) + 1)) ++ ++#define for_each_clear_bit(bit, addr, size) \ ++ for ((bit) = find_first_zero_bit((addr), (size)); \ ++ (bit) < (size); \ ++ (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) ++ ++/* same as for_each_clear_bit() but use bit as value to start with */ ++#define for_each_clear_bit_from(bit, addr, size) \ ++ for ((bit) = find_next_zero_bit((addr), (size), (bit)); \ ++ (bit) < (size); \ ++ (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) ++ + static __inline__ int get_bitmask_order(unsigned int count) + { + int order; +diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h +index fed3f3a..43d5858 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch new file mode 100644 index 00000000..56088086 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ceph_messenger.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/ceph/messenger.h ++++ b/include/linux/ceph/messenger.h +@@ -92,7 +92,11 @@ struct ceph_msg { + bool front_is_vmalloc; + bool more_to_follow; + bool needs_out_seq; ++#ifdef __GENKSYMS__ ++ int front_max; /* renamed */ ++#else + int front_alloc_len; ++#endif + unsigned long ack_stamp; /* tx: when we were acked */ + + struct ceph_msgpool *pool; +diff --git a/include/linux/connector.h b/include/linux/connector.h +index 3c9c54f..7638407 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch new file mode 100644 index 00000000..6302c284 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_connector.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/connector.h ++++ b/include/linux/connector.h +@@ -43,6 +43,7 @@ + #define CN_IDX_DRBD 0x8 + #define CN_VAL_DRBD 0x1 + #define CN_KVP_IDX 0x9 /* HyperV KVP */ ++#define CN_KVP_VAL 0x1 /* queries from the kernel */ + + #define CN_NETLINK_USERS 10 /* Highest index + 1 */ + +diff --git a/include/linux/cpu.h b/include/linux/cpu.h +index 9c3e071..ea07082 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch new file mode 100644 index 00000000..921f0fed --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_cpu.h.patch @@ -0,0 +1,63 @@ +--- a/include/linux/cpu.h ++++ b/include/linux/cpu.h +@@ -14,7 +14,7 @@ + #ifndef _LINUX_CPU_H_ + #define _LINUX_CPU_H_ + +-#include ++#include + #include + #include + #include +@@ -22,19 +22,19 @@ + struct cpu { + int node_id; /* The node which contains the CPU */ + int hotpluggable; /* creates sysfs control file if hotpluggable */ +- struct sys_device sysdev; ++ struct device dev; + }; + + extern int register_cpu(struct cpu *cpu, int num); +-extern struct sys_device *get_cpu_sysdev(unsigned cpu); ++extern struct device *get_cpu_device(unsigned cpu); + +-extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr); +-extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr); ++extern int cpu_add_dev_attr(struct device_attribute *attr); ++extern void cpu_remove_dev_attr(struct device_attribute *attr); + +-extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs); +-extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs); ++extern int cpu_add_dev_attr_group(struct attribute_group *attrs); ++extern void cpu_remove_dev_attr_group(struct attribute_group *attrs); + +-extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls); ++extern int sched_create_sysfs_power_savings_entries(struct device *dev); + + #ifdef CONFIG_HOTPLUG_CPU + extern void unregister_cpu(struct cpu *cpu); +@@ -43,6 +43,13 @@ extern ssize_t arch_cpu_release(const char *, size_t); + #endif + struct notifier_block; + ++#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env); ++extern ssize_t arch_print_cpu_modalias(struct device *dev, ++ struct device_attribute *attr, ++ char *bufptr); ++#endif ++ + /* + * CPU notifier priorities. + */ +@@ -161,7 +168,7 @@ static inline void cpu_maps_update_done(void) + } + + #endif /* CONFIG_SMP */ +-extern struct sysdev_class cpu_sysdev_class; ++extern struct bus_type cpu_subsys; + + #ifdef CONFIG_HOTPLUG_CPU + /* Stop CPUs going up and down. */ +diff --git a/include/linux/dcache.h b/include/linux/dcache.h +index 99374de..2307a30 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch new file mode 100644 index 00000000..3ad3131c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dcache.h.patch @@ -0,0 +1,36 @@ +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -133,15 +133,31 @@ struct dentry { + void *d_fsdata; /* fs-specific data */ + + struct list_head d_lru; /* LRU list */ ++#ifdef __GENKSYMS__ ++ /* ++ * bwh: The union changes here don't move anything other than ++ * d_rcu (which modules definitely should not touch). This is ++ * checked by dcache_abi_check(). ++ */ ++ union { ++#endif + struct list_head d_child; /* child of parent list */ ++#ifdef __GENKSYMS__ ++ struct rcu_head d_rcu; ++ } d_u; ++#endif + struct list_head d_subdirs; /* our children */ + /* + * d_alias and d_rcu can share memory + */ ++#ifndef __GENKSYMS__ + union { ++#endif + struct list_head d_alias; /* inode alias list */ ++#ifndef __GENKSYMS__ + struct rcu_head d_rcu; + } d_u; ++#endif + }; + + /* +diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h +index 6712ab6..fe51b99 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch new file mode 100644 index 00000000..3cdbc69f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_device-mapper.h.patch @@ -0,0 +1,15 @@ +--- a/include/linux/device-mapper.h ++++ b/include/linux/device-mapper.h +@@ -72,8 +72,8 @@ typedef void (*dm_postsuspend_fn) (struct dm_target *ti); + typedef int (*dm_preresume_fn) (struct dm_target *ti); + typedef void (*dm_resume_fn) (struct dm_target *ti); + +-typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, +- char *result, unsigned maxlen); ++typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, ++ char *result, unsigned int maxlen); + + typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); + +diff --git a/include/linux/device.h b/include/linux/device.h +index a31c5d0..34b5d6b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch new file mode 100644 index 00000000..4b4a171b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_device.h.patch @@ -0,0 +1,177 @@ +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -53,6 +53,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + * struct bus_type - The bus type of the device + * + * @name: The name of the bus. ++ * @dev_name: Used for subsystems to enumerate devices like ("foo%u", dev->id). ++ * @dev_root: Default device to use as the parent. + * @bus_attrs: Default attributes of the bus. + * @dev_attrs: Default attributes of the devices on the bus. + * @drv_attrs: Default attributes of the device drivers on the bus. +@@ -86,6 +88,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + */ + struct bus_type { + const char *name; ++ const char *dev_name; ++ struct device *dev_root; + struct bus_attribute *bus_attrs; + struct device_attribute *dev_attrs; + struct driver_attribute *drv_attrs; +@@ -106,12 +110,30 @@ struct bus_type { + struct subsys_private *p; + }; + +-extern int __must_check bus_register(struct bus_type *bus); ++/* This is a #define to keep the compiler from merging different ++ * instances of the __key variable */ ++#define bus_register(subsys) \ ++({ \ ++ static struct lock_class_key __key; \ ++ __bus_register(subsys, &__key); \ ++}) ++extern int __must_check __bus_register(struct bus_type *bus, ++ struct lock_class_key *key); + extern void bus_unregister(struct bus_type *bus); + + extern int __must_check bus_rescan_devices(struct bus_type *bus); + + /* iterator helpers for buses */ ++struct subsys_dev_iter { ++ struct klist_iter ki; ++ const struct device_type *type; ++}; ++void subsys_dev_iter_init(struct subsys_dev_iter *iter, ++ struct bus_type *subsys, ++ struct device *start, ++ const struct device_type *type); ++struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); ++void subsys_dev_iter_exit(struct subsys_dev_iter *iter); + + int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, + int (*fn)(struct device *dev, void *data)); +@@ -121,10 +143,10 @@ struct device *bus_find_device(struct bus_type *bus, struct device *start, + struct device *bus_find_device_by_name(struct bus_type *bus, + struct device *start, + const char *name); +- ++struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, ++ struct device *hint); + int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, + void *data, int (*fn)(struct device_driver *, void *)); +- + void bus_sort_breadthfirst(struct bus_type *bus, + int (*compare)(const struct device *a, + const struct device *b)); +@@ -256,6 +278,33 @@ struct device *driver_find_device(struct device_driver *drv, + int (*match)(struct device *dev, void *data)); + + /** ++ * struct subsys_interface - interfaces to device functions ++ * @name name of the device function ++ * @subsystem subsytem of the devices to attach to ++ * @node the list of functions registered at the subsystem ++ * @add device hookup to device function handler ++ * @remove device hookup to device function handler ++ * ++ * Simple interfaces attached to a subsystem. Multiple interfaces can ++ * attach to a subsystem and its devices. Unlike drivers, they do not ++ * exclusively claim or control devices. Interfaces usually represent ++ * a specific functionality of a subsystem/class of devices. ++ */ ++struct subsys_interface { ++ const char *name; ++ struct bus_type *subsys; ++ struct list_head node; ++ int (*add_dev)(struct device *dev, struct subsys_interface *sif); ++ int (*remove_dev)(struct device *dev, struct subsys_interface *sif); ++}; ++ ++int subsys_interface_register(struct subsys_interface *sif); ++void subsys_interface_unregister(struct subsys_interface *sif); ++ ++int subsys_system_register(struct bus_type *subsys, ++ const struct attribute_group **groups); ++ ++/** + * struct class - device classes + * @name: Name of the class. + * @owner: The module owner. +@@ -438,11 +487,37 @@ struct device_attribute { + const char *buf, size_t count); + }; + +-#define DEVICE_ATTR(_name, _mode, _show, _store) \ +-struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) ++struct dev_ext_attribute { ++ struct device_attribute attr; ++ void *var; ++}; ++ ++ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr, ++ char *buf); ++ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count); ++ssize_t device_show_int(struct device *dev, struct device_attribute *attr, ++ char *buf); ++ssize_t device_store_int(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count); + +-extern int __must_check device_create_file(struct device *device, +- const struct device_attribute *entry); ++#define DEVICE_ATTR(_name, _mode, _show, _store) \ ++ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) ++#define DEVICE_ATTR_RW(_name) \ ++ struct device_attribute dev_attr_##_name = __ATTR_RW(_name) ++#define DEVICE_ATTR_RO(_name) \ ++ struct device_attribute dev_attr_##_name = __ATTR_RO(_name) ++#define DEVICE_ATTR_WO(_name) \ ++ struct device_attribute dev_attr_##_name = __ATTR_WO(_name) ++#define DEVICE_ULONG_ATTR(_name, _mode, _var) \ ++ struct dev_ext_attribute dev_attr_##_name = \ ++ { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } ++#define DEVICE_INT_ATTR(_name, _mode, _var) \ ++ struct dev_ext_attribute dev_attr_##_name = \ ++ { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } ++ ++extern int device_create_file(struct device *device, ++ const struct device_attribute *entry); + extern void device_remove_file(struct device *dev, + const struct device_attribute *attr); + extern int __must_check device_create_bin_file(struct device *dev, +@@ -600,6 +675,7 @@ struct device { + struct device_node *of_node; /* associated device tree node */ + + dev_t devt; /* dev_t, creates the sysfs "dev" */ ++ u32 id; /* device instance */ + + spinlock_t devres_lock; + struct list_head devres_head; +@@ -929,4 +1005,25 @@ extern long sysfs_deprecated; + #define sysfs_deprecated 0 + #endif + ++/** ++ * module_driver() - Helper macro for drivers that don't do anything ++ * special in module init/exit. This eliminates a lot of boilerplate. ++ * Each module may only use this macro once, and calling it replaces ++ * module_init() and module_exit(). ++ * ++ * Use this macro to construct bus specific macros for registering ++ * drivers, and do not use it on its own. ++ */ ++#define module_driver(__driver, __register, __unregister) \ ++static int __init __driver##_init(void) \ ++{ \ ++ return __register(&(__driver)); \ ++} \ ++module_init(__driver##_init); \ ++static void __exit __driver##_exit(void) \ ++{ \ ++ __unregister(&(__driver)); \ ++} \ ++module_exit(__driver##_exit); ++ + #endif /* _DEVICE_H_ */ +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index e13117c..a018887 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch new file mode 100644 index 00000000..88706b07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dma-mapping.h.patch @@ -0,0 +1,25 @@ +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -89,6 +89,20 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask) + } + #endif + ++/* ++ * Set both the DMA mask and the coherent DMA mask to the same thing. ++ * Note that we don't check the return value from dma_set_coherent_mask() ++ * as the DMA API guarantees that the coherent DMA mask can be set to ++ * the same or smaller than the streaming DMA mask. ++ */ ++static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) ++{ ++ int rc = dma_set_mask(dev, mask); ++ if (rc == 0) ++ dma_set_coherent_mask(dev, mask); ++ return rc; ++} ++ + extern u64 dma_get_required_mask(struct device *dev); + + static inline unsigned int dma_get_max_seg_size(struct device *dev) +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 75f53f8..2ee20c5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch new file mode 100644 index 00000000..50d9568e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmaengine.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -530,6 +530,22 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( + return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); + } + ++static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_data_direction dir, unsigned long flags) ++{ ++ return chan->device->device_prep_slave_sg(chan, sgl, sg_len, ++ dir, flags); ++} ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_data_direction dir) ++{ ++ return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, ++ period_len, dir); ++} ++ + static inline int dmaengine_terminate_all(struct dma_chan *chan) + { + return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); +diff --git a/include/linux/dmi.h b/include/linux/dmi.h +index f156cca..f6feb54 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch new file mode 100644 index 00000000..53d74b93 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dmi.h.patch @@ -0,0 +1,20 @@ +--- a/include/linux/dmi.h ++++ b/include/linux/dmi.h +@@ -93,6 +93,14 @@ struct dmi_dev_onboard { + int devfn; + }; + ++/* ++ * bwh: These functions are renamed so that modules won't load on an ++ * older kernel version where setting the 'exact_match' flag would ++ * result in an array overrun. ++ */ ++#define dmi_check_system dmi_check_system_2 ++#define dmi_first_match dmi_first_match_2 ++ + extern int dmi_check_system(const struct dmi_system_id *list); + const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list); + extern const char * dmi_get_system_info(int field); +diff --git a/include/linux/dynamic_queue_limits.h b/include/linux/dynamic_queue_limits.h +new file mode 100644 +index 0000000..5621547 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch new file mode 100644 index 00000000..f2eab2c4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_dynamic_queue_limits.h.patch @@ -0,0 +1,103 @@ +--- /dev/null ++++ b/include/linux/dynamic_queue_limits.h +@@ -0,0 +1,97 @@ ++/* ++ * Dynamic queue limits (dql) - Definitions ++ * ++ * Copyright (c) 2011, Tom Herbert ++ * ++ * This header file contains the definitions for dynamic queue limits (dql). ++ * dql would be used in conjunction with a producer/consumer type queue ++ * (possibly a HW queue). Such a queue would have these general properties: ++ * ++ * 1) Objects are queued up to some limit specified as number of objects. ++ * 2) Periodically a completion process executes which retires consumed ++ * objects. ++ * 3) Starvation occurs when limit has been reached, all queued data has ++ * actually been consumed, but completion processing has not yet run ++ * so queuing new data is blocked. ++ * 4) Minimizing the amount of queued data is desirable. ++ * ++ * The goal of dql is to calculate the limit as the minimum number of objects ++ * needed to prevent starvation. ++ * ++ * The primary functions of dql are: ++ * dql_queued - called when objects are enqueued to record number of objects ++ * dql_avail - returns how many objects are available to be queued based ++ * on the object limit and how many objects are already enqueued ++ * dql_completed - called at completion time to indicate how many objects ++ * were retired from the queue ++ * ++ * The dql implementation does not implement any locking for the dql data ++ * structures, the higher layer should provide this. dql_queued should ++ * be serialized to prevent concurrent execution of the function; this ++ * is also true for dql_completed. However, dql_queued and dlq_completed can ++ * be executed concurrently (i.e. they can be protected by different locks). ++ */ ++ ++#ifndef _LINUX_DQL_H ++#define _LINUX_DQL_H ++ ++#ifdef __KERNEL__ ++ ++struct dql { ++ /* Fields accessed in enqueue path (dql_queued) */ ++ unsigned int num_queued; /* Total ever queued */ ++ unsigned int adj_limit; /* limit + num_completed */ ++ unsigned int last_obj_cnt; /* Count at last queuing */ ++ ++ /* Fields accessed only by completion path (dql_completed) */ ++ ++ unsigned int limit ____cacheline_aligned_in_smp; /* Current limit */ ++ unsigned int num_completed; /* Total ever completed */ ++ ++ unsigned int prev_ovlimit; /* Previous over limit */ ++ unsigned int prev_num_queued; /* Previous queue total */ ++ unsigned int prev_last_obj_cnt; /* Previous queuing cnt */ ++ ++ unsigned int lowest_slack; /* Lowest slack found */ ++ unsigned long slack_start_time; /* Time slacks seen */ ++ ++ /* Configuration */ ++ unsigned int max_limit; /* Max limit */ ++ unsigned int min_limit; /* Minimum limit */ ++ unsigned int slack_hold_time; /* Time to measure slack */ ++}; ++ ++/* Set some static maximums */ ++#define DQL_MAX_OBJECT (UINT_MAX / 16) ++#define DQL_MAX_LIMIT ((UINT_MAX / 2) - DQL_MAX_OBJECT) ++ ++/* ++ * Record number of objects queued. Assumes that caller has already checked ++ * availability in the queue with dql_avail. ++ */ ++static inline void dql_queued(struct dql *dql, unsigned int count) ++{ ++ BUG_ON(count > DQL_MAX_OBJECT); ++ ++ dql->num_queued += count; ++ dql->last_obj_cnt = count; ++} ++ ++/* Returns how many objects can be queued, < 0 indicates over limit. */ ++static inline int dql_avail(const struct dql *dql) ++{ ++ return dql->adj_limit - dql->num_queued; ++} ++ ++/* Record number of completed objects and recalculate the limit. */ ++void dql_completed(struct dql *dql, unsigned int count); ++ ++/* Reset dql state */ ++void dql_reset(struct dql *dql); ++ ++/* Initialize dql state */ ++int dql_init(struct dql *dql, unsigned hold_time); ++ ++#endif /* _KERNEL_ */ ++ ++#endif /* _LINUX_DQL_H */ +diff --git a/include/linux/early_dma_alloc.h b/include/linux/early_dma_alloc.h +new file mode 100644 +index 0000000..a6d87ec diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch new file mode 100644 index 00000000..1278658f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_early_dma_alloc.h.patch @@ -0,0 +1,42 @@ +--- /dev/null ++++ b/include/linux/early_dma_alloc.h +@@ -0,0 +1,36 @@ ++/* ++ * Early DMA Memory Allocator ++ * ++ * Copyright © 2013 Cumulus Networks, Inc. ++ * ++ * Author: Curt Brune ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#ifndef EARLY_DMA_ALLOC_H__ ++#define EARLY_DMA_ALLOC_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++extern int eda_init(void); ++extern int eda_dma_info_get(void** vaddr, uint32_t* paddr, uint32_t* size); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* EARLY_DMA_ALLOC_H__ */ +diff --git a/include/linux/eeprom_class.h b/include/linux/eeprom_class.h +new file mode 100644 +index 0000000..d21d350 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch new file mode 100644 index 00000000..f3968a44 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_eeprom_class.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/include/linux/eeprom_class.h +@@ -0,0 +1,79 @@ ++/* ++ * eeprom_class.h ++ * ++ * This file exports interface functions for the sysfs class "eeprom", ++ * for use by EEPROM drivers. ++ * ++ * Copyright (C) 2013 Cumulus Networks, Inc. ++ * Author: Curt Brune ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#ifndef EEPROM_CLASS_H__ ++#define EEPROM_CLASS_H__ ++ ++#include ++#include ++ ++/* ++ * Extra platform data used by the eeprom class ++ * ++ * An eeprom device can include this structure in its own platform ++ * data structure. ++ * ++ * A specific platform can set the values in this structure to values ++ * suitable for that platform. ++ * ++ */ ++struct eeprom_platform_data { ++ char *label; /* device label to use with the eeprom class */ ++}; ++ ++/* ++ * EEPROM device structure ++ * ++ * This structure is used by the eeprom_class driver to manage the ++ * state of the class device. ++ * ++ */ ++struct eeprom_device { ++ struct device *dev; ++ struct eeprom_platform_data *data; ++}; ++ ++#if defined(CONFIG_EEPROM_CLASS) || defined (CONFIG_EEPROM_CLASS_MODULE) ++ ++extern struct eeprom_device * ++eeprom_device_register(struct device *dev, struct eeprom_platform_data *data); ++extern void ++eeprom_device_unregister(struct eeprom_device *eeprom_dev); ++ ++#else ++ ++static inline struct eeprom_device * ++eeprom_device_register(struct device *dev, char *label) ++{ ++ return NULL; ++} ++ ++static inline void ++eeprom_device_unregister(struct eeprom_device *eeprom_dev) ++{ ++} ++ ++#endif ++ ++#endif /* EEPROM_CLASS_H__ */ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 88c953d..e3f80ba 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch new file mode 100644 index 00000000..09400652 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_efi.h.patch @@ -0,0 +1,193 @@ +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -114,6 +114,14 @@ typedef struct { + u32 imagesize; + } efi_capsule_header_t; + ++/* ++ * Allocation types for calls to boottime->allocate_pages. ++ */ ++#define EFI_ALLOCATE_ANY_PAGES 0 ++#define EFI_ALLOCATE_MAX_ADDRESS 1 ++#define EFI_ALLOCATE_ADDRESS 2 ++#define EFI_MAX_ALLOCATE_TYPE 3 ++ + typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); + + /* +@@ -144,6 +152,57 @@ typedef struct { + } efi_time_cap_t; + + /* ++ * EFI Boot Services table ++ */ ++typedef struct { ++ efi_table_hdr_t hdr; ++ void *raise_tpl; ++ void *restore_tpl; ++ void *allocate_pages; ++ void *free_pages; ++ void *get_memory_map; ++ void *allocate_pool; ++ void *free_pool; ++ void *create_event; ++ void *set_timer; ++ void *wait_for_event; ++ void *signal_event; ++ void *close_event; ++ void *check_event; ++ void *install_protocol_interface; ++ void *reinstall_protocol_interface; ++ void *uninstall_protocol_interface; ++ void *handle_protocol; ++ void *__reserved; ++ void *register_protocol_notify; ++ void *locate_handle; ++ void *locate_device_path; ++ void *install_configuration_table; ++ void *load_image; ++ void *start_image; ++ void *exit; ++ void *unload_image; ++ void *exit_boot_services; ++ void *get_next_monotonic_count; ++ void *stall; ++ void *set_watchdog_timer; ++ void *connect_controller; ++ void *disconnect_controller; ++ void *open_protocol; ++ void *close_protocol; ++ void *open_protocol_information; ++ void *protocols_per_handle; ++ void *locate_handle_buffer; ++ void *locate_protocol; ++ void *install_multiple_protocol_interfaces; ++ void *uninstall_multiple_protocol_interfaces; ++ void *calculate_crc32; ++ void *copy_mem; ++ void *set_mem; ++ void *create_event_ex; ++} efi_boot_services_t; ++ ++/* + * Types and defines for EFI ResetSystem + */ + #define EFI_RESET_COLD 0 +@@ -242,6 +301,24 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si + #define LINUX_EFI_CRASH_GUID \ + EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 ) + ++#define LOADED_IMAGE_PROTOCOL_GUID \ ++ EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) ++ ++#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ ++ EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a ) ++ ++#define EFI_UGA_PROTOCOL_GUID \ ++ EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 ) ++ ++#define EFI_PCI_IO_PROTOCOL_GUID \ ++ EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a ) ++ ++#define EFI_FILE_INFO_ID \ ++ EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) ++ ++#define EFI_FILE_SYSTEM_GUID \ ++ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) ++ + typedef struct { + efi_guid_t guid; + unsigned long table; +@@ -267,7 +344,7 @@ typedef struct { + unsigned long stderr_handle; + unsigned long stderr; + efi_runtime_services_t *runtime; +- unsigned long boottime; ++ efi_boot_services_t *boottime; + unsigned long nr_tables; + unsigned long tables; + } efi_system_table_t; +@@ -281,6 +358,56 @@ struct efi_memory_map { + unsigned long desc_size; + }; + ++typedef struct { ++ u32 revision; ++ void *parent_handle; ++ efi_system_table_t *system_table; ++ void *device_handle; ++ void *file_path; ++ void *reserved; ++ u32 load_options_size; ++ void *load_options; ++ void *image_base; ++ __aligned_u64 image_size; ++ unsigned int image_code_type; ++ unsigned int image_data_type; ++ unsigned long unload; ++} efi_loaded_image_t; ++ ++typedef struct { ++ u64 revision; ++ void *open_volume; ++} efi_file_io_interface_t; ++ ++typedef struct { ++ u64 size; ++ u64 file_size; ++ u64 phys_size; ++ efi_time_t create_time; ++ efi_time_t last_access_time; ++ efi_time_t modification_time; ++ __aligned_u64 attribute; ++ efi_char16_t filename[1]; ++} efi_file_info_t; ++ ++typedef struct { ++ u64 revision; ++ void *open; ++ void *close; ++ void *delete; ++ void *read; ++ void *write; ++ void *get_position; ++ void *set_position; ++ void *get_info; ++ void *set_info; ++ void *flush; ++} efi_file_handle_t; ++ ++#define EFI_FILE_MODE_READ 0x0000000000000001 ++#define EFI_FILE_MODE_WRITE 0x0000000000000002 ++#define EFI_FILE_MODE_CREATE 0x8000000000000000 ++ + #define EFI_INVALID_TABLE_ADDR (~0UL) + + /* +@@ -390,7 +517,9 @@ extern int __init efi_setup_pcdp_console(char *); + + #ifdef CONFIG_EFI + # ifdef CONFIG_X86 +-extern int efi_enabled(int facility); ++extern int efi_enabled; /* ABI compat; please use efi_enabled() instead */ ++extern int efi_enabled_facility(int facility); ++#define efi_enabled(f) efi_enabled_facility(f) + # else + static inline int efi_enabled(int facility) + { +@@ -423,6 +552,13 @@ static inline int efi_enabled(int facility) + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_APPEND_WRITE) + /* ++ * The type of search to perform when calling boottime->locate_handle ++ */ ++#define EFI_LOCATE_ALL_HANDLES 0 ++#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 ++#define EFI_LOCATE_BY_PROTOCOL 2 ++ ++/* + * EFI Device Path information + */ + #define EFI_DEV_HW 0x01 +diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h +index 05955cf..ae9c1f6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch new file mode 100644 index 00000000..dff10b32 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ethtool.h.patch @@ -0,0 +1,61 @@ +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -118,6 +118,24 @@ struct ethtool_eeprom { + }; + + /** ++ * struct ethtool_modinfo - plugin module eeprom information ++ * @cmd: %ETHTOOL_GMODULEINFO ++ * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx ++ * @eeprom_len: Length of the eeprom ++ * ++ * This structure is used to return the information to ++ * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. ++ * The type code indicates the eeprom data format ++ */ ++struct ethtool_modinfo { ++ __u32 cmd; ++ __u32 type; ++ __u32 eeprom_len; ++ __u32 eeprom_nums; ++ __u32 reserved[7]; ++}; ++ ++/** + * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates + * @cmd: ETHTOOL_{G,S}COALESCE + * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after +@@ -930,6 +948,8 @@ struct ethtool_ops { + int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); + void (*get_ethtool_stats)(struct net_device *, + struct ethtool_stats *, u64 *); ++ void (*get_ethtool_stats_clear)(struct net_device *, ++ struct ethtool_stats *, u64 *); + int (*begin)(struct net_device *); + void (*complete)(struct net_device *); + u32 (*get_ufo)(struct net_device *); +@@ -956,6 +976,10 @@ struct ethtool_ops { + int (*get_dump_data)(struct net_device *, + struct ethtool_dump *, void *); + int (*set_dump)(struct net_device *, struct ethtool_dump *); ++ int (*get_module_info)(struct net_device *, ++ struct ethtool_modinfo *); ++ int (*get_module_eeprom)(struct net_device *, ++ struct ethtool_eeprom *, u8 *); + + }; + #endif /* __KERNEL__ */ +@@ -1030,6 +1054,10 @@ struct ethtool_ops { + #define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ + #define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ + #define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ ++#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ ++#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ ++ ++#define ETHTOOL_GSTATS_CLEAR 0x1000001d /* get NIC-specific statistics and clear */ + + /* compatibility with older code */ + #define SPARC_ETH_GSET ETHTOOL_GSET +diff --git a/include/linux/fmd/Kbuild b/include/linux/fmd/Kbuild +new file mode 100644 +index 0000000..56a2040 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch new file mode 100644 index 00000000..d6b63fe4 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ftrace_event.h.patch @@ -0,0 +1,23 @@ +--- a/include/linux/ftrace_event.h ++++ b/include/linux/ftrace_event.h +@@ -71,8 +71,6 @@ struct trace_iterator { + /* trace_seq for __print_flags() and __print_symbolic() etc. */ + struct trace_seq tmp_seq; + +- cpumask_var_t started; +- + /* The below is zeroed out in pipe_read */ + struct trace_seq seq; + struct trace_entry *ent; +@@ -85,7 +83,7 @@ struct trace_iterator { + loff_t pos; + long idx; + +- /* All new field here will be zeroed out in pipe_read */ ++ cpumask_var_t started; + }; + + +diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h +new file mode 100644 +index 0000000..227c624 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch new file mode 100644 index 00000000..adef322b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_hashtable.h.patch @@ -0,0 +1,197 @@ +--- /dev/null ++++ b/include/linux/hashtable.h +@@ -0,0 +1,192 @@ ++/* ++ * Statically sized hash table implementation ++ * (C) 2012 Sasha Levin ++ */ ++ ++#ifndef _LINUX_HASHTABLE_H ++#define _LINUX_HASHTABLE_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define DEFINE_HASHTABLE(name, bits) \ ++ struct hlist_head name[1 << (bits)] = \ ++ { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } ++ ++#define DECLARE_HASHTABLE(name, bits) \ ++ struct hlist_head name[1 << (bits)] ++ ++#define HASH_SIZE(name) (ARRAY_SIZE(name)) ++#define HASH_BITS(name) ilog2(HASH_SIZE(name)) ++ ++/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */ ++#define hash_min(val, bits) \ ++ (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)) ++ ++static inline void __hash_init(struct hlist_head *ht, unsigned int sz) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < sz; i++) ++ INIT_HLIST_HEAD(&ht[i]); ++} ++ ++/** ++ * hash_init - initialize a hash table ++ * @hashtable: hashtable to be initialized ++ * ++ * Calculates the size of the hashtable from the given parameter, otherwise ++ * same as hash_init_size. ++ * ++ * This has to be a macro since HASH_BITS() will not work on pointers since ++ * it calculates the size during preprocessing. ++ */ ++#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable)) ++ ++/** ++ * hash_add - add an object to a hashtable ++ * @hashtable: hashtable to add to ++ * @node: the &struct hlist_node of the object to be added ++ * @key: the key of the object to be added ++ */ ++#define hash_add(hashtable, node, key) \ ++ hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) ++ ++/** ++ * hash_add_rcu - add an object to a rcu enabled hashtable ++ * @hashtable: hashtable to add to ++ * @node: the &struct hlist_node of the object to be added ++ * @key: the key of the object to be added ++ */ ++#define hash_add_rcu(hashtable, node, key) \ ++ hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) ++ ++/** ++ * hash_hashed - check whether an object is in any hashtable ++ * @node: the &struct hlist_node of the object to be checked ++ */ ++static inline bool hash_hashed(struct hlist_node *node) ++{ ++ return !hlist_unhashed(node); ++} ++ ++static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < sz; i++) ++ if (!hlist_empty(&ht[i])) ++ return false; ++ ++ return true; ++} ++ ++/** ++ * hash_empty - check whether a hashtable is empty ++ * @hashtable: hashtable to check ++ * ++ * This has to be a macro since HASH_BITS() will not work on pointers since ++ * it calculates the size during preprocessing. ++ */ ++#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable)) ++ ++/** ++ * hash_del - remove an object from a hashtable ++ * @node: &struct hlist_node of the object to remove ++ */ ++static inline void hash_del(struct hlist_node *node) ++{ ++ hlist_del_init(node); ++} ++ ++/** ++ * hash_del_rcu - remove an object from a rcu enabled hashtable ++ * @node: &struct hlist_node of the object to remove ++ */ ++static inline void hash_del_rcu(struct hlist_node *node) ++{ ++ hlist_del_init_rcu(node); ++} ++ ++/** ++ * hash_for_each - iterate over a hashtable ++ * @name: hashtable to iterate ++ * @bkt: integer to use as bucket loop cursor ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @obj: the type * to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ */ ++#define hash_for_each(name, bkt, node, obj, member) \ ++ for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ ++ hlist_for_each_entry(obj, node, &name[bkt], member) ++ ++/** ++ * hash_for_each_rcu - iterate over a rcu enabled hashtable ++ * @name: hashtable to iterate ++ * @bkt: integer to use as bucket loop cursor ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @obj: the type * to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ */ ++#define hash_for_each_rcu(name, bkt, node, obj, member) \ ++ for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ ++ hlist_for_each_entry_rcu(obj, node, &name[bkt], member) ++ ++/** ++ * hash_for_each_safe - iterate over a hashtable safe against removal of ++ * hash entry ++ * @name: hashtable to iterate ++ * @bkt: integer to use as bucket loop cursor ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @tmp: a &struct used for temporary storage ++ * @obj: the type * to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ */ ++#define hash_for_each_safe(name, bkt, node, tmp, obj, member) \ ++ for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ ++ hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member) ++ ++/** ++ * hash_for_each_possible - iterate over all possible objects hashing to the ++ * same bucket ++ * @name: hashtable to iterate ++ * @obj: the type * to use as a loop cursor for each entry ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ * @key: the key of the objects to iterate over ++ */ ++#define hash_for_each_possible(name, obj, node, member, key) \ ++ hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member) ++ ++/** ++ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the ++ * same bucket in an rcu enabled hashtable ++ * in a rcu enabled hashtable ++ * @name: hashtable to iterate ++ * @obj: the type * to use as a loop cursor for each entry ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @member: the name of the hlist_node within the struct ++ * @key: the key of the objects to iterate over ++ */ ++#define hash_for_each_possible_rcu(name, obj, node, member, key) \ ++ hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member) ++ ++/** ++ * hash_for_each_possible_safe - iterate over all possible objects hashing to the ++ * same bucket safe against removals ++ * @name: hashtable to iterate ++ * @obj: the type * to use as a loop cursor for each entry ++ * @node: the &struct list_head to use as a loop cursor for each entry ++ * @tmp: a &struct used for temporary storage ++ * @member: the name of the hlist_node within the struct ++ * @key: the key of the objects to iterate over ++ */ ++#define hash_for_each_possible_safe(name, obj, node, tmp, member, key) \ ++ hlist_for_each_entry_safe(obj, node, tmp, \ ++ &name[hash_min(key, HASH_BITS(name))], member) ++ ++ ++#endif +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 19fe719..0d07520 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch new file mode 100644 index 00000000..ed32ebdd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux-gpio.h.patch @@ -0,0 +1,48 @@ +--- /dev/null ++++ b/include/linux/i2c-mux-gpio.h +@@ -0,0 +1,43 @@ ++/* ++ * i2c-mux-gpio interface to platform code ++ * ++ * Peter Korsgaard ++ * ++ * 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. ++ */ ++ ++#ifndef _LINUX_I2C_MUX_GPIO_H ++#define _LINUX_I2C_MUX_GPIO_H ++ ++/* MUX has no specific idle mode */ ++#define I2C_MUX_GPIO_NO_IDLE ((unsigned)-1) ++ ++/** ++ * struct i2c_mux_gpio_platform_data - Platform-dependent data for i2c-mux-gpio ++ * @parent: Parent I2C bus adapter number ++ * @base_nr: Base I2C bus number to number adapters from or zero for dynamic ++ * @values: Array of bitmasks of GPIO settings (low/high) for each ++ * position ++ * @n_values: Number of multiplexer positions (busses to instantiate) ++ * @classes: Optional I2C auto-detection classes ++ * @gpio_chip: Optional GPIO chip name; if set, GPIO pin numbers are given ++ * relative to the base GPIO number of that chip ++ * @gpios: Array of GPIO numbers used to control MUX ++ * @n_gpios: Number of GPIOs used to control MUX ++ * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used ++ */ ++struct i2c_mux_gpio_platform_data { ++ int parent; ++ int base_nr; ++ const unsigned *values; ++ int n_values; ++ const unsigned *classes; ++ char *gpio_chip; ++ const unsigned *gpios; ++ int n_gpios; ++ unsigned idle; ++}; ++ ++#endif /* _LINUX_I2C_MUX_GPIO_H */ +diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h +index 34536ef..260ca6a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch new file mode 100644 index 00000000..9fc0acdc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c-mux.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/i2c-mux.h ++++ b/include/linux/i2c-mux.h +@@ -33,7 +33,8 @@ + * mux control. + */ + struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, +- void *mux_dev, u32 force_nr, u32 chan_id, ++ struct device *mux_dev, ++ void *mux_priv, u32 force_nr, u32 chan_id, + int (*select) (struct i2c_adapter *, + void *mux_dev, u32 chan_id), + int (*deselect) (struct i2c_adapter *, +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index 07d103a..8e25a91 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch new file mode 100644 index 00000000..1d2bdba9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c.h.patch @@ -0,0 +1,24 @@ +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -482,6 +482,19 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) + { + return adap->nr; + } ++ ++/** ++ * module_i2c_driver() - Helper macro for registering a I2C driver ++ * @__i2c_driver: i2c_driver struct ++ * ++ * Helper macro for I2C drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_i2c_driver(__i2c_driver) \ ++ module_driver(__i2c_driver, i2c_add_driver, \ ++ i2c_del_driver) ++ + #endif /* I2C */ + #endif /* __KERNEL__ */ + +diff --git a/include/linux/i2c/at24.h b/include/linux/i2c/at24.h +index 8ace930..3bdb466 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch new file mode 100644 index 00000000..baf04915 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_at24.h.patch @@ -0,0 +1,24 @@ +--- a/include/linux/i2c/at24.h ++++ b/include/linux/i2c/at24.h +@@ -3,6 +3,7 @@ + + #include + #include ++#include + + /* + * As seen through Linux I2C, differences between the most common types of I2C +@@ -24,9 +25,11 @@ struct at24_platform_data { + #define AT24_FLAG_READONLY 0x40 /* sysfs-entry will be read-only */ + #define AT24_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */ + #define AT24_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */ ++#define AT24_FLAG_DISABLE_I2CBLOCK 0x08 /*disable smbus i2c block access */ + + void (*setup)(struct memory_accessor *, void *context); + void *context; ++ struct eeprom_platform_data *eeprom_data; /* extra data for the eeprom_class */ + }; + + #endif /* _LINUX_AT24_H */ +diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h +index 139ba52..2a69244 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch new file mode 100644 index 00000000..1ee3f606 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_pca953x.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/i2c/pca953x.h ++++ b/include/linux/i2c/pca953x.h +@@ -11,7 +11,7 @@ struct pca953x_platform_data { + unsigned gpio_base; + + /* initial polarity inversion setting */ +- uint16_t invert; ++ uint32_t invert; + + /* interrupt base */ + int irq_base; +diff --git a/include/linux/i2c/quanta-i2cmux.h b/include/linux/i2c/quanta-i2cmux.h +new file mode 100644 +index 0000000..042dcd2 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch new file mode 100644 index 00000000..2a8a4506 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_i2c_sff-8436.h.patch @@ -0,0 +1,38 @@ +--- /dev/null ++++ b/include/linux/i2c/sff-8436.h +@@ -0,0 +1,33 @@ ++#ifndef _LINUX_SFF_8436_H ++#define _LINUX_SFF_8436_H ++ ++#include ++#include ++#include ++ ++/* ++ * As seen through Linux I2C, differences between the most common types of I2C ++ * memory include: ++ * - How much memory is available (usually specified in bit)? ++ * - What write page size does it support? ++ * - Special flags (read_only, world readable...)? ++ * ++ * If you set up a custom eeprom type, please double-check the parameters. ++ * Especially page_size needs extra care, as you risk data loss if your value ++ * is bigger than what the chip actually supports! ++ */ ++ ++struct sff_8436_platform_data { ++ u32 byte_len; /* size (sum of all addr) */ ++ u16 page_size; /* for writes */ ++ u8 flags; ++#define SFF_8436_FLAG_READONLY 0x40 /* sysfs-entry will be read-only */ ++#define SFF_8436_FLAG_IRUGO 0x20 /* sysfs-entry will be world-readable */ ++#define SFF_8436_FLAG_TAKE8ADDR 0x10 /* take always 8 addresses (24c00) */ ++ ++ void (*setup)(struct memory_accessor *, void *context); ++ void *context; ++ struct eeprom_platform_data *eeprom_data; /* extra data for the eeprom_class */ ++}; ++ ++#endif /* _LINUX_SFF_8436_H */ +diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h +index a17edda..13f3ed0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch new file mode 100644 index 00000000..4401a0d9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_bridge.h.patch @@ -0,0 +1,132 @@ +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -14,6 +14,7 @@ + #define _LINUX_IF_BRIDGE_H + + #include ++#include + + #define SYSFS_BRIDGE_ATTR "bridge" + #define SYSFS_BRIDGE_FDB "brforward" +@@ -94,9 +95,118 @@ struct __fdb_entry { + __u32 ageing_timer_value; + __u8 port_hi; + __u8 pad0; +- __u16 unused; ++ __u16 vlan; + }; + ++/* Bridge Flags */ ++#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ ++#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ ++ ++#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ ++#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ ++ ++/* Bridge management nested attributes ++ * [IFLA_AF_SPEC] = { ++ * [IFLA_BRIDGE_FLAGS] ++ * [IFLA_BRIDGE_MODE] ++ * [IFLA_BRIDGE_VLAN_INFO] ++ * } ++ */ ++enum { ++ IFLA_BRIDGE_FLAGS, ++ IFLA_BRIDGE_MODE, ++ IFLA_BRIDGE_VLAN_INFO, ++ __IFLA_BRIDGE_MAX, ++}; ++#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) ++ ++#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */ ++#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */ ++#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ ++ ++struct bridge_vlan_info { ++ __u16 flags; ++ __u16 vid; ++ __u16 vid_end; ++}; ++ ++/* Bridge multicast database attributes ++ * [MDBA_MDB] = { ++ * [MDBA_MDB_ENTRY] = { ++ * [MDBA_MDB_ENTRY_INFO] ++ * } ++ * } ++ * [MDBA_ROUTER] = { ++ * [MDBA_ROUTER_PORT] ++ * } ++ */ ++enum { ++ MDBA_UNSPEC, ++ MDBA_MDB, ++ MDBA_ROUTER, ++ __MDBA_MAX, ++}; ++#define MDBA_MAX (__MDBA_MAX - 1) ++ ++enum { ++ MDBA_MDB_UNSPEC, ++ MDBA_MDB_ENTRY, ++ __MDBA_MDB_MAX, ++}; ++#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) ++ ++enum { ++ MDBA_MDB_ENTRY_UNSPEC, ++ MDBA_MDB_ENTRY_INFO, ++ __MDBA_MDB_ENTRY_MAX, ++}; ++#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) ++ ++enum { ++ MDBA_ROUTER_UNSPEC, ++ MDBA_ROUTER_PORT, ++ __MDBA_ROUTER_MAX, ++}; ++#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) ++ ++struct br_port_msg { ++ __u8 family; ++ __u16 vlan; ++ __u32 ifindex; ++}; ++ ++struct br_mdb_entry { ++ __u32 ifindex; ++#define MDB_TEMPORARY 0 ++#define MDB_PERMANENT 1 ++ __u8 state; ++ struct { ++ union { ++ __be32 ip4; ++ struct in6_addr ip6; ++ } u; ++ __be16 proto; ++ __be16 vlan_id; ++ } addr; ++ __u32 timer; ++}; ++ ++struct br_mdb_rtr_entry { ++ __u32 ifindex; ++ __u32 timer; ++#define MDB_RTR_TEMPORARY 0 ++#define MDB_RTR_PERMANENT 1 ++ __u8 state; ++}; ++ ++enum { ++ MDBA_SET_ENTRY_UNSPEC, ++ MDBA_SET_ENTRY, ++ __MDBA_SET_ENTRY_MAX, ++}; ++#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) ++ ++ + #ifdef __KERNEL__ + + #include +diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h +index e473003..2d21664 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch new file mode 100644 index 00000000..86bc35f6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_ether.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/if_ether.h ++++ b/include/linux/if_ether.h +@@ -91,6 +91,9 @@ + #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ + #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ + ++#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value ++ * then the frame is Ethernet II. Else it is 802.3 */ ++ + /* + * Non DIX types. Won't clash for 1500 types. + */ +diff --git a/include/linux/if_link.h b/include/linux/if_link.h +index 4b24ff4..eb0b75d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch new file mode 100644 index 00000000..3ae02294 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_link.h.patch @@ -0,0 +1,210 @@ +--- a/include/linux/if_link.h ++++ b/include/linux/if_link.h +@@ -137,7 +137,20 @@ enum { + IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ + IFLA_NET_NS_FD, ++#ifndef __GENKSYMS__ + IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ ++#endif ++ IFLA_PROMISCUITY, /* not supported */ ++#define IFLA_PROMISCUITY IFLA_PROMISCUITY ++ IFLA_NUM_TX_QUEUES, /* not supported */ ++ IFLA_NUM_RX_QUEUES, /* not supported */ ++ IFLA_CARRIER, /* not supported */ ++ IFLA_PHYS_PORT_ID, /* not supported */ ++ IFLA_CARRIER_CHANGES, ++ IFLA_PHYS_SWITCH_ID, /* not supported */ ++ IFLA_LINK_NETNSID, /* not supported */ ++ IFLA_PHYS_PORT_NAME, /* not supported */ ++ IFLA_PROTO_DOWN, + __IFLA_MAX + }; + +@@ -201,6 +214,44 @@ enum { + + #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + ++/* Bridge section */ ++/* CL note: ageing_time, stp_state and priority are not supported */ ++enum { ++ IFLA_BR_UNSPEC, ++ IFLA_BR_FORWARD_DELAY, ++ IFLA_BR_HELLO_TIME, ++ IFLA_BR_MAX_AGE, ++ IFLA_BR_AGEING_TIME, ++ IFLA_BR_STP_STATE, ++ IFLA_BR_PRIORITY, ++ IFLA_BR_VLAN_FILTERING, ++ __IFLA_BR_MAX, ++}; ++ ++#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) ++ ++enum { ++ BRIDGE_MODE_UNSPEC, ++ BRIDGE_MODE_HAIRPIN, ++}; ++ ++enum { ++ IFLA_BRPORT_UNSPEC, ++ IFLA_BRPORT_STATE, /* Spanning tree state */ ++ IFLA_BRPORT_PRIORITY, /* " priority */ ++ IFLA_BRPORT_COST, /* " cost */ ++ IFLA_BRPORT_MODE, /* mode (hairpin) */ ++ IFLA_BRPORT_GUARD, /* bpdu guard */ ++ IFLA_BRPORT_PROTECT, /* root port protection */ ++ IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ ++ IFLA_BRPORT_LEARNING, /* mac learning */ ++ IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ ++ IFLA_BRPORT_PEER_LINK = 253, /* MLAG peer link */ ++ IFLA_BRPORT_DUAL_LINK, /* MLAG Dual Connected link */ ++ __IFLA_BRPORT_MAX ++}; ++#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) ++ + struct ifla_cacheinfo { + __u32 max_reasm_len; + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ +@@ -213,6 +264,8 @@ enum { + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, ++ IFLA_INFO_SLAVE_KIND, ++ IFLA_INFO_SLAVE_DATA, + __IFLA_INFO_MAX, + }; + +@@ -226,6 +279,7 @@ enum { + IFLA_VLAN_FLAGS, + IFLA_VLAN_EGRESS_QOS, + IFLA_VLAN_INGRESS_QOS, ++ IFLA_VLAN_PROTOCOL, + __IFLA_VLAN_MAX, + }; + +@@ -265,6 +319,122 @@ enum macvlan_mode { + MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ + }; + ++/* VXLAN section */ ++enum { ++ IFLA_VXLAN_UNSPEC, ++ IFLA_VXLAN_ID, ++ IFLA_VXLAN_GROUP, ++ IFLA_VXLAN_LINK, ++ IFLA_VXLAN_LOCAL, ++ IFLA_VXLAN_TTL, ++ IFLA_VXLAN_TOS, ++ IFLA_VXLAN_LEARNING, ++ IFLA_VXLAN_AGEING, ++ IFLA_VXLAN_LIMIT, ++ IFLA_VXLAN_PORT_RANGE, ++ IFLA_VXLAN_PROXY, ++ IFLA_VXLAN_RSC, ++ IFLA_VXLAN_L2MISS, ++ IFLA_VXLAN_L3MISS, ++ IFLA_VXLAN_PORT, /* destination port */ ++ IFLA_VXLAN_GROUP6, ++ IFLA_VXLAN_LOCAL6, ++ IFLA_VXLAN_UDP_CSUM, ++ IFLA_VXLAN_UDP_ZERO_CSUM6_TX, ++ IFLA_VXLAN_UDP_ZERO_CSUM6_RX, ++ IFLA_VXLAN_REMCSUM_TX, ++ IFLA_VXLAN_REMCSUM_RX, ++ IFLA_VXLAN_GBP, ++ IFLA_VXLAN_REMCSUM_NOPARTIAL, ++ IFLA_VXLAN_REPLICATION_NODE = 253, ++ IFLA_VXLAN_REPLICATION_TYPE, ++ __IFLA_VXLAN_MAX ++}; ++#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) ++ ++struct ifla_vxlan_port_range { ++ __be16 low; ++ __be16 high; ++}; ++ ++#define MAX_VXLAN_REPLICATION_NODE_ADDRS 64 ++struct ifla_vxlan_repl_node_addrs { ++ __u32 addrs[MAX_VXLAN_REPLICATION_NODE_ADDRS]; ++}; ++ ++enum { ++ VXLAN_REPLICATION_NONE = 0, ++ VXLAN_REPLICATION_SERVICE_NODE, /* service node based replication */ ++ VXLAN_REPLICATION_SELF, /* self or head-end replication */ ++}; ++ ++/* Bonding section */ ++ ++enum { ++ IFLA_BOND_UNSPEC, ++ IFLA_BOND_MODE, ++ IFLA_BOND_ACTIVE_SLAVE, ++ IFLA_BOND_MIIMON, ++ IFLA_BOND_UPDELAY, ++ IFLA_BOND_DOWNDELAY, ++ IFLA_BOND_USE_CARRIER, ++ IFLA_BOND_ARP_INTERVAL, ++ IFLA_BOND_ARP_IP_TARGET, ++ IFLA_BOND_ARP_VALIDATE, ++ IFLA_BOND_ARP_ALL_TARGETS, ++ IFLA_BOND_PRIMARY, ++ IFLA_BOND_PRIMARY_RESELECT, ++ IFLA_BOND_FAIL_OVER_MAC, ++ IFLA_BOND_XMIT_HASH_POLICY, ++ IFLA_BOND_RESEND_IGMP, ++ IFLA_BOND_NUM_PEER_NOTIF, ++ IFLA_BOND_ALL_SLAVES_ACTIVE, ++ IFLA_BOND_MIN_LINKS, ++ IFLA_BOND_LP_INTERVAL, ++ IFLA_BOND_PACKETS_PER_SLAVE, ++ IFLA_BOND_AD_LACP_RATE, ++ IFLA_BOND_AD_SELECT, ++ IFLA_BOND_AD_INFO, ++ ++ IFLA_BOND_CL_START = 100, ++ IFLA_BOND_CL_LACP_BYPASS_ALLOW = IFLA_BOND_CL_START, ++ IFLA_BOND_CL_LACP_BYPASS_ACTIVE, ++ IFLA_BOND_CL_LACP_BYPASS_PERIOD, ++ IFLA_BOND_CL_CLAG_ENABLE, ++ IFLA_BOND_CL_LACP_BYPASS_ALL_ACTIVE, ++ __IFLA_BOND_MAX, ++}; ++ ++#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) ++ ++enum { ++ IFLA_BOND_AD_INFO_UNSPEC, ++ IFLA_BOND_AD_INFO_AGGREGATOR, ++ IFLA_BOND_AD_INFO_NUM_PORTS, ++ IFLA_BOND_AD_INFO_ACTOR_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_MAC, ++ __IFLA_BOND_AD_INFO_MAX, ++}; ++ ++#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) ++ ++enum { ++ IFLA_BOND_SLAVE_UNSPEC, ++ IFLA_BOND_SLAVE_STATE, ++ IFLA_BOND_SLAVE_MII_STATUS, ++ IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, ++ IFLA_BOND_SLAVE_PERM_HWADDR, ++ IFLA_BOND_SLAVE_QUEUE_ID, ++ IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, ++ ++ IFLA_BOND_SLAVE_CL_START = 50, ++ IFLA_BOND_SLAVE_CL_LACP_BYPASS_PRIO = IFLA_BOND_SLAVE_CL_START, ++ __IFLA_BOND_SLAVE_MAX, ++}; ++ ++#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) ++ + /* SR-IOV virtual function management section */ + + enum { +diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h +index 06b1829..6dd06d3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch new file mode 100644 index 00000000..dd36db07 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_if_tun.h.patch @@ -0,0 +1,40 @@ +--- a/include/linux/if_tun.h ++++ b/include/linux/if_tun.h +@@ -34,6 +34,7 @@ + #define TUN_ONE_QUEUE 0x0080 + #define TUN_PERSIST 0x0100 + #define TUN_VNET_HDR 0x0200 ++#define TUN_SET_CARRIER 0x0400 + + /* Ioctl defines */ + #define TUNSETNOCSUM _IOW('T', 200, int) +@@ -55,12 +56,13 @@ + #define TUNSETVNETHDRSZ _IOW('T', 216, int) + + /* TUNSETIFF ifr flags */ +-#define IFF_TUN 0x0001 +-#define IFF_TAP 0x0002 +-#define IFF_NO_PI 0x1000 +-#define IFF_ONE_QUEUE 0x2000 +-#define IFF_VNET_HDR 0x4000 +-#define IFF_TUN_EXCL 0x8000 ++#define IFF_TUN 0x0001 ++#define IFF_TAP 0x0002 ++#define IFF_NO_PI 0x1000 ++#define IFF_ONE_QUEUE 0x2000 ++#define IFF_VNET_HDR 0x4000 ++#define IFF_TUN_EXCL 0x8000 ++#define IFF_TUN_SET_CARRIER 0x0008 + + /* Features for GSO (TUNSETOFFLOAD). */ + #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ +@@ -68,6 +70,7 @@ + #define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ + #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ + #define TUN_F_UFO 0x10 /* I can handle UFO packets */ ++#define TUN_F_HW_SWITCH_OFFLOAD 0x20 /* I can handle switch offloaded packets */ + + /* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ + #define TUN_PKT_STRIP 0x0001 +diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h +index c944c4f..344e6ab 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch new file mode 100644 index 00000000..435b379f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_init.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/init.h ++++ b/include/linux/init.h +@@ -82,12 +82,22 @@ + #define __exit __section(.exit.text) __exitused __cold notrace + + /* Used for HOTPLUG */ ++/* XXX - hack to disable __devinit for DPA drivers */ ++#ifdef CONFIG_DPA ++#define __devinit ++#define __devinitdata ++#define __devinitconst ++#define __devexit ++#define __devexitdata ++#define __devexitconst ++#else + #define __devinit __section(.devinit.text) __cold notrace + #define __devinitdata __section(.devinit.data) + #define __devinitconst __section(.devinit.rodata) + #define __devexit __section(.devexit.text) __exitused __cold notrace + #define __devexitdata __section(.devexit.data) + #define __devexitconst __section(.devexit.rodata) ++#endif + + /* Used for HOTPLUG_CPU */ + #define __cpuinit __section(.cpuinit.text) __cold notrace +diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h +index 318bb82..0c74dfd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch new file mode 100644 index 00000000..d0cd6c52 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_irqdesc.h.patch @@ -0,0 +1,24 @@ +--- a/include/linux/irqdesc.h ++++ b/include/linux/irqdesc.h +@@ -55,8 +55,6 @@ struct irq_desc { + unsigned int irq_count; /* For detecting broken IRQs */ + unsigned long last_unhandled; /* Aging timer for unhandled count */ + unsigned int irqs_unhandled; +- atomic_t threads_handled; +- int threads_handled_last; + raw_spinlock_t lock; + struct cpumask *percpu_enabled; + #ifdef CONFIG_SMP +@@ -74,6 +72,10 @@ struct irq_desc { + #endif + struct module *owner; + const char *name; ++#ifndef __GENKSYMS__ ++ atomic_t threads_handled; ++ int threads_handled_last; ++#endif + } ____cacheline_internodealigned_in_smp; + + #ifndef CONFIG_SPARSE_IRQ +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 4920c55..dce0ef5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch new file mode 100644 index 00000000..716b3624 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_jbd2.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -470,7 +470,9 @@ struct transaction_s + T_COMMIT, + T_COMMIT_DFLUSH, + T_COMMIT_JFLUSH, ++#ifndef __GENKSYMS__ + T_COMMIT_CALLBACK, ++#endif + T_FINISHED + } t_state; + +diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h +index f4e8578..333dea6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch new file mode 100644 index 00000000..8abe5bfc --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_jiffies.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -292,6 +292,11 @@ extern unsigned long timeval_to_jiffies(const struct timeval *value); + extern void jiffies_to_timeval(const unsigned long jiffies, + struct timeval *value); + extern clock_t jiffies_to_clock_t(unsigned long x); ++static inline clock_t jiffies_delta_to_clock_t(long delta) ++{ ++ return jiffies_to_clock_t(max(0L, delta)); ++} ++ + extern unsigned long clock_t_to_jiffies(unsigned long x); + extern u64 jiffies_64_to_clock_t(u64 x); + extern u64 nsec_to_clock_t(u64 x); +diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h +index ee0c952..35f7237 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch new file mode 100644 index 00000000..02d95f30 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_kvm_host.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -50,6 +50,7 @@ + #define KVM_REQ_APF_HALT 12 + #define KVM_REQ_STEAL_UPDATE 13 + #define KVM_REQ_NMI 14 ++#define KVM_REQ_IMMEDIATE_EXIT 15 + + #define KVM_USERSPACE_IRQ_SOURCE_ID 0 + +diff --git a/include/linux/libata.h b/include/linux/libata.h +index 000434e..a548ffd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch new file mode 100644 index 00000000..a0a960a6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mdio.h.patch @@ -0,0 +1,61 @@ +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -42,7 +42,11 @@ + #define MDIO_PKGID2 15 + #define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ + #define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ ++#define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */ ++#define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */ + #define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ ++#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ ++#define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */ + + /* Media-dependent registers. */ + #define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */ +@@ -55,7 +59,6 @@ + #define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */ + #define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */ + #define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */ +-#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ + + /* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */ + #define MDIO_PMA_LASI_RXCTRL 0x9000 /* RX_ALARM control */ +@@ -81,6 +84,7 @@ + #define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART + #define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE + #define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */ ++#define MDIO_PCS_CTRL1_CLKSTOP_EN 0x400 /* Stop the clock during LPI */ + + /* 10 Gb/s */ + #define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00) +@@ -236,9 +240,25 @@ + #define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */ + #define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */ + +-/* AN EEE Advertisement register. */ +-#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */ +-#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */ ++/* EEE Supported/Advertisement/LP Advertisement registers. ++ * ++ * EEE capability Register (3.20), Advertisement (7.60) and ++ * Link partner ability (7.61) registers have and can use the same identical ++ * bit masks. ++ */ ++#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */ ++#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */ ++/* Note: the two defines above can be potentially used by the user-land ++ * and cannot remove them now. ++ * So, we define the new generic MDIO_EEE_100TX and MDIO_EEE_1000T macros ++ * using the previous ones (that can be considered obsolete). ++ */ ++#define MDIO_EEE_100TX MDIO_AN_EEE_ADV_100TX /* 100TX EEE cap */ ++#define MDIO_EEE_1000T MDIO_AN_EEE_ADV_1000T /* 1000T EEE cap */ ++#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */ ++#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */ ++#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */ ++#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */ + + /* LASI RX_ALARM control/status registers. */ + #define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */ +diff --git a/include/linux/mii.h b/include/linux/mii.h +index 2774823..4212186 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch new file mode 100644 index 00000000..54df4e96 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mii.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/mii.h ++++ b/include/linux/mii.h +@@ -20,6 +20,8 @@ + #define MII_EXPANSION 0x06 /* Expansion register */ + #define MII_CTRL1000 0x09 /* 1000BASE-T control */ + #define MII_STAT1000 0x0a /* 1000BASE-T status */ ++#define MII_MMD_CTRL 0x0d /* MMD Access Control Register */ ++#define MII_MMD_DATA 0x0e /* MMD Access Data Register */ + #define MII_ESTATUS 0x0f /* Extended Status */ + #define MII_DCOUNTER 0x12 /* Disconnect counter */ + #define MII_FCSCOUNTER 0x13 /* False carrier counter */ +@@ -140,6 +142,13 @@ + #define FLOW_CTRL_TX 0x01 + #define FLOW_CTRL_RX 0x02 + ++/* MMD Access Control register fields */ ++#define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/ ++#define MII_MMD_CTRL_ADDR 0x0000 /* Address */ ++#define MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */ ++#define MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */ ++#define MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */ ++ + /* This structure is used in all SIOCxMIIxxx ioctl calls */ + struct mii_ioctl_data { + __u16 phy_id; +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index de3a321..a94dbfd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch new file mode 100644 index 00000000..6e721117 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mm_types.h.patch @@ -0,0 +1,23 @@ +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -297,7 +297,6 @@ struct mm_struct { + void (*unmap_area) (struct mm_struct *mm, unsigned long addr); + #endif + unsigned long mmap_base; /* base of mmap area */ +- unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */ + unsigned long task_size; /* size of task vm space */ + unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ + unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ +@@ -390,6 +389,10 @@ struct mm_struct { + #ifdef CONFIG_CPUMASK_OFFSTACK + struct cpumask cpumask_allocation; + #endif ++ ++#ifndef __GENKSYMS__ ++ unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */ ++#endif + }; + + static inline void mm_init_cpumask(struct mm_struct *mm) +diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h +index 87967ee..d424b9d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch new file mode 100644 index 00000000..bce90b44 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mod_devicetable.h.patch @@ -0,0 +1,44 @@ +--- a/include/linux/mod_devicetable.h ++++ b/include/linux/mod_devicetable.h +@@ -461,8 +461,13 @@ enum dmi_field { + }; + + struct dmi_strmatch { ++#ifndef __GENKSYMS__ ++ /* Layout supported by dmi_check_system_2() and dmi_first_match_2() */ + unsigned char slot:7; + unsigned char exact_match:1; ++#else ++ unsigned char slot; ++#endif + char substr[79]; + }; + +@@ -544,4 +549,25 @@ struct isapnp_device_id { + kernel_ulong_t driver_data; /* data private to the driver */ + }; + ++/* ++ * Match x86 CPUs for CPU specific drivers. ++ * See documentation of "x86_match_cpu" for details. ++ */ ++ ++struct x86_cpu_id { ++ __u16 vendor; ++ __u16 family; ++ __u16 model; ++ __u16 feature; /* bit index */ ++ kernel_ulong_t driver_data; ++}; ++ ++#define X86_FEATURE_MATCH(x) \ ++ { X86_VENDOR_ANY, X86_FAMILY_ANY, X86_MODEL_ANY, x } ++ ++#define X86_VENDOR_ANY 0xffff ++#define X86_FAMILY_ANY 0 ++#define X86_MODEL_ANY 0 ++#define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ ++ + #endif /* LINUX_MOD_DEVICETABLE_H */ +diff --git a/include/linux/mount.h b/include/linux/mount.h +index fc17c4d..e1e7aba 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch new file mode 100644 index 00000000..0552b53d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mroute.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/mroute.h ++++ b/include/linux/mroute.h +@@ -34,7 +34,7 @@ + #define SIOCGETSGCNT (SIOCPROTOPRIVATE+1) + #define SIOCGETRPF (SIOCPROTOPRIVATE+2) + +-#define MAXVIFS 32 ++#define MAXVIFS 256 + typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */ + typedef unsigned short vifi_t; + #define ALL_VIFS ((vifi_t)(-1)) +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 05acced..11b750e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch new file mode 100644 index 00000000..d5972d3b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_msi.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -1,6 +1,7 @@ + #ifndef LINUX_MSI_H + #define LINUX_MSI_H + ++#include + #include + + struct msi_msg { +diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h +index d249254..d5d2ec6 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch new file mode 100644 index 00000000..9556fb99 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi.h.patch @@ -0,0 +1,60 @@ +--- a/include/linux/mtd/cfi.h ++++ b/include/linux/mtd/cfi.h +@@ -354,10 +354,10 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf + onecmd = cmd; + break; + case 2: +- onecmd = cpu_to_cfi16(cmd); ++ onecmd = cpu_to_cfi16(map, cmd); + break; + case 4: +- onecmd = cpu_to_cfi32(cmd); ++ onecmd = cpu_to_cfi32(map, cmd); + break; + } + +@@ -437,10 +437,10 @@ static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, + case 1: + break; + case 2: +- res = cfi16_to_cpu(res); ++ res = cfi16_to_cpu(map, res); + break; + case 4: +- res = cfi32_to_cpu(res); ++ res = cfi32_to_cpu(map, res); + break; + default: BUG(); + } +@@ -480,12 +480,12 @@ static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr) + if (map_bankwidth_is_1(map)) { + return val.x[0]; + } else if (map_bankwidth_is_2(map)) { +- return cfi16_to_cpu(val.x[0]); ++ return cfi16_to_cpu(map, val.x[0]); + } else { + /* No point in a 64-bit byteswap since that would just be + swapping the responses from different chips, and we are + only interested in one chip (a representative sample) */ +- return cfi32_to_cpu(val.x[0]); ++ return cfi32_to_cpu(map, val.x[0]); + } + } + +@@ -496,12 +496,12 @@ static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr) + if (map_bankwidth_is_1(map)) { + return val.x[0] & 0xff; + } else if (map_bankwidth_is_2(map)) { +- return cfi16_to_cpu(val.x[0]); ++ return cfi16_to_cpu(map, val.x[0]); + } else { + /* No point in a 64-bit byteswap since that would just be + swapping the responses from different chips, and we are + only interested in one chip (a representative sample) */ +- return cfi32_to_cpu(val.x[0]); ++ return cfi32_to_cpu(map, val.x[0]); + } + } + +diff --git a/include/linux/mtd/cfi_endian.h b/include/linux/mtd/cfi_endian.h +index 51cc3f5..c785284 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch new file mode 100644 index 00000000..0f2ef19c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_cfi_endian.h.patch @@ -0,0 +1,77 @@ +--- a/include/linux/mtd/cfi_endian.h ++++ b/include/linux/mtd/cfi_endian.h +@@ -37,35 +37,48 @@ + #define CFI_BIG_ENDIAN + #endif + ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++#define CFI_OF_BYTE_SWAP ++#endif ++ + #endif + + #if defined(CFI_LITTLE_ENDIAN) +-#define cpu_to_cfi8(x) (x) +-#define cfi8_to_cpu(x) (x) +-#define cpu_to_cfi16(x) cpu_to_le16(x) +-#define cpu_to_cfi32(x) cpu_to_le32(x) +-#define cpu_to_cfi64(x) cpu_to_le64(x) +-#define cfi16_to_cpu(x) le16_to_cpu(x) +-#define cfi32_to_cpu(x) le32_to_cpu(x) +-#define cfi64_to_cpu(x) le64_to_cpu(x) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) cpu_to_le16(x) ++#define cpu_to_cfi32(m,x) cpu_to_le32(x) ++#define cpu_to_cfi64(m,x) cpu_to_le64(x) ++#define cfi16_to_cpu(m,x) le16_to_cpu(x) ++#define cfi32_to_cpu(m,x) le32_to_cpu(x) ++#define cfi64_to_cpu(m,x) le64_to_cpu(x) + #elif defined (CFI_BIG_ENDIAN) +-#define cpu_to_cfi8(x) (x) +-#define cfi8_to_cpu(x) (x) +-#define cpu_to_cfi16(x) cpu_to_be16(x) +-#define cpu_to_cfi32(x) cpu_to_be32(x) +-#define cpu_to_cfi64(x) cpu_to_be64(x) +-#define cfi16_to_cpu(x) be16_to_cpu(x) +-#define cfi32_to_cpu(x) be32_to_cpu(x) +-#define cfi64_to_cpu(x) be64_to_cpu(x) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) cpu_to_be16(x) ++#define cpu_to_cfi32(m,x) cpu_to_be32(x) ++#define cpu_to_cfi64(m,x) cpu_to_be64(x) ++#define cfi16_to_cpu(m,x) be16_to_cpu(x) ++#define cfi32_to_cpu(m,x) be32_to_cpu(x) ++#define cfi64_to_cpu(m,x) be64_to_cpu(x) + #elif defined (CFI_HOST_ENDIAN) +-#define cpu_to_cfi8(x) (x) +-#define cfi8_to_cpu(x) (x) +-#define cpu_to_cfi16(x) (x) +-#define cpu_to_cfi32(x) (x) +-#define cpu_to_cfi64(x) (x) +-#define cfi16_to_cpu(x) (x) +-#define cfi32_to_cpu(x) (x) +-#define cfi64_to_cpu(x) (x) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) (x) ++#define cpu_to_cfi32(m,x) (x) ++#define cpu_to_cfi64(m,x) (x) ++#define cfi16_to_cpu(m,x) (x) ++#define cfi32_to_cpu(m,x) (x) ++#define cfi64_to_cpu(m,x) (x) ++#elif defined (CFI_OF_BYTE_SWAP) ++#define cpu_to_cfi8(m,x) (x) ++#define cfi8_to_cpu(m,x) (x) ++#define cpu_to_cfi16(m,x) ((m)->byteswap ? swab16(x) : (x)) ++#define cpu_to_cfi32(m,x) ((m)->byteswap ? swab32(x) : (x)) ++#define cpu_to_cfi64(m,x) ((m)->byteswap ? swab64(x) : (x)) ++#define cfi16_to_cpu(m,x) ((m)->byteswap ? swab16(x) : (x)) ++#define cfi32_to_cpu(m,x) ((m)->byteswap ? swab32(x) : (x)) ++#define cfi64_to_cpu(m,x) ((m)->byteswap ? swab64(x) : (x)) + #else + #error No CFI endianness defined + #endif +diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h +index 3887901..b8ca7de 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch new file mode 100644 index 00000000..0ea52eff --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_mtd_map.h.patch @@ -0,0 +1,15 @@ +--- a/include/linux/mtd/map.h ++++ b/include/linux/mtd/map.h +@@ -219,6 +219,10 @@ struct map_info { + in bytes, before you are talking to the first chip again. + */ + ++#ifdef CONFIG_MTD_CFI_OF_BYTE_SWAP ++ int byteswap; /* get byte swap configuration from device tree */ ++#endif ++ + #ifdef CONFIG_MTD_COMPLEX_MAPPINGS + map_word (*read)(struct map_info *, unsigned long); + void (*copy_from)(struct map_info *, void *, unsigned long, ssize_t); +diff --git a/include/linux/namei.h b/include/linux/namei.h +index ffc0213..ef35a31 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch new file mode 100644 index 00000000..dc3e4214 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_neighbour.h.patch @@ -0,0 +1,26 @@ +--- a/include/linux/neighbour.h ++++ b/include/linux/neighbour.h +@@ -20,6 +20,11 @@ enum { + NDA_LLADDR, + NDA_CACHEINFO, + NDA_PROBES, ++ NDA_VLAN, ++ NDA_PORT, ++ NDA_VNI, ++ NDA_IFINDEX, ++ NDA_MASTER, + __NDA_MAX + }; + +@@ -33,6 +38,9 @@ enum { + #define NTF_PROXY 0x08 /* == ATF_PUBL */ + #define NTF_ROUTER 0x80 + ++#define NTF_SELF 0x02 ++#define NTF_MASTER 0x04 ++ + /* + * Neighbor Cache Entry States. + */ +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 4b04097..e2bde14 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch new file mode 100644 index 00000000..dc989518 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_of_mdio.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/of_mdio.h ++++ b/include/linux/of_mdio.h +@@ -21,5 +21,8 @@ extern struct phy_device *of_phy_connect(struct net_device *dev, + extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev, + void (*hndlr)(struct net_device *), + phy_interface_t iface); ++extern struct phy_device *of_phy_attach(struct net_device *dev, ++ struct device_node *phy_np, u32 flags, ++ phy_interface_t iface); + + #endif /* __LINUX_OF_MDIO_H */ +diff --git a/include/linux/pci.h b/include/linux/pci.h +index fe76a74..cea9ae5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch new file mode 100644 index 00000000..a99511b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci.h.patch @@ -0,0 +1,101 @@ +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -282,6 +282,10 @@ struct pci_dev { + unsigned int mmio_always_on:1; /* disallow turning off io/mem + decoding during bar sizing */ + unsigned int wakeup_prepared:1; ++#ifndef __GENKSYMS__ ++ unsigned int :4; /* spare */ ++ unsigned int pcie_flags_reg:16; /* cached PCI-E Capabilities Register */ ++#endif + unsigned int d3_delay; /* D3->D0 transition time in ms */ + + #ifdef CONFIG_PCIEASPM +@@ -345,6 +349,9 @@ struct pci_dev { + }; + struct pci_ats *ats; /* Address Translation Service */ + #endif ++#if defined(CONFIG_PCI_MSI) && !defined(__GENKSYMS__) ++ const struct attribute_group *msi_irq_group; ++#endif + }; + + static inline struct pci_dev *pci_physfn(struct pci_dev *dev) +@@ -790,6 +797,39 @@ static inline int pci_write_config_dword(struct pci_dev *dev, int where, + return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); + } + ++int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val); ++int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val); ++int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val); ++int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val); ++int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, ++ u16 clear, u16 set); ++int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, ++ u32 clear, u32 set); ++ ++static inline int pcie_capability_set_word(struct pci_dev *dev, int pos, ++ u16 set) ++{ ++ return pcie_capability_clear_and_set_word(dev, pos, 0, set); ++} ++ ++static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos, ++ u32 set) ++{ ++ return pcie_capability_clear_and_set_dword(dev, pos, 0, set); ++} ++ ++static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos, ++ u16 clear) ++{ ++ return pcie_capability_clear_and_set_word(dev, pos, clear, 0); ++} ++ ++static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos, ++ u32 clear) ++{ ++ return pcie_capability_clear_and_set_dword(dev, pos, clear, 0); ++} ++ + int __must_check pci_enable_device(struct pci_dev *dev); + int __must_check pci_enable_device_io(struct pci_dev *dev); + int __must_check pci_enable_device_mem(struct pci_dev *dev); +@@ -955,6 +995,19 @@ int __must_check __pci_register_driver(struct pci_driver *, struct module *, + __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) + + void pci_unregister_driver(struct pci_driver *dev); ++ ++/** ++ * module_pci_driver() - Helper macro for registering a PCI driver ++ * @__pci_driver: pci_driver struct ++ * ++ * Helper macro for PCI drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_pci_driver(__pci_driver) \ ++ module_driver(__pci_driver, pci_register_driver, \ ++ pci_unregister_driver) ++ + void pci_remove_behind_bridge(struct pci_dev *dev); + struct pci_driver *pci_dev_driver(const struct pci_dev *dev); + int pci_add_dynid(struct pci_driver *drv, +@@ -1531,6 +1584,15 @@ static inline bool pci_is_pcie(struct pci_dev *dev) + return !!pci_pcie_cap(dev); + } + ++/** ++ * pci_pcie_type - get the PCIe device/port type ++ * @dev: PCI device ++ */ ++static inline int pci_pcie_type(const struct pci_dev *dev) ++{ ++ return (dev->pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4; ++} ++ + void pci_request_acs(void); + + +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index d93f417..f1fecb0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch new file mode 100644 index 00000000..4021ab5b --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_ids.h.patch @@ -0,0 +1,28 @@ +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -721,6 +721,7 @@ + #define PCI_DEVICE_ID_SI_7018 0x7018 + + #define PCI_VENDOR_ID_HP 0x103c ++#define PCI_VENDOR_ID_HP_3PAR 0x1590 + #define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 + #define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 + #define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 +@@ -753,6 +754,7 @@ + #define PCI_DEVICE_ID_HP_CISSE 0x323a + #define PCI_DEVICE_ID_HP_CISSF 0x323b + #define PCI_DEVICE_ID_HP_CISSH 0x323c ++#define PCI_DEVICE_ID_HP_CISSI 0x3239 + #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 + + #define PCI_VENDOR_ID_PCTECH 0x1042 +@@ -2484,6 +2486,7 @@ + #define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F + #define PCI_DEVICE_ID_INTEL_I960 0x0960 + #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 ++#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 + #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 + #define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085 + #define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108F +diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h +index 411c412..7451a34 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch new file mode 100644 index 00000000..6487eccd --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pci_regs.h.patch @@ -0,0 +1,27 @@ +--- a/include/linux/pci_regs.h ++++ b/include/linux/pci_regs.h +@@ -441,6 +441,8 @@ + #define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */ + #define PCI_EXP_LNKCTL 16 /* Link Control */ + #define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ ++#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */ ++#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */ + #define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */ + #define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */ + #define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */ +@@ -520,7 +522,13 @@ + #define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ + #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ + #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ ++#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ ++#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ ++#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ ++#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ ++#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ + #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ ++#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ + #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ + + /* Extended Capabilities (PCI-X 2.0 and Express) */ +diff --git a/include/linux/percpu.h b/include/linux/percpu.h +index 9ca008f..c925813 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch new file mode 100644 index 00000000..76dba9af --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_percpu.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/percpu.h ++++ b/include/linux/percpu.h +@@ -73,9 +73,9 @@ + * intelligent way to determine this would be nice. + */ + #if BITS_PER_LONG > 32 +-#define PERCPU_DYNAMIC_RESERVE (20 << 10) ++#define PERCPU_DYNAMIC_RESERVE (28 << 10) + #else +-#define PERCPU_DYNAMIC_RESERVE (12 << 10) ++#define PERCPU_DYNAMIC_RESERVE (20 << 14) + #endif + + extern void *pcpu_base_addr; +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 8d5b91e..aaed55b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch new file mode 100644 index 00000000..d1fdb2ca --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_perf_event.h.patch @@ -0,0 +1,38 @@ +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -796,7 +796,11 @@ struct perf_event { + struct hw_perf_event hw; + + struct perf_event_context *ctx; ++#ifdef __GENKSYMS__ ++ struct file *filp; ++#else + atomic_long_t refcount; ++#endif + + /* + * These accumulate total time (in nanoseconds) that children +@@ -821,6 +825,9 @@ struct perf_event { + /* mmap bits */ + struct mutex mmap_mutex; + atomic_t mmap_count; ++ /* These two are unused but kept here for ABI compat */ ++ int mmap_locked; ++ struct user_struct *mmap_user; + + struct ring_buffer *rb; + struct list_head rb_entry; +@@ -929,7 +936,11 @@ struct perf_cpu_context { + int exclusive; + struct list_head rotation_list; + int jiffies_interval; ++#ifdef __GENKSYMS__ ++ struct pmu *active_pmu; ++#else + struct pmu *unique_pmu; ++#endif + struct perf_cgroup *cgrp; + }; + +diff --git a/include/linux/phy.h b/include/linux/phy.h +index 79f337c..1efebc0 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch new file mode 100644 index 00000000..48ce3607 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_phy.h.patch @@ -0,0 +1,112 @@ +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -65,6 +65,7 @@ typedef enum { + PHY_INTERFACE_MODE_RGMII_TXID, + PHY_INTERFACE_MODE_RTBI, + PHY_INTERFACE_MODE_SMII, ++ PHY_INTERFACE_MODE_XGMII, + } phy_interface_t; + + +@@ -96,8 +97,10 @@ struct mii_bus { + const char *name; + char id[MII_BUS_ID_SIZE]; + void *priv; +- int (*read)(struct mii_bus *bus, int phy_id, int regnum); +- int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val); ++ int (*read)(struct mii_bus *bus, int port_addr, int dev_addr, ++ int regnum); ++ int (*write)(struct mii_bus *bus, int port_addr, int dev_addr, ++ int regnum, u16 val); + int (*reset)(struct mii_bus *bus); + + /* +@@ -126,6 +129,9 @@ struct mii_bus { + * interrupt at the index matching its address + */ + int *irq; ++ ++ /* indicate whether it's for Clause 45 PHY */ ++ bool is_c45; + }; + #define to_mii_bus(d) container_of(d, struct mii_bus, dev) + +@@ -134,8 +140,9 @@ int mdiobus_register(struct mii_bus *bus); + void mdiobus_unregister(struct mii_bus *bus); + void mdiobus_free(struct mii_bus *bus); + struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); +-int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); +-int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); ++int mdiobus_read(struct mii_bus *bus, int addr, int devad, u16 regnum); ++int mdiobus_write(struct mii_bus *bus, int addr, int devad, ++ u16 regnum, u16 val); + + + #define PHY_INTERRUPT_DISABLED 0x0 +@@ -307,6 +314,7 @@ struct phy_device { + /* See mii.h for more info */ + u32 supported; + u32 advertising; ++ u32 mmds; + + int autoneg; + +@@ -453,7 +461,22 @@ struct phy_fixup { + */ + static inline int phy_read(struct phy_device *phydev, u32 regnum) + { +- return mdiobus_read(phydev->bus, phydev->addr, regnum); ++ return mdiobus_read(phydev->bus, phydev->addr, 0, regnum); ++} ++ ++/** ++ * phy45_read - Convenience function for reading a given port/dev/reg address ++ * @phydev: The phy_device struct ++ * @devad: The device address to read ++ * @regnum: The register number to read ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++static inline int phy45_read(struct phy_device *phydev, int devad, u16 regnum) ++{ ++ return mdiobus_read(phydev->bus, phydev->addr, devad, regnum); + } + + /** +@@ -468,12 +491,31 @@ static inline int phy_read(struct phy_device *phydev, u32 regnum) + */ + static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val) + { +- return mdiobus_write(phydev->bus, phydev->addr, regnum, val); ++ return mdiobus_write(phydev->bus, phydev->addr, 0, regnum, val); ++} ++ ++/** ++ * phy45_write - Convenience function for writing a given port/dev/reg ++ * @phydev: the phy_device struct ++ * @devad: the device addr ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++static inline int phy45_write(struct phy_device *phydev, u16 regnum, ++ int devad, u16 val) ++{ ++ return mdiobus_write(phydev->bus, phydev->addr, devad, regnum, val); + } + + int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); + struct phy_device* get_phy_device(struct mii_bus *bus, int addr); + int phy_device_register(struct phy_device *phy); ++int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ++ u32 flags, phy_interface_t interface); + int phy_init_hw(struct phy_device *phydev); + struct phy_device * phy_attach(struct net_device *dev, + const char *bus_id, u32 flags, phy_interface_t interface); +diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h +index 38d1032..e7cf666 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch new file mode 100644 index 00000000..f73d0c03 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pid_namespace.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/pid_namespace.h ++++ b/include/linux/pid_namespace.h +@@ -30,6 +30,8 @@ struct pid_namespace { + #ifdef CONFIG_BSD_PROCESS_ACCT + struct bsd_acct_struct *bacct; + #endif ++ gid_t pid_gid; ++ int hide_pid; + }; + + extern struct pid_namespace init_pid_ns; +diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h +index 7281d5a..443655d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch new file mode 100644 index 00000000..e2354c66 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pkt_sched.h.patch @@ -0,0 +1,90 @@ +--- a/include/linux/pkt_sched.h ++++ b/include/linux/pkt_sched.h +@@ -603,4 +603,84 @@ struct tc_qfq_stats { + __u32 lmax; + }; + ++/* CODEL */ ++ ++enum { ++ TCA_CODEL_UNSPEC, ++ TCA_CODEL_TARGET, ++ TCA_CODEL_LIMIT, ++ TCA_CODEL_INTERVAL, ++ TCA_CODEL_ECN, ++ __TCA_CODEL_MAX ++}; ++ ++#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1) ++ ++struct tc_codel_xstats { ++ __u32 maxpacket; /* largest packet we've seen so far */ ++ __u32 count; /* how many drops we've done since the last time we ++ * entered dropping state ++ */ ++ __u32 lastcount; /* count at entry to dropping state */ ++ __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */ ++ __s32 drop_next; /* time to drop next packet */ ++ __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */ ++ __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */ ++ __u32 dropping; /* are we in dropping state ? */ ++}; ++ ++/* FQ_CODEL */ ++ ++enum { ++ TCA_FQ_CODEL_UNSPEC, ++ TCA_FQ_CODEL_TARGET, ++ TCA_FQ_CODEL_LIMIT, ++ TCA_FQ_CODEL_INTERVAL, ++ TCA_FQ_CODEL_ECN, ++ TCA_FQ_CODEL_FLOWS, ++ TCA_FQ_CODEL_QUANTUM, ++ __TCA_FQ_CODEL_MAX ++}; ++ ++#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1) ++ ++enum { ++ TCA_FQ_CODEL_XSTATS_QDISC, ++ TCA_FQ_CODEL_XSTATS_CLASS, ++}; ++ ++struct tc_fq_codel_qd_stats { ++ __u32 maxpacket; /* largest packet we've seen so far */ ++ __u32 drop_overlimit; /* number of time max qdisc ++ * packet limit was hit ++ */ ++ __u32 ecn_mark; /* number of packets we ECN marked ++ * instead of being dropped ++ */ ++ __u32 new_flow_count; /* number of time packets ++ * created a 'new flow' ++ */ ++ __u32 new_flows_len; /* count of flows in new list */ ++ __u32 old_flows_len; /* count of flows in old list */ ++}; ++ ++struct tc_fq_codel_cl_stats { ++ __s32 deficit; ++ __u32 ldelay; /* in-queue delay seen by most recently ++ * dequeued packet ++ */ ++ __u32 count; ++ __u32 lastcount; ++ __u32 dropping; ++ __s32 drop_next; ++}; ++ ++struct tc_fq_codel_xstats { ++ __u32 type; ++ union { ++ struct tc_fq_codel_qd_stats qdisc_stats; ++ struct tc_fq_codel_cl_stats class_stats; ++ }; ++}; ++ + #endif +diff --git a/include/linux/platform_data/max6697.h b/include/linux/platform_data/max6697.h +new file mode 100644 +index 0000000..ed9d3b3 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch new file mode 100644 index 00000000..b9856ddb --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_data_max6697.h.patch @@ -0,0 +1,41 @@ +--- /dev/null ++++ b/include/linux/platform_data/max6697.h +@@ -0,0 +1,36 @@ ++/* ++ * max6697.h ++ * Copyright (c) 2012 Guenter Roeck ++ * ++ * 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. ++ */ ++ ++#ifndef MAX6697_H ++#define MAX6697_H ++ ++#include ++ ++/* ++ * For all bit masks: ++ * bit 0: local temperature ++ * bit 1..7: remote temperatures ++ */ ++struct max6697_platform_data { ++ bool smbus_timeout_disable; /* set to disable SMBus timeouts */ ++ bool extended_range_enable; /* set to enable extended temp range */ ++ bool beta_compensation; /* set to enable beta compensation */ ++ u8 alert_mask; /* set bit to 1 to disable alert */ ++ u8 over_temperature_mask; /* set bit to 1 to disable */ ++ u8 resistance_cancellation; /* set bit to 0 to disable ++ * bit mask for MAX6581, ++ * boolean for other chips ++ */ ++ u8 ideality_mask; /* set bit to 0 to disable */ ++ u8 ideality_value; /* transistor ideality as per ++ * MAX6581 datasheet ++ */ ++}; ++ ++#endif /* MAX6697_H */ +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index 2a23f7d..4cf54aa 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch new file mode 100644 index 00000000..e082122d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_platform_device.h.patch @@ -0,0 +1,34 @@ +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -14,6 +14,9 @@ + #include + #include + ++#define PLATFORM_DEVID_NONE (-1) ++#define PLATFORM_DEVID_AUTO (-2) ++ + struct mfd_cell; + + struct platform_device { +@@ -196,16 +199,8 @@ static inline void platform_set_drvdata(struct platform_device *pdev, void *data + * calling it replaces module_init() and module_exit() + */ + #define module_platform_driver(__platform_driver) \ +-static int __init __platform_driver##_init(void) \ +-{ \ +- return platform_driver_register(&(__platform_driver)); \ +-} \ +-module_init(__platform_driver##_init); \ +-static void __exit __platform_driver##_exit(void) \ +-{ \ +- platform_driver_unregister(&(__platform_driver)); \ +-} \ +-module_exit(__platform_driver##_exit); ++ module_driver(__platform_driver, platform_driver_register, \ ++ platform_driver_unregister) + + extern struct platform_device *platform_create_bundle(struct platform_driver *driver, + int (*probe)(struct platform_device *), +diff --git a/include/linux/port.h b/include/linux/port.h +new file mode 100644 +index 0000000..6389048 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch new file mode 100644 index 00000000..90cdcf8e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_port.h.patch @@ -0,0 +1,84 @@ +--- /dev/null ++++ b/include/linux/port.h +@@ -0,0 +1,79 @@ ++/* ++ * port.h - defines for generic netlink port handler ++ * Copyright (C) 2013 Cumulus Networks ++ */ ++ ++#ifndef _LINUX_PORT_H ++#define _LINUX_PORT_H ++ ++#ifdef __KERNEL__ ++#include ++#endif ++#include ++ ++enum { ++ PORT_ATTR_UNSPEC, ++ PORT_ATTR_STATUS, ++ PORT_ATTR_IFINDEX, ++ PORT_ATTR_FLAGS, ++ PORT_ATTR_CARRIER, ++ PORT_ATTR_PHYS_ID_STATE, ++ PORT_ATTR_SETTINGS, ++ PORT_ATTR_PAUSE, ++ PORT_ATTR_MODINFO, ++ PORT_ATTR_EEPROM, ++ PORT_ATTR_EEPROM_DATA, ++ PORT_ATTR_STATS, ++ PORT_ATTR_STAT, ++ PORT_ATTR_STRINGS, ++ PORT_ATTR_STRING, ++ PORT_ATTR_SSET, ++ PORT_ATTR_SSET_COUNT, ++ __PORT_ATTR_MAX, ++}; ++#define PORT_ATTR_MAX (__PORT_ATTR_MAX - 1) ++ ++enum { ++ PORT_CMD_UNSPEC, ++ PORT_CMD_REPLY, ++ PORT_CMD_GET_SETTINGS, ++ PORT_CMD_SET_SETTINGS, ++ PORT_CMD_GET_PAUSE, ++ PORT_CMD_SET_PAUSE, ++ PORT_CMD_GET_MODULE_INFO, ++ PORT_CMD_GET_MODULE_EEPROM, ++ PORT_CMD_SET_STATS, ++ PORT_CMD_GET_STRINGS, ++ PORT_CMD_GET_SSET_COUNT, ++ PORT_CMD_SET_CARRIER, ++ PORT_CMD_SET_PHYS_ID_STATE, ++ PORT_CMD_GET_CACHED_SETTINGS, ++ __PORT_CMD_MAX, ++}; ++ ++#ifdef __KERNEL__ ++ ++#define PORT_ATTR_FLAG_STAT_RESTART (1 << 0) ++ ++void port_init_ethtool_stats(struct net_device *dev); ++void port_uninit_ethtool_stats(struct net_device *dev); ++int port_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); ++int port_set_settings(struct net_device *dev, struct ethtool_cmd *cmd); ++void port_get_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause); ++int port_set_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam * pause); ++void port_get_ethtool_stats(struct net_device *dev, ++ struct ethtool_stats *stats, u64 *data); ++void port_get_ethtool_stats_clear(struct net_device *dev, ++ struct ethtool_stats *stats, u64 *data); ++void port_get_strings(struct net_device *dev, u32 stringset, u8 *data); ++int port_get_sset_count(struct net_device *dev, int sset); ++int port_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state); ++int port_get_module_info(struct net_device *dev, struct ethtool_modinfo *info); ++int port_get_module_eeprom(struct net_device *dev, ++ struct ethtool_eeprom *eeprom, u8 *data); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _LINUX_PORT_H */ +diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h +index ce2ab3d..d189738 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch new file mode 100644 index 00000000..5eadec05 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_pps_kernel.h.patch @@ -0,0 +1,20 @@ +--- a/include/linux/pps_kernel.h ++++ b/include/linux/pps_kernel.h +@@ -69,11 +69,14 @@ struct pps_device { + wait_queue_head_t queue; /* PPS event queue */ + + unsigned int id; /* PPS source unique ID */ +- void const *lookup_cookie; /* pps_lookup_dev only */ + struct cdev cdev; + struct device *dev; + struct fasync_struct *async_queue; /* fasync method */ + spinlock_t lock; ++ ++#ifndef __GENKSYMS__ ++ void const *lookup_cookie; /* pps_lookup_dev only */ ++#endif + }; + + /* +diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h +index e49240b..ecbd207 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch new file mode 100644 index 00000000..d4caad94 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_ptrace.h.patch @@ -0,0 +1,14 @@ +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -112,7 +112,9 @@ + + #include /* For unlikely. */ + #include /* For struct task_struct. */ ++#ifndef __GENKSYMS__ + #include /* For task_active_pid_ns. */ ++#endif + + + extern long arch_ptrace(struct task_struct *child, long request, +diff --git a/include/linux/random.h b/include/linux/random.h +index f5e1311..02c1d28 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch new file mode 100644 index 00000000..85486bf5 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_random.h.patch @@ -0,0 +1,47 @@ +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -34,6 +34,30 @@ + /* Clear the entropy pool and associated counters. (Superuser only.) */ + #define RNDCLEARPOOL _IO( 'R', 0x06 ) + ++#ifdef CONFIG_FIPS_RNG ++ ++/* Size of seed value - equal to AES blocksize */ ++#define AES_BLOCK_SIZE_BYTES 16 ++#define SEED_SIZE_BYTES AES_BLOCK_SIZE_BYTES ++/* Size of AES key */ ++#define KEY_SIZE_BYTES 16 ++ ++/* ioctl() structure used by FIPS 140-2 Tests */ ++struct rand_fips_test { ++ unsigned char key[KEY_SIZE_BYTES]; /* Input */ ++ unsigned char datetime[SEED_SIZE_BYTES]; /* Input */ ++ unsigned char seed[SEED_SIZE_BYTES]; /* Input */ ++ unsigned char result[SEED_SIZE_BYTES]; /* Output */ ++}; ++ ++/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */ ++#define RNDFIPSVST _IOWR('R', 0x10, struct rand_fips_test) ++ ++/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */ ++#define RNDFIPSMCT _IOWR('R', 0x11, struct rand_fips_test) ++ ++#endif /* #ifdef CONFIG_FIPS_RNG */ ++ + struct rand_pool_info { + int entropy_count; + int buf_size; +@@ -55,6 +79,11 @@ extern void add_input_randomness(unsigned int type, unsigned int code, + unsigned int value); + extern void add_interrupt_randomness(int irq, int irq_flags); + ++extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count); ++extern int random_input_wait(void); ++#define HAS_RANDOM_INPUT_WAIT 1 ++ ++ + extern void get_random_bytes(void *buf, int nbytes); + extern void get_random_bytes_arch(void *buf, int nbytes); + void generate_random_uuid(unsigned char uuid_out[16]); +diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h +index f7756d1..34234fd 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch new file mode 100644 index 00000000..866db67d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_regulator_consumer.h.patch @@ -0,0 +1,19 @@ +--- a/include/linux/regulator/consumer.h ++++ b/include/linux/regulator/consumer.h +@@ -258,6 +258,13 @@ static inline int regulator_get_voltage(struct regulator *regulator) + return 0; + } + ++static inline int regulator_is_supported_voltage(struct regulator *regulator, ++ int min_uV, int max_uV) ++{ ++ return 0; ++} ++ ++ + static inline int regulator_set_current_limit(struct regulator *regulator, + int min_uA, int max_uA) + { +diff --git a/include/linux/retimer_class.h b/include/linux/retimer_class.h +new file mode 100644 +index 0000000..6f37318 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch new file mode 100644 index 00000000..679e553d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_retimer_class.h.patch @@ -0,0 +1,40 @@ +--- /dev/null ++++ b/include/linux/retimer_class.h +@@ -0,0 +1,35 @@ ++/* ++ * retimer_class.c ++ * ++ * This file exports interface functions for the sysfs class "retimer", ++ * for use by RETIMER drivers. ++ * ++ * Copyright (C) 2014 Cumulus Networks, Inc. ++ * Author: Puneet Shenoy ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#ifndef RETIMER_CLASS_H__ ++#define RETIMER_CLASS_H__ ++ ++#include ++#include ++ ++struct device *retimer_device_register(struct device *dev); ++ ++void retimer_device_unregister(struct device *dev); ++ ++#endif /* RETIMER_CLASS_H__ */ +diff --git a/include/linux/rmap.h b/include/linux/rmap.h +index b0df05a..590ea0f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch new file mode 100644 index 00000000..1f7d3c31 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_rmap.h.patch @@ -0,0 +1,40 @@ +--- a/include/linux/rmap.h ++++ b/include/linux/rmap.h +@@ -37,16 +37,6 @@ struct anon_vma { + atomic_t refcount; + + /* +- * Count of child anon_vmas and VMAs which points to this anon_vma. +- * +- * This counter is used for making decision about reusing anon_vma +- * instead of forking new one. See comments in function anon_vma_clone. +- */ +- unsigned degree; +- +- struct anon_vma *parent; /* Parent of this anon_vma */ +- +- /* + * NOTE: the LSB of the head.next is set by + * mm_take_all_locks() _after_ taking the above lock. So the + * head must only be read/written after taking the above lock +@@ -55,6 +45,18 @@ struct anon_vma { + * mm_take_all_locks() (mm_all_locks_mutex). + */ + struct list_head head; /* Chain of private "related" vmas */ ++ ++#ifndef __GENKSYMS__ ++ /* ++ * Count of child anon_vmas and VMAs which points to this anon_vma. ++ * ++ * This counter is used for making decision about reusing anon_vma ++ * instead of forking new one. See comments in function anon_vma_clone. ++ */ ++ unsigned degree; ++ ++ struct anon_vma *parent; /* Parent of this anon_vma */ ++#endif + }; + + /* +diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h +index 577592e..2aa8240 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch new file mode 100644 index 00000000..93b83705 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_skbuff.h.patch @@ -0,0 +1,31 @@ +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -446,8 +446,8 @@ struct sk_buff { + + /* 0/13 bit hole */ + +-#ifdef CONFIG_NET_DMA +- dma_cookie_t dma_cookie; ++#ifdef CONFIG_NET_DMA_DUMMY ++ dma_cookie_t dma_cookie; /* now unused */ + #endif + #ifdef CONFIG_NETWORK_SECMARK + __u32 secmark; +@@ -455,9 +455,15 @@ struct sk_buff { + union { + __u32 mark; + __u32 dropcount; ++ /* For use by TCP only */ ++#ifdef __GENKSYMS__ ++ __u32 avail_size; ++#else + __u32 reserved_tailroom; ++#endif + }; + ++ __be16 vlan_proto; + __u16 vlan_tci; + + sk_buff_data_t transport_header; +diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h +index d00e0ba..fbd1117 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch new file mode 100644 index 00000000..7719ed6d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_slab_def.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/slab_def.h ++++ b/include/linux/slab_def.h +@@ -15,8 +15,6 @@ + #include /* kmalloc_sizes.h needs L1_CACHE_BYTES */ + #include + +-#include +- + /* + * struct kmem_cache + * +diff --git a/include/linux/snmp.h b/include/linux/snmp.h +index 64f5ca7..b49eae1 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch new file mode 100644 index 00000000..9b2e753f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_snmp.h.patch @@ -0,0 +1,23 @@ +--- a/include/linux/snmp.h ++++ b/include/linux/snmp.h +@@ -210,6 +210,7 @@ enum + LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ + LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ + LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ ++ LINUX_MIB_TCPABORTONSYN, /* unused, binary compat */ + LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ + LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ + LINUX_MIB_TCPABORTONTIMEOUT, /* TCPAbortOnTimeout */ +@@ -232,8 +233,10 @@ enum + LINUX_MIB_TCPTIMEWAITOVERFLOW, /* TCPTimeWaitOverflow */ + LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ + LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ ++#ifndef __GENKSYMS__ + LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ + LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ ++#endif + __LINUX_MIB_MAX + }; + +diff --git a/include/linux/splice.h b/include/linux/splice.h +index 09a545a..1ac5727 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch new file mode 100644 index 00000000..0de224d6 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_swiotlb.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/swiotlb.h ++++ b/include/linux/swiotlb.h +@@ -24,7 +24,7 @@ extern int swiotlb_force; + + extern void swiotlb_init(int verbose); + extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); +-extern unsigned long swioltb_nr_tbl(void); ++extern unsigned long swiotlb_nr_tbl(void); + + /* + * Enumeration for sync targets +diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h +index 703cfa3..4154bd4 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch new file mode 100644 index 00000000..5b1dda47 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysctl.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/sysctl.h ++++ b/include/linux/sysctl.h +@@ -275,6 +275,7 @@ enum + NET_CORE_AEVENT_ETIME=20, + NET_CORE_AEVENT_RSEQTH=21, + NET_CORE_WARNINGS=22, ++ NET_CORE_KILL_ROUTES_ON_LINKDOWN=23, + }; + + /* /proc/sys/net/ethernet */ +diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h +index 2b9cd8d..ecd4cc5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch new file mode 100644 index 00000000..e1f77eec --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysfs.h.patch @@ -0,0 +1,19 @@ +--- a/include/linux/sysfs.h ++++ b/include/linux/sysfs.h +@@ -78,6 +78,14 @@ struct attribute_group { + .show = _name##_show, \ + } + ++#define __ATTR_WO(_name) { \ ++ .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ ++ .store = _name##_store, \ ++} ++ ++#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ ++ _name##_show, _name##_store) ++ + #define __ATTR_NULL { .attr = { .name = NULL } } + + #define ATTRIBUTE_GROUPS(name) \ +diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h +index 7faf933..cbbbbe3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch new file mode 100644 index 00000000..c57ee1d0 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_sysrq.h.patch @@ -0,0 +1,13 @@ +--- a/include/linux/sysrq.h ++++ b/include/linux/sysrq.h +@@ -18,7 +18,7 @@ + #include + + /* Enable/disable SYSRQ support by default (0==no, 1==yes). */ +-#define SYSRQ_DEFAULT_ENABLE 1 ++#define SYSRQ_DEFAULT_ENABLE CONFIG_MAGIC_SYSRQ_DEFAULT_MASK + + /* Possible values of bitmask for enabling sysrq functions */ + /* 0x0001 is reserved for enable everything */ +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index 7f59ee9..0d62739 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch new file mode 100644 index 00000000..fff47999 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_tcp.h.patch @@ -0,0 +1,15 @@ +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -325,8 +325,8 @@ struct tcp_sock { + struct iovec *iov; + int memory; + int len; +-#ifdef CONFIG_NET_DMA +- /* members for async copy */ ++#ifdef CONFIG_NET_DMA_DUMMY ++ /* members for async copy, now unused */ + struct dma_chan *dma_chan; + int wakeup; + struct dma_pinned_list *pinned_list; +diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h +index 8da8c4e..3dc2be5 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch new file mode 100644 index 00000000..e65a1fe8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_u64_stats_sync.h.patch @@ -0,0 +1,17 @@ +--- a/include/linux/u64_stats_sync.h ++++ b/include/linux/u64_stats_sync.h +@@ -67,6 +67,12 @@ struct u64_stats_sync { + #endif + }; + ++#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) ++# define u64_stats_init(syncp) seqcount_init(syncp.seq) ++#else ++# define u64_stats_init(syncp) do { } while (0) ++#endif ++ + static inline void u64_stats_update_begin(struct u64_stats_sync *syncp) + { + #if BITS_PER_LONG==32 && defined(CONFIG_SMP) +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 93629fc..3959c62 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch new file mode 100644 index 00000000..3e983308 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb.h.patch @@ -0,0 +1,51 @@ +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -796,6 +796,27 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + ++/** ++ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces ++ * @vend: the 16 bit USB Vendor ID ++ * @cl: bInterfaceClass value ++ * @sc: bInterfaceSubClass value ++ * @pr: bInterfaceProtocol value ++ * ++ * This macro is used to create a struct usb_device_id that matches a ++ * specific vendor with a specific class of interfaces. ++ * ++ * This is especially useful when explicitly matching devices that have ++ * vendor specific bDeviceClass values, but standards-compliant interfaces. ++ */ ++#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ ++ | USB_DEVICE_ID_MATCH_VENDOR, \ ++ .idVendor = (vend), \ ++ .bInterfaceClass = (cl), \ ++ .bInterfaceSubClass = (sc), \ ++ .bInterfaceProtocol = (pr) ++ + /* ----------------------------------------------------------------------- */ + + /* Stuff for dynamic usb ids */ +@@ -974,6 +995,18 @@ extern int usb_register_driver(struct usb_driver *, struct module *, + + extern void usb_deregister(struct usb_driver *); + ++/** ++ * module_usb_driver() - Helper macro for registering a USB driver ++ * @__usb_driver: usb_driver struct ++ * ++ * Helper macro for USB drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_usb_driver(__usb_driver) \ ++ module_driver(__usb_driver, usb_register, \ ++ usb_deregister) ++ + extern int usb_register_device_driver(struct usb_device_driver *, + struct module *); + extern void usb_deregister_device_driver(struct usb_device_driver *); +diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h +index 7cc95ee..2ca3076 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch new file mode 100644 index 00000000..a184e029 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_ehci_def.h.patch @@ -0,0 +1,60 @@ +--- a/include/linux/usb/ehci_def.h ++++ b/include/linux/usb/ehci_def.h +@@ -111,7 +111,13 @@ struct ehci_regs { + /* ASYNCLISTADDR: offset 0x18 */ + u32 async_next; /* address of next async queue head */ + +- u32 reserved[9]; ++ u32 reserved1[2]; ++ ++ /* TXFILLTUNING: offset 0x24 */ ++ u32 txfill_tuning; /* TX FIFO Tuning register */ ++#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */ ++ ++ u32 reserved2[6]; + + /* CONFIGFLAG: offset 0x40 */ + u32 configured_flag; +@@ -155,26 +161,35 @@ struct ehci_regs { + #define PORT_CSC (1<<1) /* connect status change */ + #define PORT_CONNECT (1<<0) /* device connected */ + #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) +-}; + +-#define USBMODE 0x68 /* USB Device mode */ ++ u32 reserved3[9]; ++ ++ /* USBMODE: offset 0x68 */ ++ u32 usbmode; /* USB Device mode */ + #define USBMODE_SDIS (1<<3) /* Stream disable */ + #define USBMODE_BE (1<<2) /* BE/LE endianness select */ + #define USBMODE_CM_HC (3<<0) /* host controller mode */ + #define USBMODE_CM_IDLE (0<<0) /* idle state */ + ++ u32 reserved4[7]; ++ + /* Moorestown has some non-standard registers, partially due to the fact that + * its EHCI controller has both TT and LPM support. HOSTPCx are extensions to + * PORTSCx + */ ++ /* HOSTPC: offset 0x84 */ ++ u32 hostpc[0]; /* HOSTPC extension */ + #define HOSTPC0 0x84 /* HOSTPC extension */ + #define HOSTPC_PHCD (1<<22) /* Phy clock disable */ + #define HOSTPC_PSPD (3<<25) /* Port speed detection */ +-#define USBMODE_EX 0xc8 /* USB Device mode extension */ ++ ++ u32 reserved5[17]; ++ ++ /* USBMODE_EX: offset 0xc8 */ ++ u32 usbmode_ex; /* USB Device mode extension */ + #define USBMODE_EX_VBPS (1<<5) /* VBus Power Select On */ + #define USBMODE_EX_HC (3<<0) /* host controller mode */ +-#define TXFILLTUNING 0x24 /* TX FIFO Tuning register */ +-#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */ ++}; + + /* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index 4fc3e5d..c4ad44f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch new file mode 100644 index 00000000..044284b2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_usb_hcd.h.patch @@ -0,0 +1,16 @@ +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -128,8 +128,11 @@ struct usb_hcd { + unsigned wireless:1; /* Wireless USB HCD */ + unsigned authorized_default:1; + unsigned has_tt:1; /* Integrated TT in root hub */ ++#ifndef __GENKSYMS__ + unsigned cant_recv_wakeups:1; + /* wakeup requests from downstream aren't received */ ++ /* 24 bits spare */ ++#endif + + int irq; /* irq allocated */ + void __iomem *regs; /* device memory/io */ +diff --git a/include/linux/virtio.h b/include/linux/virtio.h +index e4807af..f12924f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch new file mode 100644 index 00000000..02b29ea9 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_vmalloc.h.patch @@ -0,0 +1,12 @@ +--- a/include/linux/vmalloc.h ++++ b/include/linux/vmalloc.h +@@ -131,6 +131,7 @@ extern long vwrite(char *buf, char *addr, unsigned long count); + */ + extern rwlock_t vmlist_lock; + extern struct vm_struct *vmlist; ++extern __init void vm_area_add_early(struct vm_struct *vm); + extern __init void vm_area_register_early(struct vm_struct *vm, size_t align); + + #ifdef CONFIG_SMP +diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h +index 111843f..6e4e300 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch new file mode 100644 index 00000000..caf4c26d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_linux_watchdog.h.patch @@ -0,0 +1,18 @@ +--- a/include/linux/watchdog.h ++++ b/include/linux/watchdog.h +@@ -122,6 +122,13 @@ struct watchdog_device { + #define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */ + }; + ++/* Use the following function to set the nowayout feature */ ++static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout) ++{ ++ if (nowayout) ++ set_bit(WDOG_NO_WAY_OUT, &wdd->status); ++} ++ + /* Use the following functions to manipulate watchdog driver specific data */ + static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) + { +diff --git a/include/net/addrconf.h b/include/net/addrconf.h +index 44b1110..401ed48 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch b/packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch new file mode 100644 index 00000000..5297b973 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/include_trace_syscall.h.patch @@ -0,0 +1,14 @@ +--- a/include/trace/syscall.h ++++ b/include/trace/syscall.h +@@ -4,7 +4,9 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include ++#endif + + #include + +diff --git a/init/Kconfig b/init/Kconfig +index b8dc1de..d37670d 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch new file mode 100644 index 00000000..0c5d86b3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/init_Kconfig.patch @@ -0,0 +1,19 @@ +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -660,6 +660,14 @@ config CGROUP_MEM_RES_CTLR + This config option also selects MM_OWNER config option, which + could in turn add some fork/exit overhead. + ++config CGROUP_MEM_RES_CTLR_DISABLED ++ bool "Memory Resource Controller disabled by default" ++ depends on CGROUP_MEM_RES_CTLR ++ default n ++ help ++ Disable the memory group resource controller unless explicitly ++ enabled using the kernel parameter "cgroup_enable=memory". ++ + config CGROUP_MEM_RES_CTLR_SWAP + bool "Memory Resource Controller Swap Extension" + depends on CGROUP_MEM_RES_CTLR && SWAP +diff --git a/kernel/audit.c b/kernel/audit.c +index e14bc74..51420a8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch b/packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch new file mode 100644 index 00000000..f0e75bd7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/kernel-fs-overlayfs-inode.patch @@ -0,0 +1,12 @@ +diff -uNpr a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +--- a/fs/overlayfs/inode.c 2015-04-07 13:55:17.487864270 -0700 ++++ b/fs/overlayfs/inode.c 2015-04-07 13:56:24.948259512 -0700 +@@ -68,7 +68,7 @@ int ovl_permission(struct inode *inode, + spin_unlock(&inode->i_lock); + return -ENOENT; + } +- alias = list_entry(inode->i_dentry.next, struct dentry, d_alias); ++ alias = list_entry(inode->i_dentry.next, struct dentry, d_u.d_alias); + dget(alias); + spin_unlock(&inode->i_lock); + oe = alias->d_fsdata; diff --git a/packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch b/packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch new file mode 100644 index 00000000..f336a65f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/kernel-overlayfs-v11.patch @@ -0,0 +1,3178 @@ +--- /dev/null ++++ b/Documentation/filesystems/overlayfs.txt +@@ -0,0 +1,199 @@ ++Written by: Neil Brown ++ ++Overlay Filesystem ++================== ++ ++This document describes a prototype for a new approach to providing ++overlay-filesystem functionality in Linux (sometimes referred to as ++union-filesystems). An overlay-filesystem tries to present a ++filesystem which is the result over overlaying one filesystem on top ++of the other. ++ ++The result will inevitably fail to look exactly like a normal ++filesystem for various technical reasons. The expectation is that ++many use cases will be able to ignore these differences. ++ ++This approach is 'hybrid' because the objects that appear in the ++filesystem do not all appear to belong to that filesystem. In many ++cases an object accessed in the union will be indistinguishable ++from accessing the corresponding object from the original filesystem. ++This is most obvious from the 'st_dev' field returned by stat(2). ++ ++While directories will report an st_dev from the overlay-filesystem, ++all non-directory objects will report an st_dev from the lower or ++upper filesystem that is providing the object. Similarly st_ino will ++only be unique when combined with st_dev, and both of these can change ++over the lifetime of a non-directory object. Many applications and ++tools ignore these values and will not be affected. ++ ++Upper and Lower ++--------------- ++ ++An overlay filesystem combines two filesystems - an 'upper' filesystem ++and a 'lower' filesystem. When a name exists in both filesystems, the ++object in the 'upper' filesystem is visible while the object in the ++'lower' filesystem is either hidden or, in the case of directories, ++merged with the 'upper' object. ++ ++It would be more correct to refer to an upper and lower 'directory ++tree' rather than 'filesystem' as it is quite possible for both ++directory trees to be in the same filesystem and there is no ++requirement that the root of a filesystem be given for either upper or ++lower. ++ ++The lower filesystem can be any filesystem supported by Linux and does ++not need to be writable. The lower filesystem can even be another ++overlayfs. The upper filesystem will normally be writable and if it ++is it must support the creation of trusted.* extended attributes, and ++must provide valid d_type in readdir responses, at least for symbolic ++links - so NFS is not suitable. ++ ++A read-only overlay of two read-only filesystems may use any ++filesystem type. ++ ++Directories ++----------- ++ ++Overlaying mainly involved directories. If a given name appears in both ++upper and lower filesystems and refers to a non-directory in either, ++then the lower object is hidden - the name refers only to the upper ++object. ++ ++Where both upper and lower objects are directories, a merged directory ++is formed. ++ ++At mount time, the two directories given as mount options are combined ++into a merged directory: ++ ++ mount -t overlayfs overlayfs -olowerdir=/lower,upperdir=/upper /overlay ++ ++Then whenever a lookup is requested in such a merged directory, the ++lookup is performed in each actual directory and the combined result ++is cached in the dentry belonging to the overlay filesystem. If both ++actual lookups find directories, both are stored and a merged ++directory is created, otherwise only one is stored: the upper if it ++exists, else the lower. ++ ++Only the lists of names from directories are merged. Other content ++such as metadata and extended attributes are reported for the upper ++directory only. These attributes of the lower directory are hidden. ++ ++whiteouts and opaque directories ++-------------------------------- ++ ++In order to support rm and rmdir without changing the lower ++filesystem, an overlay filesystem needs to record in the upper filesystem ++that files have been removed. This is done using whiteouts and opaque ++directories (non-directories are always opaque). ++ ++The overlay filesystem uses extended attributes with a ++"trusted.overlay." prefix to record these details. ++ ++A whiteout is created as a symbolic link with target ++"(overlay-whiteout)" and with xattr "trusted.overlay.whiteout" set to "y". ++When a whiteout is found in the upper level of a merged directory, any ++matching name in the lower level is ignored, and the whiteout itself ++is also hidden. ++ ++A directory is made opaque by setting the xattr "trusted.overlay.opaque" ++to "y". Where the upper filesystem contains an opaque directory, any ++directory in the lower filesystem with the same name is ignored. ++ ++readdir ++------- ++ ++When a 'readdir' request is made on a merged directory, the upper and ++lower directories are each read and the name lists merged in the ++obvious way (upper is read first, then lower - entries that already ++exist are not re-added). This merged name list is cached in the ++'struct file' and so remains as long as the file is kept open. If the ++directory is opened and read by two processes at the same time, they ++will each have separate caches. A seekdir to the start of the ++directory (offset 0) followed by a readdir will cause the cache to be ++discarded and rebuilt. ++ ++This means that changes to the merged directory do not appear while a ++directory is being read. This is unlikely to be noticed by many ++programs. ++ ++seek offsets are assigned sequentially when the directories are read. ++Thus if ++ - read part of a directory ++ - remember an offset, and close the directory ++ - re-open the directory some time later ++ - seek to the remembered offset ++ ++there may be little correlation between the old and new locations in ++the list of filenames, particularly if anything has changed in the ++directory. ++ ++Readdir on directories that are not merged is simply handled by the ++underlying directory (upper or lower). ++ ++ ++Non-directories ++--------------- ++ ++Objects that are not directories (files, symlinks, device-special ++files etc.) are presented either from the upper or lower filesystem as ++appropriate. When a file in the lower filesystem is accessed in a way ++the requires write-access, such as opening for write access, changing ++some metadata etc., the file is first copied from the lower filesystem ++to the upper filesystem (copy_up). Note that creating a hard-link ++also requires copy_up, though of course creation of a symlink does ++not. ++ ++The copy_up may turn out to be unnecessary, for example if the file is ++opened for read-write but the data is not modified. ++ ++The copy_up process first makes sure that the containing directory ++exists in the upper filesystem - creating it and any parents as ++necessary. It then creates the object with the same metadata (owner, ++mode, mtime, symlink-target etc.) and then if the object is a file, the ++data is copied from the lower to the upper filesystem. Finally any ++extended attributes are copied up. ++ ++Once the copy_up is complete, the overlay filesystem simply ++provides direct access to the newly created file in the upper ++filesystem - future operations on the file are barely noticed by the ++overlay filesystem (though an operation on the name of the file such as ++rename or unlink will of course be noticed and handled). ++ ++ ++Non-standard behavior ++--------------------- ++ ++The copy_up operation essentially creates a new, identical file and ++moves it over to the old name. The new file may be on a different ++filesystem, so both st_dev and st_ino of the file may change. ++ ++Any open files referring to this inode will access the old data and ++metadata. Similarly any file locks obtained before copy_up will not ++apply to the copied up file. ++ ++On a file is opened with O_RDONLY fchmod(2), fchown(2), futimesat(2) ++and fsetxattr(2) will fail with EROFS. ++ ++If a file with multiple hard links is copied up, then this will ++"break" the link. Changes will not be propagated to other names ++referring to the same inode. ++ ++Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory ++object in overlayfs will not contain vaid absolute paths, only ++relative paths leading up to the filesystem's root. This will be ++fixed in the future. ++ ++Some operations are not atomic, for example a crash during copy_up or ++rename will leave the filesystem in an inconsitent state. This will ++be addressed in the future. ++ ++Changes to underlying filesystems ++--------------------------------- ++ ++Offline changes, when the overlay is not mounted, are allowed to either ++the upper or the lower trees. ++ ++Changes to the underlying filesystems while part of a mounted overlay ++filesystem are not allowed. If the underlying filesystem is changed, ++the behavior of the overlay is undefined, though it will not result in ++a crash or deadlock. + +diff --git a/MAINTAINERS b/MAINTAINERS +index 768ceee..6701e5a 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -4910,6 +4910,13 @@ F: drivers/scsi/osd/ + F: include/scsi/osd_* + F: fs/exofs/ + ++OVERLAYFS FILESYSTEM ++M: Miklos Szeredi ++L: linux-fsdevel@vger.kernel.org ++S: Supported ++F: fs/overlayfs/* ++F: Documentation/filesystems/overlayfs.txt ++ + P54 WIRELESS DRIVER + M: Christian Lamparter + L: linux-wireless@vger.kernel.org +diff --git a/fs/Kconfig b/fs/Kconfig +index ded2ffb..7f618e9 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -63,6 +63,7 @@ source "fs/quota/Kconfig" + + source "fs/autofs4/Kconfig" + source "fs/fuse/Kconfig" ++source "fs/overlayfs/Kconfig" + + config CUSE + tristate "Character device in Userspace support" +diff --git a/fs/Makefile b/fs/Makefile +index 680ad8a..1727784 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -104,6 +104,7 @@ obj-$(CONFIG_QNX4FS_FS) += qnx4/ + obj-$(CONFIG_AUTOFS4_FS) += autofs4/ + obj-$(CONFIG_ADFS_FS) += adfs/ + obj-$(CONFIG_FUSE_FS) += fuse/ ++obj-$(CONFIG_OVERLAYFS_FS) += overlayfs/ + obj-$(CONFIG_UDF_FS) += udf/ + obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ + obj-$(CONFIG_OMFS_FS) += omfs/ +diff --git a/fs/namespace.c b/fs/namespace.c +index 99d2154..0719c07 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1493,6 +1493,23 @@ void drop_collected_mounts(struct vfsmount *mnt) + release_mounts(&umount_list); + } + ++struct vfsmount *clone_private_mount(struct path *path) ++{ ++ struct vfsmount *mnt; ++ ++ if (IS_MNT_UNBINDABLE(path->mnt)) ++ return ERR_PTR(-EINVAL); ++ ++ down_read(&namespace_sem); ++ mnt = clone_mnt(path->mnt, path->dentry, CL_PRIVATE); ++ up_read(&namespace_sem); ++ if (!mnt) ++ return ERR_PTR(-ENOMEM); ++ ++ return mnt; ++} ++EXPORT_SYMBOL_GPL(clone_private_mount); ++ + int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, + struct vfsmount *root) + { +diff --git a/fs/open.c b/fs/open.c +index a57313e..1d4de26 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -645,8 +645,7 @@ static inline int __get_file_write_access(struct inode *inode, + return error; + } + +-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, +- struct file *f, ++static struct file *__dentry_open(struct path *path, struct file *f, + int (*open)(struct inode *, struct file *), + const struct cred *cred) + { +@@ -654,15 +653,16 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, + struct inode *inode; + int error; + ++ path_get(path); + f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | + FMODE_PREAD | FMODE_PWRITE; + + if (unlikely(f->f_flags & O_PATH)) + f->f_mode = FMODE_PATH; + +- inode = dentry->d_inode; ++ inode = path->dentry->d_inode; + if (f->f_mode & FMODE_WRITE) { +- error = __get_file_write_access(inode, mnt); ++ error = __get_file_write_access(inode, path->mnt); + if (error) + goto cleanup_file; + if (!special_file(inode->i_mode)) +@@ -670,8 +670,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, + } + + f->f_mapping = inode->i_mapping; +- f->f_path.dentry = dentry; +- f->f_path.mnt = mnt; ++ f->f_path = *path; + f->f_pos = 0; + file_sb_list_add(f, inode->i_sb); + +@@ -728,7 +727,7 @@ cleanup_all: + * here, so just reset the state. + */ + file_reset_write(f); +- mnt_drop_write(mnt); ++ mnt_drop_write(path->mnt); + } + } + file_sb_list_del(f); +@@ -736,8 +735,7 @@ cleanup_all: + f->f_path.mnt = NULL; + cleanup_file: + put_filp(f); +- dput(dentry); +- mntput(mnt); ++ path_put(path); + return ERR_PTR(error); + } + +@@ -763,14 +761,14 @@ cleanup_file: + struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, + int (*open)(struct inode *, struct file *)) + { ++ struct path path = { .dentry = dentry, .mnt = nd->path.mnt }; + const struct cred *cred = current_cred(); + + if (IS_ERR(nd->intent.open.file)) + goto out; + if (IS_ERR(dentry)) + goto out_err; +- nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), +- nd->intent.open.file, ++ nd->intent.open.file = __dentry_open(&path, nd->intent.open.file, + open, cred); + out: + return nd->intent.open.file; +@@ -799,10 +797,17 @@ struct file *nameidata_to_filp(struct nameidata *nd) + + /* Has the filesystem initialised the file for us? */ + if (filp->f_path.dentry == NULL) { +- path_get(&nd->path); +- filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, +- NULL, cred); ++ struct inode *inode = nd->path.dentry->d_inode; ++ ++ if (inode->i_op->open) { ++ int flags = filp->f_flags; ++ put_filp(filp); ++ filp = inode->i_op->open(nd->path.dentry, flags, cred); ++ } else { ++ filp = __dentry_open(&nd->path, filp, NULL, cred); ++ } + } ++ + return filp; + } + +@@ -813,26 +818,45 @@ struct file *nameidata_to_filp(struct nameidata *nd) + struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, + const struct cred *cred) + { +- int error; +- struct file *f; +- +- validate_creds(cred); ++ struct path path = { .dentry = dentry, .mnt = mnt }; ++ struct file *ret; + + /* We must always pass in a valid mount pointer. */ + BUG_ON(!mnt); + +- error = -ENFILE; ++ ret = vfs_open(&path, flags, cred); ++ path_put(&path); ++ ++ return ret; ++} ++EXPORT_SYMBOL(dentry_open); ++ ++/** ++ * vfs_open - open the file at the given path ++ * @path: path to open ++ * @flags: open flags ++ * @cred: credentials to use ++ * ++ * Open the file. If successful, the returned file will have acquired ++ * an additional reference for path. ++ */ ++struct file *vfs_open(struct path *path, int flags, const struct cred *cred) ++{ ++ struct file *f; ++ struct inode *inode = path->dentry->d_inode; ++ ++ validate_creds(cred); ++ ++ if (inode->i_op->open) ++ return inode->i_op->open(path->dentry, flags, cred); + f = get_empty_filp(); +- if (f == NULL) { +- dput(dentry); +- mntput(mnt); +- return ERR_PTR(error); +- } ++ if (f == NULL) ++ return ERR_PTR(-ENFILE); + + f->f_flags = flags; +- return __dentry_open(dentry, mnt, f, NULL, cred); ++ return __dentry_open(path, f, NULL, cred); + } +-EXPORT_SYMBOL(dentry_open); ++EXPORT_SYMBOL(vfs_open); + + static void __put_unused_fd(struct files_struct *files, unsigned int fd) + { +diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig +new file mode 100644 +index 0000000..c4517da +--- /dev/null ++++ b/fs/overlayfs/Kconfig +@@ -0,0 +1,4 @@ ++config OVERLAYFS_FS ++ tristate "Overlay filesystem support" ++ help ++ Add support for overlay filesystem. +diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile +new file mode 100644 +index 0000000..8f91889 +--- /dev/null ++++ b/fs/overlayfs/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for the overlay filesystem. ++# ++ ++obj-$(CONFIG_OVERLAYFS_FS) += overlayfs.o ++ ++overlayfs-objs := super.o inode.o dir.o readdir.o copy_up.o +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +new file mode 100644 +index 0000000..308a80a +--- /dev/null ++++ b/fs/overlayfs/copy_up.c +@@ -0,0 +1,383 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include "overlayfs.h" ++ ++#define OVL_COPY_UP_CHUNK_SIZE (1 << 20) ++ ++static int ovl_copy_up_xattr(struct dentry *old, struct dentry *new) ++{ ++ ssize_t list_size, size; ++ char *buf, *name, *value; ++ int error; ++ ++ if (!old->d_inode->i_op->getxattr || ++ !new->d_inode->i_op->getxattr) ++ return 0; ++ ++ list_size = vfs_listxattr(old, NULL, 0); ++ if (list_size <= 0) { ++ if (list_size == -EOPNOTSUPP) ++ return 0; ++ return list_size; ++ } ++ ++ buf = kzalloc(list_size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ error = -ENOMEM; ++ value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL); ++ if (!value) ++ goto out; ++ ++ list_size = vfs_listxattr(old, buf, list_size); ++ if (list_size <= 0) { ++ error = list_size; ++ goto out_free_value; ++ } ++ ++ for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { ++ size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX); ++ if (size <= 0) { ++ error = size; ++ goto out_free_value; ++ } ++ error = vfs_setxattr(new, name, value, size, 0); ++ if (error) ++ goto out_free_value; ++ } ++ ++out_free_value: ++ kfree(value); ++out: ++ kfree(buf); ++ return error; ++} ++ ++static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) ++{ ++ struct file *old_file; ++ struct file *new_file; ++ int error = 0; ++ ++ if (len == 0) ++ return 0; ++ ++ old_file = vfs_open(old, O_RDONLY, current_cred()); ++ if (IS_ERR(old_file)) ++ return PTR_ERR(old_file); ++ ++ new_file = vfs_open(new, O_WRONLY, current_cred()); ++ if (IS_ERR(new_file)) { ++ error = PTR_ERR(new_file); ++ goto out_fput; ++ } ++ ++ /* FIXME: copy up sparse files efficiently */ ++ while (len) { ++ loff_t offset = new_file->f_pos; ++ size_t this_len = OVL_COPY_UP_CHUNK_SIZE; ++ long bytes; ++ ++ if (len < this_len) ++ this_len = len; ++ ++ if (signal_pending_state(TASK_KILLABLE, current)) { ++ error = -EINTR; ++ break; ++ } ++ ++ bytes = do_splice_direct(old_file, &offset, new_file, this_len, ++ SPLICE_F_MOVE); ++ if (bytes <= 0) { ++ error = bytes; ++ break; ++ } ++ ++ len -= bytes; ++ } ++ ++ fput(new_file); ++out_fput: ++ fput(old_file); ++ return error; ++} ++ ++static char *ovl_read_symlink(struct dentry *realdentry) ++{ ++ int res; ++ char *buf; ++ struct inode *inode = realdentry->d_inode; ++ mm_segment_t old_fs; ++ ++ res = -EINVAL; ++ if (!inode->i_op->readlink) ++ goto err; ++ ++ res = -ENOMEM; ++ buf = (char *) __get_free_page(GFP_KERNEL); ++ if (!buf) ++ goto err; ++ ++ old_fs = get_fs(); ++ set_fs(get_ds()); ++ /* The cast to a user pointer is valid due to the set_fs() */ ++ res = inode->i_op->readlink(realdentry, ++ (char __user *)buf, PAGE_SIZE - 1); ++ set_fs(old_fs); ++ if (res < 0) { ++ free_page((unsigned long) buf); ++ goto err; ++ } ++ buf[res] = '\0'; ++ ++ return buf; ++ ++err: ++ return ERR_PTR(res); ++} ++ ++static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) ++{ ++ struct iattr attr = { ++ .ia_valid = ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, ++ .ia_atime = stat->atime, ++ .ia_mtime = stat->mtime, ++ }; ++ ++ return notify_change(upperdentry, &attr); ++} ++ ++static int ovl_set_mode(struct dentry *upperdentry, umode_t mode) ++{ ++ struct iattr attr = { ++ .ia_valid = ATTR_MODE, ++ .ia_mode = mode, ++ }; ++ ++ return notify_change(upperdentry, &attr); ++} ++ ++static int ovl_copy_up_locked(struct dentry *upperdir, struct dentry *dentry, ++ struct path *lowerpath, struct kstat *stat, ++ const char *link) ++{ ++ int err; ++ struct path newpath; ++ umode_t mode = stat->mode; ++ ++ /* Can't properly set mode on creation because of the umask */ ++ stat->mode &= S_IFMT; ++ ++ ovl_path_upper(dentry, &newpath); ++ WARN_ON(newpath.dentry); ++ newpath.dentry = ovl_upper_create(upperdir, dentry, stat, link); ++ if (IS_ERR(newpath.dentry)) ++ return PTR_ERR(newpath.dentry); ++ ++ if (S_ISREG(stat->mode)) { ++ err = ovl_copy_up_data(lowerpath, &newpath, stat->size); ++ if (err) ++ goto err_remove; ++ } ++ ++ err = ovl_copy_up_xattr(lowerpath->dentry, newpath.dentry); ++ if (err) ++ goto err_remove; ++ ++ mutex_lock(&newpath.dentry->d_inode->i_mutex); ++ if (!S_ISLNK(stat->mode)) ++ err = ovl_set_mode(newpath.dentry, mode); ++ if (!err) ++ err = ovl_set_timestamps(newpath.dentry, stat); ++ mutex_unlock(&newpath.dentry->d_inode->i_mutex); ++ if (err) ++ goto err_remove; ++ ++ ovl_dentry_update(dentry, newpath.dentry); ++ ++ /* ++ * Easiest way to get rid of the lower dentry reference is to ++ * drop this dentry. This is neither needed nor possible for ++ * directories. ++ */ ++ if (!S_ISDIR(stat->mode)) ++ d_drop(dentry); ++ ++ return 0; ++ ++err_remove: ++ if (S_ISDIR(stat->mode)) ++ vfs_rmdir(upperdir->d_inode, newpath.dentry); ++ else ++ vfs_unlink(upperdir->d_inode, newpath.dentry); ++ ++ dput(newpath.dentry); ++ ++ return err; ++} ++ ++/* ++ * Copy up a single dentry ++ * ++ * Directory renames only allowed on "pure upper" (already created on ++ * upper filesystem, never copied up). Directories which are on lower or ++ * are merged may not be renamed. For these -EXDEV is returned and ++ * userspace has to deal with it. This means, when copying up a ++ * directory we can rely on it and ancestors being stable. ++ * ++ * Non-directory renames start with copy up of source if necessary. The ++ * actual rename will only proceed once the copy up was successful. Copy ++ * up uses upper parent i_mutex for exclusion. Since rename can change ++ * d_parent it is possible that the copy up will lock the old parent. At ++ * that point the file will have already been copied up anyway. ++ */ ++static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, ++ struct path *lowerpath, struct kstat *stat) ++{ ++ int err; ++ struct kstat pstat; ++ struct path parentpath; ++ struct dentry *upperdir; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ char *link = NULL; ++ ++ ovl_path_upper(parent, &parentpath); ++ upperdir = parentpath.dentry; ++ ++ err = vfs_getattr(parentpath.mnt, parentpath.dentry, &pstat); ++ if (err) ++ return err; ++ ++ if (S_ISLNK(stat->mode)) { ++ link = ovl_read_symlink(lowerpath->dentry); ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ } ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_free_link; ++ ++ override_cred->fsuid = stat->uid; ++ override_cred->fsgid = stat->gid; ++ /* ++ * CAP_SYS_ADMIN for copying up extended attributes ++ * CAP_DAC_OVERRIDE for create ++ * CAP_FOWNER for chmod, timestamp update ++ * CAP_FSETID for chmod ++ * CAP_MKNOD for mknod ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ cap_raise(override_cred->cap_effective, CAP_FSETID); ++ cap_raise(override_cred->cap_effective, CAP_MKNOD); ++ old_cred = override_creds(override_cred); ++ ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ if (ovl_path_type(dentry) != OVL_PATH_LOWER) { ++ err = 0; ++ } else { ++ err = ovl_copy_up_locked(upperdir, dentry, lowerpath, ++ stat, link); ++ if (!err) { ++ /* Restore timestamps on parent (best effort) */ ++ ovl_set_timestamps(upperdir, &pstat); ++ } ++ } ++ ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++out_free_link: ++ if (link) ++ free_page((unsigned long) link); ++ ++ return err; ++} ++ ++int ovl_copy_up(struct dentry *dentry) ++{ ++ int err; ++ ++ err = 0; ++ while (!err) { ++ struct dentry *next; ++ struct dentry *parent; ++ struct path lowerpath; ++ struct kstat stat; ++ enum ovl_path_type type = ovl_path_type(dentry); ++ ++ if (type != OVL_PATH_LOWER) ++ break; ++ ++ next = dget(dentry); ++ /* find the topmost dentry not yet copied up */ ++ for (;;) { ++ parent = dget_parent(next); ++ ++ type = ovl_path_type(parent); ++ if (type != OVL_PATH_LOWER) ++ break; ++ ++ dput(next); ++ next = parent; ++ } ++ ++ ovl_path_lower(next, &lowerpath); ++ err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); ++ if (!err) ++ err = ovl_copy_up_one(parent, next, &lowerpath, &stat); ++ ++ dput(parent); ++ dput(next); ++ } ++ ++ return err; ++} ++ ++/* Optimize by not copying up the file first and truncating later */ ++int ovl_copy_up_truncate(struct dentry *dentry, loff_t size) ++{ ++ int err; ++ struct kstat stat; ++ struct path lowerpath; ++ struct dentry *parent = dget_parent(dentry); ++ ++ err = ovl_copy_up(parent); ++ if (err) ++ goto out_dput_parent; ++ ++ ovl_path_lower(dentry, &lowerpath); ++ err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); ++ if (err) ++ goto out_dput_parent; ++ ++ if (size < stat.size) ++ stat.size = size; ++ ++ err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); ++ ++out_dput_parent: ++ dput(parent); ++ return err; ++} +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +new file mode 100644 +index 0000000..834bed8 +--- /dev/null ++++ b/fs/overlayfs/dir.c +@@ -0,0 +1,596 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include "overlayfs.h" ++ ++static const char *ovl_whiteout_symlink = "(overlay-whiteout)"; ++ ++static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry) ++{ ++ int err; ++ struct dentry *newdentry; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ /* FIXME: recheck lower dentry to see if whiteout is really needed */ ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out; ++ ++ /* ++ * CAP_SYS_ADMIN for setxattr ++ * CAP_DAC_OVERRIDE for symlink creation ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ override_cred->fsuid = 0; ++ override_cred->fsgid = 0; ++ old_cred = override_creds(override_cred); ++ ++ newdentry = lookup_one_len(dentry->d_name.name, upperdir, ++ dentry->d_name.len); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_put_cred; ++ ++ /* Just been removed within the same locked region */ ++ WARN_ON(newdentry->d_inode); ++ ++ err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink); ++ if (err) ++ goto out_dput; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ ++ err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0); ++ if (err) ++ vfs_unlink(upperdir->d_inode, newdentry); ++ ++out_dput: ++ dput(newdentry); ++out_put_cred: ++ revert_creds(old_cred); ++ put_cred(override_cred); ++out: ++ if (err) { ++ /* ++ * There's no way to recover from failure to whiteout. ++ * What should we do? Log a big fat error and... ? ++ */ ++ printk(KERN_ERR "overlayfs: ERROR - failed to whiteout '%s'\n", ++ dentry->d_name.name); ++ } ++ ++ return err; ++} ++ ++static struct dentry *ovl_lookup_create(struct dentry *upperdir, ++ struct dentry *template) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct qstr *name = &template->d_name; ++ ++ newdentry = lookup_one_len(name->name, upperdir, name->len); ++ if (IS_ERR(newdentry)) ++ return newdentry; ++ ++ if (newdentry->d_inode) { ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ /* No need to check whiteout if lower parent is non-existent */ ++ err = -EEXIST; ++ if (!ovl_dentry_lower(template->d_parent)) ++ goto out_dput; ++ ++ if (!S_ISLNK(newdentry->d_inode->i_mode)) ++ goto out_dput; ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_dput; ++ ++ /* ++ * CAP_SYS_ADMIN for getxattr ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ old_cred = override_creds(override_cred); ++ ++ err = -EEXIST; ++ if (ovl_is_whiteout(newdentry)) ++ err = vfs_unlink(upperdir->d_inode, newdentry); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ if (err) ++ goto out_dput; ++ ++ dput(newdentry); ++ newdentry = lookup_one_len(name->name, upperdir, name->len); ++ if (IS_ERR(newdentry)) { ++ ovl_whiteout(upperdir, template); ++ return newdentry; ++ } ++ ++ /* ++ * Whiteout just been successfully removed, parent ++ * i_mutex is still held, there's no way the lookup ++ * could return positive. ++ */ ++ WARN_ON(newdentry->d_inode); ++ } ++ ++ return newdentry; ++ ++out_dput: ++ dput(newdentry); ++ return ERR_PTR(err); ++} ++ ++struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, ++ struct kstat *stat, const char *link) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct inode *dir = upperdir->d_inode; ++ ++ newdentry = ovl_lookup_create(upperdir, dentry); ++ if (IS_ERR(newdentry)) ++ goto out; ++ ++ switch (stat->mode & S_IFMT) { ++ case S_IFREG: ++ err = vfs_create(dir, newdentry, stat->mode, NULL); ++ break; ++ ++ case S_IFDIR: ++ err = vfs_mkdir(dir, newdentry, stat->mode); ++ break; ++ ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ err = vfs_mknod(dir, newdentry, stat->mode, stat->rdev); ++ break; ++ ++ case S_IFLNK: ++ err = vfs_symlink(dir, newdentry, link); ++ break; ++ ++ default: ++ err = -EPERM; ++ } ++ if (err) { ++ if (ovl_dentry_is_opaque(dentry)) ++ ovl_whiteout(upperdir, dentry); ++ dput(newdentry); ++ newdentry = ERR_PTR(err); ++ } else if (WARN_ON(!newdentry->d_inode)) { ++ /* ++ * Not quite sure if non-instantiated dentry is legal or not. ++ * VFS doesn't seem to care so check and warn here. ++ */ ++ dput(newdentry); ++ newdentry = ERR_PTR(-ENOENT); ++ } ++ ++out: ++ return newdentry; ++ ++} ++ ++static int ovl_set_opaque(struct dentry *upperdentry) ++{ ++ int err; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* CAP_SYS_ADMIN for setxattr of "trusted" namespace */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0); ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++static int ovl_remove_opaque(struct dentry *upperdentry) ++{ ++ int err; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* CAP_SYS_ADMIN for removexattr of "trusted" namespace */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ err = vfs_removexattr(upperdentry, ovl_opaque_xattr); ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, ++ struct kstat *stat) ++{ ++ int err; ++ enum ovl_path_type type; ++ struct path realpath; ++ ++ type = ovl_path_real(dentry, &realpath); ++ err = vfs_getattr(realpath.mnt, realpath.dentry, stat); ++ if (err) ++ return err; ++ ++ stat->dev = dentry->d_sb->s_dev; ++ stat->ino = dentry->d_inode->i_ino; ++ ++ /* ++ * It's probably not worth it to count subdirs to get the ++ * correct link count. nlink=1 seems to pacify 'find' and ++ * other utilities. ++ */ ++ if (type == OVL_PATH_MERGE) ++ stat->nlink = 1; ++ ++ return 0; ++} ++ ++static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, ++ const char *link) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct dentry *upperdir; ++ struct inode *inode; ++ struct kstat stat = { ++ .mode = mode, ++ .rdev = rdev, ++ }; ++ ++ err = -ENOMEM; ++ inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata); ++ if (!inode) ++ goto out; ++ ++ err = ovl_copy_up(dentry->d_parent); ++ if (err) ++ goto out_iput; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ ++ newdentry = ovl_upper_create(upperdir, dentry, &stat, link); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ if (ovl_dentry_is_opaque(dentry) && S_ISDIR(mode)) { ++ err = ovl_set_opaque(newdentry); ++ if (err) { ++ vfs_rmdir(upperdir->d_inode, newdentry); ++ ovl_whiteout(upperdir, dentry); ++ goto out_dput; ++ } ++ } ++ ovl_dentry_update(dentry, newdentry); ++ d_instantiate(dentry, inode); ++ inode = NULL; ++ newdentry = NULL; ++ err = 0; ++ ++out_dput: ++ dput(newdentry); ++out_unlock: ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++out_iput: ++ iput(inode); ++out: ++ return err; ++} ++ ++static int ovl_create(struct inode *dir, struct dentry *dentry, int mode, ++ struct nameidata *nd) ++{ ++ return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL); ++} ++ ++static int ovl_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++{ ++ return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL); ++} ++ ++static int ovl_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ dev_t rdev) ++{ ++ return ovl_create_object(dentry, mode, rdev, NULL); ++} ++ ++static int ovl_symlink(struct inode *dir, struct dentry *dentry, ++ const char *link) ++{ ++ return ovl_create_object(dentry, S_IFLNK, 0, link); ++} ++ ++static int ovl_do_remove(struct dentry *dentry, bool is_dir) ++{ ++ int err; ++ enum ovl_path_type type; ++ struct path realpath; ++ struct dentry *upperdir; ++ ++ err = ovl_copy_up(dentry->d_parent); ++ if (err) ++ return err; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ type = ovl_path_real(dentry, &realpath); ++ if (type != OVL_PATH_LOWER) { ++ err = -ESTALE; ++ if (realpath.dentry->d_parent != upperdir) ++ goto out_d_drop; ++ ++ /* FIXME: create whiteout up front and rename to target */ ++ ++ if (is_dir) ++ err = vfs_rmdir(upperdir->d_inode, realpath.dentry); ++ else ++ err = vfs_unlink(upperdir->d_inode, realpath.dentry); ++ if (err) ++ goto out_d_drop; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ } ++ ++ if (type != OVL_PATH_UPPER || ovl_dentry_is_opaque(dentry)) ++ err = ovl_whiteout(upperdir, dentry); ++ ++ /* ++ * Keeping this dentry hashed would mean having to release ++ * upperpath/lowerpath, which could only be done if we are the ++ * sole user of this dentry. Too tricky... Just unhash for ++ * now. ++ */ ++out_d_drop: ++ d_drop(dentry); ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++ return err; ++} ++ ++static int ovl_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ return ovl_do_remove(dentry, false); ++} ++ ++ ++static int ovl_rmdir(struct inode *dir, struct dentry *dentry) ++{ ++ int err; ++ enum ovl_path_type type; ++ ++ type = ovl_path_type(dentry); ++ if (type != OVL_PATH_UPPER) { ++ err = ovl_check_empty_and_clear(dentry, type); ++ if (err) ++ return err; ++ } ++ ++ return ovl_do_remove(dentry, true); ++} ++ ++static int ovl_link(struct dentry *old, struct inode *newdir, ++ struct dentry *new) ++{ ++ int err; ++ struct dentry *olddentry; ++ struct dentry *newdentry; ++ struct dentry *upperdir; ++ ++ err = ovl_copy_up(old); ++ if (err) ++ goto out; ++ ++ err = ovl_copy_up(new->d_parent); ++ if (err) ++ goto out; ++ ++ upperdir = ovl_dentry_upper(new->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ newdentry = ovl_lookup_create(upperdir, new); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ ++ olddentry = ovl_dentry_upper(old); ++ err = vfs_link(olddentry, upperdir->d_inode, newdentry); ++ if (!err) { ++ if (WARN_ON(!newdentry->d_inode)) { ++ dput(newdentry); ++ err = -ENOENT; ++ goto out_unlock; ++ } ++ ++ ovl_dentry_version_inc(new->d_parent); ++ ovl_dentry_update(new, newdentry); ++ ++ ihold(old->d_inode); ++ d_instantiate(new, old->d_inode); ++ } else { ++ if (ovl_dentry_is_opaque(new)) ++ ovl_whiteout(upperdir, new); ++ dput(newdentry); ++ } ++out_unlock: ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++out: ++ return err; ++ ++} ++ ++static int ovl_rename(struct inode *olddir, struct dentry *old, ++ struct inode *newdir, struct dentry *new) ++{ ++ int err; ++ enum ovl_path_type old_type; ++ enum ovl_path_type new_type; ++ struct dentry *old_upperdir; ++ struct dentry *new_upperdir; ++ struct dentry *olddentry; ++ struct dentry *newdentry; ++ struct dentry *trap; ++ bool old_opaque; ++ bool new_opaque; ++ bool new_create = false; ++ bool is_dir = S_ISDIR(old->d_inode->i_mode); ++ ++ /* Don't copy up directory trees */ ++ old_type = ovl_path_type(old); ++ if (old_type != OVL_PATH_UPPER && is_dir) ++ return -EXDEV; ++ ++ if (new->d_inode) { ++ new_type = ovl_path_type(new); ++ ++ if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) { ++ if (ovl_dentry_lower(old)->d_inode == ++ ovl_dentry_lower(new)->d_inode) ++ return 0; ++ } ++ if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) { ++ if (ovl_dentry_upper(old)->d_inode == ++ ovl_dentry_upper(new)->d_inode) ++ return 0; ++ } ++ ++ if (new_type != OVL_PATH_UPPER && ++ S_ISDIR(new->d_inode->i_mode)) { ++ err = ovl_check_empty_and_clear(new, new_type); ++ if (err) ++ return err; ++ } ++ } else { ++ new_type = OVL_PATH_UPPER; ++ } ++ ++ err = ovl_copy_up(old); ++ if (err) ++ return err; ++ ++ err = ovl_copy_up(new->d_parent); ++ if (err) ++ return err; ++ ++ old_upperdir = ovl_dentry_upper(old->d_parent); ++ new_upperdir = ovl_dentry_upper(new->d_parent); ++ ++ trap = lock_rename(new_upperdir, old_upperdir); ++ ++ olddentry = ovl_dentry_upper(old); ++ newdentry = ovl_dentry_upper(new); ++ if (newdentry) { ++ dget(newdentry); ++ } else { ++ new_create = true; ++ newdentry = ovl_lookup_create(new_upperdir, new); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ } ++ ++ err = -ESTALE; ++ if (olddentry->d_parent != old_upperdir) ++ goto out_dput; ++ if (newdentry->d_parent != new_upperdir) ++ goto out_dput; ++ if (olddentry == trap) ++ goto out_dput; ++ if (newdentry == trap) ++ goto out_dput; ++ ++ old_opaque = ovl_dentry_is_opaque(old); ++ new_opaque = ovl_dentry_is_opaque(new) || new_type != OVL_PATH_UPPER; ++ ++ if (is_dir && !old_opaque && new_opaque) { ++ err = ovl_set_opaque(olddentry); ++ if (err) ++ goto out_dput; ++ } ++ ++ err = vfs_rename(old_upperdir->d_inode, olddentry, ++ new_upperdir->d_inode, newdentry); ++ ++ if (err) { ++ if (new_create && ovl_dentry_is_opaque(new)) ++ ovl_whiteout(new_upperdir, new); ++ if (is_dir && !old_opaque && new_opaque) ++ ovl_remove_opaque(olddentry); ++ goto out_dput; ++ } ++ ++ if (old_type != OVL_PATH_UPPER || old_opaque) ++ err = ovl_whiteout(old_upperdir, old); ++ if (is_dir && old_opaque && !new_opaque) ++ ovl_remove_opaque(olddentry); ++ ++ if (old_opaque != new_opaque) ++ ovl_dentry_set_opaque(old, new_opaque); ++ ++ ovl_dentry_version_inc(old->d_parent); ++ ovl_dentry_version_inc(new->d_parent); ++ ++out_dput: ++ dput(newdentry); ++out_unlock: ++ unlock_rename(new_upperdir, old_upperdir); ++ return err; ++} ++ ++const struct inode_operations ovl_dir_inode_operations = { ++ .lookup = ovl_lookup, ++ .mkdir = ovl_mkdir, ++ .symlink = ovl_symlink, ++ .unlink = ovl_unlink, ++ .rmdir = ovl_rmdir, ++ .rename = ovl_rename, ++ .link = ovl_link, ++ .setattr = ovl_setattr, ++ .create = ovl_create, ++ .mknod = ovl_mknod, ++ .permission = ovl_permission, ++ .getattr = ovl_dir_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++}; +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +new file mode 100644 +index 0000000..40b79d0 +--- /dev/null ++++ b/fs/overlayfs/inode.c +@@ -0,0 +1,383 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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 ++#include ++#include ++#include "overlayfs.h" ++ ++int ovl_setattr(struct dentry *dentry, struct iattr *attr) ++{ ++ struct dentry *upperdentry; ++ int err; ++ ++ if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry)) ++ err = ovl_copy_up_truncate(dentry, attr->ia_size); ++ else ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ upperdentry = ovl_dentry_upper(dentry); ++ ++ if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) ++ attr->ia_valid &= ~ATTR_MODE; ++ ++ mutex_lock(&upperdentry->d_inode->i_mutex); ++ err = notify_change(upperdentry, attr); ++ mutex_unlock(&upperdentry->d_inode->i_mutex); ++ ++ return err; ++} ++ ++static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, ++ struct kstat *stat) ++{ ++ struct path realpath; ++ ++ ovl_path_real(dentry, &realpath); ++ return vfs_getattr(realpath.mnt, realpath.dentry, stat); ++} ++ ++int ovl_permission(struct inode *inode, int mask) ++{ ++ struct ovl_entry *oe; ++ struct dentry *alias = NULL; ++ struct inode *realinode; ++ struct dentry *realdentry; ++ bool is_upper; ++ int err; ++ ++ if (S_ISDIR(inode->i_mode)) { ++ oe = inode->i_private; ++ } else if (mask & MAY_NOT_BLOCK) { ++ return -ECHILD; ++ } else { ++ /* ++ * For non-directories find an alias and get the info ++ * from there. ++ */ ++ spin_lock(&inode->i_lock); ++ if (WARN_ON(list_empty(&inode->i_dentry))) { ++ spin_unlock(&inode->i_lock); ++ return -ENOENT; ++ } ++ alias = list_entry(inode->i_dentry.next, struct dentry, d_alias); ++ dget(alias); ++ spin_unlock(&inode->i_lock); ++ oe = alias->d_fsdata; ++ } ++ ++ realdentry = ovl_entry_real(oe, &is_upper); ++ ++ /* Careful in RCU walk mode */ ++ realinode = ACCESS_ONCE(realdentry->d_inode); ++ if (!realinode) { ++ WARN_ON(!(mask & MAY_NOT_BLOCK)); ++ err = -ENOENT; ++ goto out_dput; ++ } ++ ++ if (mask & MAY_WRITE) { ++ umode_t mode = realinode->i_mode; ++ ++ /* ++ * Writes will always be redirected to upper layer, so ++ * ignore lower layer being read-only. ++ * ++ * If the overlay itself is read-only then proceed ++ * with the permission check, don't return EROFS. ++ * This will only happen if this is the lower layer of ++ * another overlayfs. ++ * ++ * If upper fs becomes read-only after the overlay was ++ * constructed return EROFS to prevent modification of ++ * upper layer. ++ */ ++ err = -EROFS; ++ if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && ++ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) ++ goto out_dput; ++ ++ /* ++ * Nobody gets write access to an immutable file. ++ */ ++ err = -EACCES; ++ if (IS_IMMUTABLE(realinode)) ++ goto out_dput; ++ } ++ ++ if (realinode->i_op->permission) ++ err = realinode->i_op->permission(realinode, mask); ++ else ++ err = generic_permission(realinode, mask); ++out_dput: ++ dput(alias); ++ return err; ++} ++ ++ ++struct ovl_link_data { ++ struct dentry *realdentry; ++ void *cookie; ++}; ++ ++static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ void *ret; ++ struct dentry *realdentry; ++ struct inode *realinode; ++ ++ realdentry = ovl_dentry_real(dentry); ++ realinode = realdentry->d_inode; ++ ++ if (WARN_ON(!realinode->i_op->follow_link)) ++ return ERR_PTR(-EPERM); ++ ++ ret = realinode->i_op->follow_link(realdentry, nd); ++ if (IS_ERR(ret)) ++ return ret; ++ ++ if (realinode->i_op->put_link) { ++ struct ovl_link_data *data; ++ ++ data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL); ++ if (!data) { ++ realinode->i_op->put_link(realdentry, nd, ret); ++ return ERR_PTR(-ENOMEM); ++ } ++ data->realdentry = realdentry; ++ data->cookie = ret; ++ ++ return data; ++ } else { ++ return NULL; ++ } ++} ++ ++static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c) ++{ ++ struct inode *realinode; ++ struct ovl_link_data *data = c; ++ ++ if (!data) ++ return; ++ ++ realinode = data->realdentry->d_inode; ++ realinode->i_op->put_link(data->realdentry, nd, data->cookie); ++ kfree(data); ++} ++ ++static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) ++{ ++ struct path realpath; ++ struct inode *realinode; ++ ++ ovl_path_real(dentry, &realpath); ++ realinode = realpath.dentry->d_inode; ++ ++ if (!realinode->i_op->readlink) ++ return -EINVAL; ++ ++ touch_atime(realpath.mnt, realpath.dentry); ++ ++ return realinode->i_op->readlink(realpath.dentry, buf, bufsiz); ++} ++ ++ ++static bool ovl_is_private_xattr(const char *name) ++{ ++ return strncmp(name, "trusted.overlay.", 14) == 0; ++} ++ ++int ovl_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ int err; ++ struct dentry *upperdentry; ++ ++ if (ovl_is_private_xattr(name)) ++ return -EPERM; ++ ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ upperdentry = ovl_dentry_upper(dentry); ++ return vfs_setxattr(upperdentry, name, value, size, flags); ++} ++ ++ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ++ void *value, size_t size) ++{ ++ if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ++ ovl_is_private_xattr(name)) ++ return -ENODATA; ++ ++ return vfs_getxattr(ovl_dentry_real(dentry), name, value, size); ++} ++ ++ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) ++{ ++ ssize_t res; ++ int off; ++ ++ res = vfs_listxattr(ovl_dentry_real(dentry), list, size); ++ if (res <= 0 || size == 0) ++ return res; ++ ++ if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE) ++ return res; ++ ++ /* filter out private xattrs */ ++ for (off = 0; off < res;) { ++ char *s = list + off; ++ size_t slen = strlen(s) + 1; ++ ++ BUG_ON(off + slen > res); ++ ++ if (ovl_is_private_xattr(s)) { ++ res -= slen; ++ memmove(s, s + slen, res - off); ++ } else { ++ off += slen; ++ } ++ } ++ ++ return res; ++} ++ ++int ovl_removexattr(struct dentry *dentry, const char *name) ++{ ++ int err; ++ struct path realpath; ++ enum ovl_path_type type; ++ ++ if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ++ ovl_is_private_xattr(name)) ++ return -ENODATA; ++ ++ type = ovl_path_real(dentry, &realpath); ++ if (type == OVL_PATH_LOWER) { ++ err = vfs_getxattr(realpath.dentry, name, NULL, 0); ++ if (err < 0) ++ return err; ++ ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ ovl_path_upper(dentry, &realpath); ++ } ++ ++ return vfs_removexattr(realpath.dentry, name); ++} ++ ++static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, ++ struct dentry *realdentry) ++{ ++ if (type != OVL_PATH_LOWER) ++ return false; ++ ++ if (special_file(realdentry->d_inode->i_mode)) ++ return false; ++ ++ if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC)) ++ return false; ++ ++ return true; ++} ++ ++static struct file *ovl_open(struct dentry *dentry, int flags, ++ const struct cred *cred) ++{ ++ int err; ++ struct path realpath; ++ enum ovl_path_type type; ++ ++ type = ovl_path_real(dentry, &realpath); ++ if (ovl_open_need_copy_up(flags, type, realpath.dentry)) { ++ if (flags & O_TRUNC) ++ err = ovl_copy_up_truncate(dentry, 0); ++ else ++ err = ovl_copy_up(dentry); ++ if (err) ++ return ERR_PTR(err); ++ ++ ovl_path_upper(dentry, &realpath); ++ } ++ ++ return vfs_open(&realpath, flags, cred); ++} ++ ++static const struct inode_operations ovl_file_inode_operations = { ++ .setattr = ovl_setattr, ++ .permission = ovl_permission, ++ .getattr = ovl_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++ .open = ovl_open, ++}; ++ ++static const struct inode_operations ovl_symlink_inode_operations = { ++ .setattr = ovl_setattr, ++ .follow_link = ovl_follow_link, ++ .put_link = ovl_put_link, ++ .readlink = ovl_readlink, ++ .getattr = ovl_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++}; ++ ++struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, ++ struct ovl_entry *oe) ++{ ++ struct inode *inode; ++ ++ inode = new_inode(sb); ++ if (!inode) ++ return NULL; ++ ++ mode &= S_IFMT; ++ ++ inode->i_ino = get_next_ino(); ++ inode->i_mode = mode; ++ inode->i_flags |= S_NOATIME | S_NOCMTIME; ++ ++ switch (mode) { ++ case S_IFDIR: ++ inode->i_private = oe; ++ inode->i_op = &ovl_dir_inode_operations; ++ inode->i_fop = &ovl_dir_operations; ++ break; ++ ++ case S_IFLNK: ++ inode->i_op = &ovl_symlink_inode_operations; ++ break; ++ ++ case S_IFREG: ++ case S_IFSOCK: ++ case S_IFBLK: ++ case S_IFCHR: ++ case S_IFIFO: ++ inode->i_op = &ovl_file_inode_operations; ++ break; ++ ++ default: ++ WARN(1, "illegal file type: %i\n", mode); ++ inode = NULL; ++ } ++ ++ return inode; ++ ++} +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +new file mode 100644 +index 0000000..07a1fe9 +--- /dev/null ++++ b/fs/overlayfs/overlayfs.h +@@ -0,0 +1,63 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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. ++ */ ++ ++struct ovl_entry; ++ ++enum ovl_path_type { ++ OVL_PATH_UPPER, ++ OVL_PATH_MERGE, ++ OVL_PATH_LOWER, ++}; ++ ++extern const char *ovl_opaque_xattr; ++extern const char *ovl_whiteout_xattr; ++extern const struct dentry_operations ovl_dentry_operations; ++ ++enum ovl_path_type ovl_path_type(struct dentry *dentry); ++u64 ovl_dentry_version_get(struct dentry *dentry); ++void ovl_dentry_version_inc(struct dentry *dentry); ++void ovl_path_upper(struct dentry *dentry, struct path *path); ++void ovl_path_lower(struct dentry *dentry, struct path *path); ++enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); ++struct dentry *ovl_dentry_upper(struct dentry *dentry); ++struct dentry *ovl_dentry_lower(struct dentry *dentry); ++struct dentry *ovl_dentry_real(struct dentry *dentry); ++struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper); ++bool ovl_dentry_is_opaque(struct dentry *dentry); ++void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque); ++bool ovl_is_whiteout(struct dentry *dentry); ++void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); ++struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd); ++ ++struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, ++ struct kstat *stat, const char *link); ++ ++/* readdir.c */ ++extern const struct file_operations ovl_dir_operations; ++int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type); ++ ++/* inode.c */ ++int ovl_setattr(struct dentry *dentry, struct iattr *attr); ++int ovl_permission(struct inode *inode, int mask); ++int ovl_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags); ++ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ++ void *value, size_t size); ++ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); ++int ovl_removexattr(struct dentry *dentry, const char *name); ++ ++struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, ++ struct ovl_entry *oe); ++/* dir.c */ ++extern const struct inode_operations ovl_dir_inode_operations; ++ ++/* copy_up.c */ ++int ovl_copy_up(struct dentry *dentry); ++int ovl_copy_up_truncate(struct dentry *dentry, loff_t size); +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +new file mode 100644 +index 0000000..6fcda39 +--- /dev/null ++++ b/fs/overlayfs/readdir.c +@@ -0,0 +1,559 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include "overlayfs.h" ++ ++struct ovl_cache_entry { ++ const char *name; ++ unsigned int len; ++ unsigned int type; ++ u64 ino; ++ bool is_whiteout; ++ struct list_head l_node; ++ struct rb_node node; ++}; ++ ++struct ovl_readdir_data { ++ struct rb_root *root; ++ struct list_head *list; ++ struct list_head *middle; ++ struct dentry *dir; ++ int count; ++ int err; ++}; ++ ++struct ovl_dir_file { ++ bool is_real; ++ bool is_cached; ++ struct list_head cursor; ++ u64 cache_version; ++ struct list_head cache; ++ struct file *realfile; ++}; ++ ++static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n) ++{ ++ return container_of(n, struct ovl_cache_entry, node); ++} ++ ++static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, ++ const char *name, int len) ++{ ++ struct rb_node *node = root->rb_node; ++ int cmp; ++ ++ while (node) { ++ struct ovl_cache_entry *p = ovl_cache_entry_from_node(node); ++ ++ cmp = strncmp(name, p->name, len); ++ if (cmp > 0) ++ node = p->node.rb_right; ++ else if (cmp < 0 || len < p->len) ++ node = p->node.rb_left; ++ else ++ return p; ++ } ++ ++ return NULL; ++} ++ ++static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len, ++ u64 ino, unsigned int d_type) ++{ ++ struct ovl_cache_entry *p; ++ ++ p = kmalloc(sizeof(*p) + len + 1, GFP_KERNEL); ++ if (p) { ++ char *name_copy = (char *) (p + 1); ++ memcpy(name_copy, name, len); ++ name_copy[len] = '\0'; ++ p->name = name_copy; ++ p->len = len; ++ p->type = d_type; ++ p->ino = ino; ++ p->is_whiteout = false; ++ } ++ ++ return p; ++} ++ ++static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd, ++ const char *name, int len, u64 ino, ++ unsigned int d_type) ++{ ++ struct rb_node **newp = &rdd->root->rb_node; ++ struct rb_node *parent = NULL; ++ struct ovl_cache_entry *p; ++ ++ while (*newp) { ++ int cmp; ++ struct ovl_cache_entry *tmp; ++ ++ parent = *newp; ++ tmp = ovl_cache_entry_from_node(*newp); ++ cmp = strncmp(name, tmp->name, len); ++ if (cmp > 0) ++ newp = &tmp->node.rb_right; ++ else if (cmp < 0 || len < tmp->len) ++ newp = &tmp->node.rb_left; ++ else ++ return 0; ++ } ++ ++ p = ovl_cache_entry_new(name, len, ino, d_type); ++ if (p == NULL) ++ return -ENOMEM; ++ ++ list_add_tail(&p->l_node, rdd->list); ++ rb_link_node(&p->node, parent, newp); ++ rb_insert_color(&p->node, rdd->root); ++ ++ return 0; ++} ++ ++static int ovl_fill_lower(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = buf; ++ struct ovl_cache_entry *p; ++ ++ rdd->count++; ++ p = ovl_cache_entry_find(rdd->root, name, namelen); ++ if (p) { ++ list_move_tail(&p->l_node, rdd->middle); ++ } else { ++ p = ovl_cache_entry_new(name, namelen, ino, d_type); ++ if (p == NULL) ++ rdd->err = -ENOMEM; ++ else ++ list_add_tail(&p->l_node, rdd->middle); ++ } ++ ++ return rdd->err; ++} ++ ++static void ovl_cache_free(struct list_head *list) ++{ ++ struct ovl_cache_entry *p; ++ struct ovl_cache_entry *n; ++ ++ list_for_each_entry_safe(p, n, list, l_node) ++ kfree(p); ++ ++ INIT_LIST_HEAD(list); ++} ++ ++static int ovl_fill_upper(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = buf; ++ ++ rdd->count++; ++ return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type); ++} ++ ++static inline int ovl_dir_read(struct path *realpath, ++ struct ovl_readdir_data *rdd, filldir_t filler) ++{ ++ struct file *realfile; ++ int err; ++ ++ realfile = vfs_open(realpath, O_RDONLY | O_DIRECTORY, current_cred()); ++ if (IS_ERR(realfile)) ++ return PTR_ERR(realfile); ++ ++ do { ++ rdd->count = 0; ++ rdd->err = 0; ++ err = vfs_readdir(realfile, filler, rdd); ++ if (err >= 0) ++ err = rdd->err; ++ } while (!err && rdd->count); ++ fput(realfile); ++ ++ return 0; ++} ++ ++static void ovl_dir_reset(struct file *file) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ enum ovl_path_type type = ovl_path_type(file->f_path.dentry); ++ ++ if (ovl_dentry_version_get(file->f_path.dentry) != od->cache_version) { ++ list_del_init(&od->cursor); ++ ovl_cache_free(&od->cache); ++ od->is_cached = false; ++ } ++ WARN_ON(!od->is_real && type != OVL_PATH_MERGE); ++ if (od->is_real && type == OVL_PATH_MERGE) { ++ fput(od->realfile); ++ od->realfile = NULL; ++ od->is_real = false; ++ } ++} ++ ++static int ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd) ++{ ++ struct ovl_cache_entry *p; ++ struct dentry *dentry; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) { ++ ovl_cache_free(rdd->list); ++ return -ENOMEM; ++ } ++ ++ /* ++ * CAP_SYS_ADMIN for getxattr ++ * CAP_DAC_OVERRIDE for lookup ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ old_cred = override_creds(override_cred); ++ ++ mutex_lock(&rdd->dir->d_inode->i_mutex); ++ list_for_each_entry(p, rdd->list, l_node) { ++ if (p->type != DT_LNK) ++ continue; ++ ++ dentry = lookup_one_len(p->name, rdd->dir, p->len); ++ if (IS_ERR(dentry)) ++ continue; ++ ++ p->is_whiteout = ovl_is_whiteout(dentry); ++ dput(dentry); ++ } ++ mutex_unlock(&rdd->dir->d_inode->i_mutex); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return 0; ++} ++ ++static inline int ovl_dir_read_merged(struct path *upperpath, struct path *lowerpath, ++ struct ovl_readdir_data *rdd) ++{ ++ int err; ++ struct rb_root root = RB_ROOT; ++ struct list_head middle; ++ ++ rdd->root = &root; ++ if (upperpath->dentry) { ++ rdd->dir = upperpath->dentry; ++ err = ovl_dir_read(upperpath, rdd, ovl_fill_upper); ++ if (err) ++ goto out; ++ ++ err = ovl_dir_mark_whiteouts(rdd); ++ if (err) ++ goto out; ++ } ++ /* ++ * Insert lowerpath entries before upperpath ones, this allows ++ * offsets to be reasonably constant ++ */ ++ list_add(&middle, rdd->list); ++ rdd->middle = &middle; ++ err = ovl_dir_read(lowerpath, rdd, ovl_fill_lower); ++ list_del(&middle); ++out: ++ rdd->root = NULL; ++ ++ return err; ++} ++ ++static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) ++{ ++ struct list_head *l; ++ loff_t off; ++ ++ l = od->cache.next; ++ for (off = 0; off < pos; off++) { ++ if (l == &od->cache) ++ break; ++ l = l->next; ++ } ++ list_move_tail(&od->cursor, l); ++} ++ ++static int ovl_readdir(struct file *file, void *buf, filldir_t filler) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ int res; ++ ++ if (!file->f_pos) ++ ovl_dir_reset(file); ++ ++ if (od->is_real) { ++ res = vfs_readdir(od->realfile, filler, buf); ++ file->f_pos = od->realfile->f_pos; ++ ++ return res; ++ } ++ ++ if (!od->is_cached) { ++ struct path lowerpath; ++ struct path upperpath; ++ struct ovl_readdir_data rdd = { .list = &od->cache }; ++ ++ ovl_path_lower(file->f_path.dentry, &lowerpath); ++ ovl_path_upper(file->f_path.dentry, &upperpath); ++ ++ res = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd); ++ if (res) { ++ ovl_cache_free(rdd.list); ++ return res; ++ } ++ ++ od->cache_version = ovl_dentry_version_get(file->f_path.dentry); ++ od->is_cached = true; ++ ++ ovl_seek_cursor(od, file->f_pos); ++ } ++ ++ while (od->cursor.next != &od->cache) { ++ int over; ++ loff_t off; ++ struct ovl_cache_entry *p; ++ ++ p = list_entry(od->cursor.next, struct ovl_cache_entry, l_node); ++ off = file->f_pos; ++ if (!p->is_whiteout) { ++ over = filler(buf, p->name, p->len, off, p->ino, p->type); ++ if (over) ++ break; ++ } ++ file->f_pos++; ++ list_move(&od->cursor, &p->l_node); ++ } ++ ++ return 0; ++} ++ ++static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin) ++{ ++ loff_t res; ++ struct ovl_dir_file *od = file->private_data; ++ ++ mutex_lock(&file->f_dentry->d_inode->i_mutex); ++ if (!file->f_pos) ++ ovl_dir_reset(file); ++ ++ if (od->is_real) { ++ res = vfs_llseek(od->realfile, offset, origin); ++ file->f_pos = od->realfile->f_pos; ++ } else { ++ res = -EINVAL; ++ ++ switch (origin) { ++ case SEEK_CUR: ++ offset += file->f_pos; ++ break; ++ case SEEK_SET: ++ break; ++ default: ++ goto out_unlock; ++ } ++ if (offset < 0) ++ goto out_unlock; ++ ++ if (offset != file->f_pos) { ++ file->f_pos = offset; ++ if (od->is_cached) ++ ovl_seek_cursor(od, offset); ++ } ++ res = offset; ++ } ++out_unlock: ++ mutex_unlock(&file->f_dentry->d_inode->i_mutex); ++ ++ return res; ++} ++ ++static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, ++ int datasync) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ ++ /* May need to reopen directory if it got copied up */ ++ if (!od->realfile) { ++ struct path upperpath; ++ ++ ovl_path_upper(file->f_path.dentry, &upperpath); ++ od->realfile = vfs_open(&upperpath, O_RDONLY, current_cred()); ++ if (IS_ERR(od->realfile)) ++ return PTR_ERR(od->realfile); ++ } ++ ++ return vfs_fsync_range(od->realfile, start, end, datasync); ++} ++ ++static int ovl_dir_release(struct inode *inode, struct file *file) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ ++ list_del(&od->cursor); ++ ovl_cache_free(&od->cache); ++ if (od->realfile) ++ fput(od->realfile); ++ kfree(od); ++ ++ return 0; ++} ++ ++static int ovl_dir_open(struct inode *inode, struct file *file) ++{ ++ struct path realpath; ++ struct file *realfile; ++ struct ovl_dir_file *od; ++ enum ovl_path_type type; ++ ++ od = kzalloc(sizeof(struct ovl_dir_file), GFP_KERNEL); ++ if (!od) ++ return -ENOMEM; ++ ++ type = ovl_path_real(file->f_path.dentry, &realpath); ++ realfile = vfs_open(&realpath, file->f_flags, current_cred()); ++ if (IS_ERR(realfile)) { ++ kfree(od); ++ return PTR_ERR(realfile); ++ } ++ INIT_LIST_HEAD(&od->cache); ++ INIT_LIST_HEAD(&od->cursor); ++ od->is_cached = false; ++ od->realfile = realfile; ++ od->is_real = (type != OVL_PATH_MERGE); ++ file->private_data = od; ++ ++ return 0; ++} ++ ++const struct file_operations ovl_dir_operations = { ++ .read = generic_read_dir, ++ .open = ovl_dir_open, ++ .readdir = ovl_readdir, ++ .llseek = ovl_dir_llseek, ++ .fsync = ovl_dir_fsync, ++ .release = ovl_dir_release, ++}; ++ ++static int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) ++{ ++ int err; ++ struct path lowerpath; ++ struct path upperpath; ++ struct ovl_cache_entry *p; ++ struct ovl_readdir_data rdd = { .list = list }; ++ ++ ovl_path_upper(dentry, &upperpath); ++ ovl_path_lower(dentry, &lowerpath); ++ ++ err = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd); ++ if (err) ++ return err; ++ ++ err = 0; ++ ++ list_for_each_entry(p, list, l_node) { ++ if (p->is_whiteout) ++ continue; ++ ++ if (p->name[0] == '.') { ++ if (p->len == 1) ++ continue; ++ if (p->len == 2 && p->name[1] == '.') ++ continue; ++ } ++ err = -ENOTEMPTY; ++ break; ++ } ++ ++ return err; ++} ++ ++static int ovl_remove_whiteouts(struct dentry *dir, struct list_head *list) ++{ ++ struct path upperpath; ++ struct dentry *upperdir; ++ struct ovl_cache_entry *p; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ int err; ++ ++ ovl_path_upper(dir, &upperpath); ++ upperdir = upperpath.dentry; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* ++ * CAP_DAC_OVERRIDE for lookup and unlink ++ * CAP_SYS_ADMIN for setxattr of "trusted" namespace ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ old_cred = override_creds(override_cred); ++ ++ err = vfs_setxattr(upperdir, ovl_opaque_xattr, "y", 1, 0); ++ if (err) ++ goto out_revert_creds; ++ ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ list_for_each_entry(p, list, l_node) { ++ struct dentry *dentry; ++ int ret; ++ ++ if (!p->is_whiteout) ++ continue; ++ ++ dentry = lookup_one_len(p->name, upperdir, p->len); ++ if (IS_ERR(dentry)) { ++ printk(KERN_WARNING "overlayfs: failed to lookup whiteout %.*s: %li\n", p->len, p->name, PTR_ERR(dentry)); ++ continue; ++ } ++ ret = vfs_unlink(upperdir->d_inode, dentry); ++ dput(dentry); ++ if (ret) ++ printk(KERN_WARNING "overlayfs: failed to unlink whiteout %.*s: %i\n", p->len, p->name, ret); ++ } ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++out_revert_creds: ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type) ++{ ++ int err; ++ LIST_HEAD(list); ++ ++ err = ovl_check_empty_dir(dentry, &list); ++ if (!err && type == OVL_PATH_MERGE) ++ err = ovl_remove_whiteouts(dentry, &list); ++ ++ ovl_cache_free(&list); ++ ++ return err; ++} +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +new file mode 100644 +index 0000000..508cf19 +--- /dev/null ++++ b/fs/overlayfs/super.c +@@ -0,0 +1,656 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "overlayfs.h" ++ ++MODULE_AUTHOR("Miklos Szeredi "); ++MODULE_DESCRIPTION("Overlay filesystem"); ++MODULE_LICENSE("GPL"); ++ ++struct ovl_config { ++ char *lowerdir; ++ char *upperdir; ++}; ++ ++/* private information held for overlayfs's superblock */ ++struct ovl_fs { ++ struct vfsmount *upper_mnt; ++ struct vfsmount *lower_mnt; ++ /* pathnames of lower and upper dirs, for show_options */ ++ struct ovl_config config; ++}; ++ ++/* private information held for every overlayfs dentry */ ++struct ovl_entry { ++ /* ++ * Keep "double reference" on upper dentries, so that ++ * d_delete() doesn't think it's OK to reset d_inode to NULL. ++ */ ++ struct dentry *__upperdentry; ++ struct dentry *lowerdentry; ++ union { ++ struct { ++ u64 version; ++ bool opaque; ++ }; ++ struct rcu_head rcu; ++ }; ++}; ++ ++const char *ovl_whiteout_xattr = "trusted.overlay.whiteout"; ++const char *ovl_opaque_xattr = "trusted.overlay.opaque"; ++ ++ ++enum ovl_path_type ovl_path_type(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ if (oe->__upperdentry) { ++ if (oe->lowerdentry && S_ISDIR(dentry->d_inode->i_mode)) ++ return OVL_PATH_MERGE; ++ else ++ return OVL_PATH_UPPER; ++ } else { ++ return OVL_PATH_LOWER; ++ } ++} ++ ++static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) ++{ ++ struct dentry *upperdentry = ACCESS_ONCE(oe->__upperdentry); ++ smp_read_barrier_depends(); ++ return upperdentry; ++} ++ ++void ovl_path_upper(struct dentry *dentry, struct path *path) ++{ ++ struct ovl_fs *ofs = dentry->d_sb->s_fs_info; ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ path->mnt = ofs->upper_mnt; ++ path->dentry = ovl_upperdentry_dereference(oe); ++} ++ ++void ovl_path_lower(struct dentry *dentry, struct path *path) ++{ ++ struct ovl_fs *ofs = dentry->d_sb->s_fs_info; ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ path->mnt = ofs->lower_mnt; ++ path->dentry = oe->lowerdentry; ++} ++ ++enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) ++{ ++ ++ enum ovl_path_type type = ovl_path_type(dentry); ++ ++ if (type == OVL_PATH_LOWER) ++ ovl_path_lower(dentry, path); ++ else ++ ovl_path_upper(dentry, path); ++ ++ return type; ++} ++ ++struct dentry *ovl_dentry_upper(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ return ovl_upperdentry_dereference(oe); ++} ++ ++struct dentry *ovl_dentry_lower(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ return oe->lowerdentry; ++} ++ ++struct dentry *ovl_dentry_real(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ struct dentry *realdentry; ++ ++ realdentry = ovl_upperdentry_dereference(oe); ++ if (!realdentry) ++ realdentry = oe->lowerdentry; ++ ++ return realdentry; ++} ++ ++struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper) ++{ ++ struct dentry *realdentry; ++ ++ realdentry = ovl_upperdentry_dereference(oe); ++ if (realdentry) { ++ *is_upper = true; ++ } else { ++ realdentry = oe->lowerdentry; ++ *is_upper = false; ++ } ++ return realdentry; ++} ++ ++bool ovl_dentry_is_opaque(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ return oe->opaque; ++} ++ ++void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ oe->opaque = opaque; ++} ++ ++void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&upperdentry->d_parent->d_inode->i_mutex)); ++ WARN_ON(oe->__upperdentry); ++ BUG_ON(!upperdentry->d_inode); ++ smp_wmb(); ++ oe->__upperdentry = dget(upperdentry); ++} ++ ++void ovl_dentry_version_inc(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); ++ oe->version++; ++} ++ ++u64 ovl_dentry_version_get(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); ++ return oe->version; ++} ++ ++bool ovl_is_whiteout(struct dentry *dentry) ++{ ++ int res; ++ char val; ++ ++ if (!dentry) ++ return false; ++ if (!dentry->d_inode) ++ return false; ++ if (!S_ISLNK(dentry->d_inode->i_mode)) ++ return false; ++ ++ res = vfs_getxattr(dentry, ovl_whiteout_xattr, &val, 1); ++ if (res == 1 && val == 'y') ++ return true; ++ ++ return false; ++} ++ ++static bool ovl_is_opaquedir(struct dentry *dentry) ++{ ++ int res; ++ char val; ++ ++ if (!S_ISDIR(dentry->d_inode->i_mode)) ++ return false; ++ ++ res = vfs_getxattr(dentry, ovl_opaque_xattr, &val, 1); ++ if (res == 1 && val == 'y') ++ return true; ++ ++ return false; ++} ++ ++static void ovl_entry_free(struct rcu_head *head) ++{ ++ struct ovl_entry *oe = container_of(head, struct ovl_entry, rcu); ++ kfree(oe); ++} ++ ++static void ovl_dentry_release(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ if (oe) { ++ dput(oe->__upperdentry); ++ dput(oe->__upperdentry); ++ dput(oe->lowerdentry); ++ call_rcu(&oe->rcu, ovl_entry_free); ++ } ++} ++ ++const struct dentry_operations ovl_dentry_operations = { ++ .d_release = ovl_dentry_release, ++}; ++ ++static struct ovl_entry *ovl_alloc_entry(void) ++{ ++ return kzalloc(sizeof(struct ovl_entry), GFP_KERNEL); ++} ++ ++static inline struct dentry *ovl_lookup_real(struct dentry *dir, struct qstr *name) ++{ ++ struct dentry *dentry; ++ ++ mutex_lock(&dir->d_inode->i_mutex); ++ dentry = lookup_one_len(name->name, dir, name->len); ++ mutex_unlock(&dir->d_inode->i_mutex); ++ ++ if (IS_ERR(dentry)) { ++ if (PTR_ERR(dentry) == -ENOENT) ++ dentry = NULL; ++ } else if (!dentry->d_inode) { ++ dput(dentry); ++ dentry = NULL; ++ } ++ return dentry; ++} ++ ++static int ovl_do_lookup(struct dentry *dentry) ++{ ++ struct ovl_entry *oe; ++ struct dentry *upperdir; ++ struct dentry *lowerdir; ++ struct dentry *upperdentry = NULL; ++ struct dentry *lowerdentry = NULL; ++ struct inode *inode = NULL; ++ int err; ++ ++ err = -ENOMEM; ++ oe = ovl_alloc_entry(); ++ if (!oe) ++ goto out; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ lowerdir = ovl_dentry_lower(dentry->d_parent); ++ ++ if (upperdir) { ++ upperdentry = ovl_lookup_real(upperdir, &dentry->d_name); ++ err = PTR_ERR(upperdentry); ++ if (IS_ERR(upperdentry)) ++ goto out_put_dir; ++ ++ if (lowerdir && upperdentry && ++ (S_ISLNK(upperdentry->d_inode->i_mode) || ++ S_ISDIR(upperdentry->d_inode->i_mode))) { ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_dput_upper; ++ ++ /* CAP_SYS_ADMIN needed for getxattr */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ ++ if (ovl_is_opaquedir(upperdentry)) { ++ oe->opaque = true; ++ } else if (ovl_is_whiteout(upperdentry)) { ++ dput(upperdentry); ++ upperdentry = NULL; ++ oe->opaque = true; ++ } ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ } ++ } ++ if (lowerdir && !oe->opaque) { ++ lowerdentry = ovl_lookup_real(lowerdir, &dentry->d_name); ++ err = PTR_ERR(lowerdentry); ++ if (IS_ERR(lowerdentry)) ++ goto out_dput_upper; ++ } ++ ++ if (lowerdentry && upperdentry && ++ (!S_ISDIR(upperdentry->d_inode->i_mode) || ++ !S_ISDIR(lowerdentry->d_inode->i_mode))) { ++ dput(lowerdentry); ++ lowerdentry = NULL; ++ oe->opaque = true; ++ } ++ ++ if (lowerdentry || upperdentry) { ++ struct dentry *realdentry; ++ ++ realdentry = upperdentry ? upperdentry : lowerdentry; ++ err = -ENOMEM; ++ inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode, oe); ++ if (!inode) ++ goto out_dput; ++ } ++ ++ if (upperdentry) ++ oe->__upperdentry = dget(upperdentry); ++ ++ if (lowerdentry) ++ oe->lowerdentry = lowerdentry; ++ ++ dentry->d_fsdata = oe; ++ dentry->d_op = &ovl_dentry_operations; ++ d_add(dentry, inode); ++ ++ return 0; ++ ++out_dput: ++ dput(lowerdentry); ++out_dput_upper: ++ dput(upperdentry); ++out_put_dir: ++ kfree(oe); ++out: ++ return err; ++} ++ ++struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd) ++{ ++ int err = ovl_do_lookup(dentry); ++ ++ if (err) ++ return ERR_PTR(err); ++ ++ return NULL; ++} ++ ++static void ovl_put_super(struct super_block *sb) ++{ ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ if (!(sb->s_flags & MS_RDONLY)) ++ mnt_drop_write(ufs->upper_mnt); ++ ++ mntput(ufs->upper_mnt); ++ mntput(ufs->lower_mnt); ++ ++ kfree(ufs->config.lowerdir); ++ kfree(ufs->config.upperdir); ++ kfree(ufs); ++} ++ ++static int ovl_remount_fs(struct super_block *sb, int *flagsp, char *data) ++{ ++ int flags = *flagsp; ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ /* When remounting rw or ro, we need to adjust the write access to the ++ * upper fs. ++ */ ++ if (((flags ^ sb->s_flags) & MS_RDONLY) == 0) ++ /* No change to readonly status */ ++ return 0; ++ ++ if (flags & MS_RDONLY) { ++ mnt_drop_write(ufs->upper_mnt); ++ return 0; ++ } else ++ return mnt_want_write(ufs->upper_mnt); ++} ++ ++/** ++ * ovl_statfs ++ * @sb: The overlayfs super block ++ * @buf: The struct kstatfs to fill in with stats ++ * ++ * Get the filesystem statistics. As writes always target the upper layer ++ * filesystem pass the statfs to the same filesystem. ++ */ ++static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ struct dentry *root_dentry = dentry->d_sb->s_root; ++ struct path path; ++ ovl_path_upper(root_dentry, &path); ++ ++ if (!path.dentry->d_sb->s_op->statfs) ++ return -ENOSYS; ++ return path.dentry->d_sb->s_op->statfs(path.dentry, buf); ++} ++ ++/** ++ * ovl_show_options ++ * ++ * Prints the mount options for a given superblock. ++ * Returns zero; does not fail. ++ */ ++static int ovl_show_options(struct seq_file *m, struct vfsmount *mnt) ++{ ++ struct super_block *sb = mnt->mnt_sb; ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); ++ seq_printf(m, ",upperdir=%s", ufs->config.upperdir); ++ return 0; ++} ++ ++static const struct super_operations ovl_super_operations = { ++ .put_super = ovl_put_super, ++ .remount_fs = ovl_remount_fs, ++ .statfs = ovl_statfs, ++ .show_options = ovl_show_options, ++}; ++ ++enum { ++ Opt_lowerdir, ++ Opt_upperdir, ++ Opt_err, ++}; ++ ++static const match_table_t ovl_tokens = { ++ {Opt_lowerdir, "lowerdir=%s"}, ++ {Opt_upperdir, "upperdir=%s"}, ++ {Opt_err, NULL} ++}; ++ ++static int ovl_parse_opt(char *opt, struct ovl_config *config) ++{ ++ char *p; ++ ++ config->upperdir = NULL; ++ config->lowerdir = NULL; ++ ++ while ((p = strsep(&opt, ",")) != NULL) { ++ int token; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ if (!*p) ++ continue; ++ ++ token = match_token(p, ovl_tokens, args); ++ switch (token) { ++ case Opt_upperdir: ++ kfree(config->upperdir); ++ config->upperdir = match_strdup(&args[0]); ++ if (!config->upperdir) ++ return -ENOMEM; ++ break; ++ ++ case Opt_lowerdir: ++ kfree(config->lowerdir); ++ config->lowerdir = match_strdup(&args[0]); ++ if (!config->lowerdir) ++ return -ENOMEM; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++static int ovl_fill_super(struct super_block *sb, void *data, int silent) ++{ ++ struct path lowerpath; ++ struct path upperpath; ++ struct inode *root_inode; ++ struct dentry *root_dentry; ++ struct ovl_entry *oe; ++ struct ovl_fs *ufs; ++ int err; ++ ++ err = -ENOMEM; ++ ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); ++ if (!ufs) ++ goto out; ++ ++ err = ovl_parse_opt((char *) data, &ufs->config); ++ if (err) ++ goto out_free_ufs; ++ ++ err = -EINVAL; ++ if (!ufs->config.upperdir || !ufs->config.lowerdir) { ++ printk(KERN_ERR "overlayfs: missing upperdir or lowerdir\n"); ++ goto out_free_config; ++ } ++ ++ oe = ovl_alloc_entry(); ++ if (oe == NULL) ++ goto out_free_config; ++ ++ root_inode = ovl_new_inode(sb, S_IFDIR, oe); ++ if (!root_inode) ++ goto out_free_oe; ++ ++ err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath); ++ if (err) ++ goto out_put_root; ++ ++ err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath); ++ if (err) ++ goto out_put_upperpath; ++ ++ err = -ENOTDIR; ++ if (!S_ISDIR(upperpath.dentry->d_inode->i_mode) || ++ !S_ISDIR(lowerpath.dentry->d_inode->i_mode)) ++ goto out_put_lowerpath; ++ ++ sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth, ++ lowerpath.mnt->mnt_sb->s_stack_depth) + 1; ++ ++ err = -EINVAL; ++ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { ++ printk(KERN_ERR "overlayfs: maximum fs stacking depth exceeded\n"); ++ goto out_put_lowerpath; ++ } ++ ++ ++ ufs->upper_mnt = clone_private_mount(&upperpath); ++ err = PTR_ERR(ufs->upper_mnt); ++ if (IS_ERR(ufs->upper_mnt)) { ++ printk(KERN_ERR "overlayfs: failed to clone upperpath\n"); ++ goto out_put_lowerpath; ++ } ++ ++ ufs->lower_mnt = clone_private_mount(&lowerpath); ++ err = PTR_ERR(ufs->lower_mnt); ++ if (IS_ERR(ufs->lower_mnt)) { ++ printk(KERN_ERR "overlayfs: failed to clone lowerpath\n"); ++ goto out_put_upper_mnt; ++ } ++ ++ /* ++ * Make lower_mnt R/O. That way fchmod/fchown on lower file ++ * will fail instead of modifying lower fs. ++ */ ++ ufs->lower_mnt->mnt_flags |= MNT_READONLY; ++ ++ /* If the upper fs is r/o, we mark overlayfs r/o too */ ++ if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY) ++ sb->s_flags |= MS_RDONLY; ++ ++ if (!(sb->s_flags & MS_RDONLY)) { ++ err = mnt_want_write(ufs->upper_mnt); ++ if (err) ++ goto out_put_lower_mnt; ++ } ++ ++ err = -ENOMEM; ++ root_dentry = d_alloc_root(root_inode); ++ if (!root_dentry) ++ goto out_drop_write; ++ ++ mntput(upperpath.mnt); ++ mntput(lowerpath.mnt); ++ ++ oe->__upperdentry = dget(upperpath.dentry); ++ oe->lowerdentry = lowerpath.dentry; ++ ++ root_dentry->d_fsdata = oe; ++ root_dentry->d_op = &ovl_dentry_operations; ++ ++ sb->s_op = &ovl_super_operations; ++ sb->s_root = root_dentry; ++ sb->s_fs_info = ufs; ++ ++ return 0; ++ ++out_drop_write: ++ if (!(sb->s_flags & MS_RDONLY)) ++ mnt_drop_write(ufs->upper_mnt); ++out_put_lower_mnt: ++ mntput(ufs->lower_mnt); ++out_put_upper_mnt: ++ mntput(ufs->upper_mnt); ++out_put_lowerpath: ++ path_put(&lowerpath); ++out_put_upperpath: ++ path_put(&upperpath); ++out_put_root: ++ iput(root_inode); ++out_free_oe: ++ kfree(oe); ++out_free_config: ++ kfree(ufs->config.lowerdir); ++ kfree(ufs->config.upperdir); ++out_free_ufs: ++ kfree(ufs); ++out: ++ return err; ++} ++ ++static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *raw_data) ++{ ++ return mount_nodev(fs_type, flags, raw_data, ovl_fill_super); ++} ++ ++static struct file_system_type ovl_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "overlayfs", ++ .mount = ovl_mount, ++ .kill_sb = kill_anon_super, ++}; ++ ++static int __init ovl_init(void) ++{ ++ return register_filesystem(&ovl_fs_type); ++} ++ ++static void __exit ovl_exit(void) ++{ ++ unregister_filesystem(&ovl_fs_type); ++} ++ ++module_init(ovl_init); ++module_exit(ovl_exit); +diff --git a/fs/splice.c b/fs/splice.c +index 3bd1700..a12a11f 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1329,6 +1329,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + + return ret; + } ++EXPORT_SYMBOL(do_splice_direct); + + static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 269e920..2a1497c 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1656,6 +1667,7 @@ struct inode_operations { + void (*truncate_range)(struct inode *, loff_t, loff_t); + int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, + u64 len); ++ struct file *(*open)(struct dentry *, int flags, const struct cred *); + } ____cacheline_aligned; + + struct seq_file; +diff --git a/include/linux/mount.h b/include/linux/mount.h +index 33fe53d..30cd21e 100644 +--- a/include/linux/mount.h ++++ b/include/linux/mount.h +@@ -100,5 +100,8 @@ extern void mnt_pin(struct vfsmount *mnt); + extern void mnt_unpin(struct vfsmount *mnt); + extern int __mnt_is_readonly(struct vfsmount *mnt); + ++struct path; ++extern struct vfsmount *clone_private_mount(struct path *path); ++ + extern struct vfsmount *do_kern_mount(const char *fstype, int flags, + const char *name, void *data); + +--- original/include/linux/fs.h 2016-11-20 01:01:45.000000000 +0000 ++++ linux-3.2.84/include/linux/fs.h 2017-02-18 18:00:23.041049898 +0000 +@@ -2087,6 +2088,7 @@ extern struct file *file_open_root(struc + const char *, int, umode_t); + extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, + const struct cred *); ++extern struct file *vfs_open(struct path *, int flags, const struct cred *); + extern int filp_close(struct file *, fl_owner_t id); + extern char * getname(const char __user *); + diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch new file mode 100644 index 00000000..a16d6c5c --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.debug.patch @@ -0,0 +1,35 @@ +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -62,6 +62,14 @@ config MAGIC_SYSRQ + keys are documented in . Don't say Y + unless you really know what this hack does. + ++config MAGIC_SYSRQ_DEFAULT_MASK ++ hex "Default mask for Magic SysRq keys on the console" ++ depends on MAGIC_SYSRQ ++ default 1 ++ help ++ Specifies the default mask for the allowed SysRq keys. This can be ++ used to disable several sensitive keys by default. ++ + config STRIP_ASM_SYMS + bool "Strip assembler-generated symbols during link" + default n +@@ -278,6 +286,15 @@ config BOOTPARAM_HUNG_TASK_PANIC_VALUE + default 0 if !BOOTPARAM_HUNG_TASK_PANIC + default 1 if BOOTPARAM_HUNG_TASK_PANIC + ++config PANIC_TIMEOUT ++ int "panic timeout" ++ default 0 ++ help ++ Set the timeout value (in seconds) until a reboot occurs when the ++ the kernel panics. If n = 0, then we wait forever. A timeout ++ value n > 0 will wait n seconds before rebooting, while a timeout ++ value n < 0 will reboot immediately. ++ + config SCHED_DEBUG + bool "Collect scheduler debugging info" + depends on DEBUG_KERNEL && PROC_FS +diff --git a/lib/Makefile b/lib/Makefile +index c06efca..fba5b91 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch new file mode 100644 index 00000000..e881fc9d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_Kconfig.patch @@ -0,0 +1,14 @@ +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -244,6 +244,9 @@ config CPU_RMAP + bool + depends on SMP + ++config DQL ++ bool ++ + # + # Netlink attribute parsing support is select'ed if needed + # +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index 82928f5..005f0b9 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch new file mode 100644 index 00000000..32a1cdae --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_Makefile.patch @@ -0,0 +1,14 @@ +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -116,6 +116,8 @@ obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o + + obj-$(CONFIG_CORDIC) += cordic.o + ++obj-$(CONFIG_DQL) += dynamic_queue_limits.o ++ + hostprogs-y := gen_crc32table + clean-files := crc32table.h + +diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c +new file mode 100644 +index 0000000..0777c5a diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch b/packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch new file mode 100644 index 00000000..08a56ac3 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_dynamic_queue_limits.c.patch @@ -0,0 +1,143 @@ +--- /dev/null ++++ b/lib/dynamic_queue_limits.c +@@ -0,0 +1,138 @@ ++/* ++ * Dynamic byte queue limits. See include/linux/dynamic_queue_limits.h ++ * ++ * Copyright (c) 2011, Tom Herbert ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define POSDIFF(A, B) ((int)((A) - (B)) > 0 ? (A) - (B) : 0) ++#define AFTER_EQ(A, B) ((int)((A) - (B)) >= 0) ++ ++/* Records completed count and recalculates the queue limit */ ++void dql_completed(struct dql *dql, unsigned int count) ++{ ++ unsigned int inprogress, prev_inprogress, limit; ++ unsigned int ovlimit, completed, num_queued; ++ bool all_prev_completed; ++ ++ num_queued = ACCESS_ONCE(dql->num_queued); ++ ++ /* Can't complete more than what's in queue */ ++ BUG_ON(count > num_queued - dql->num_completed); ++ ++ completed = dql->num_completed + count; ++ limit = dql->limit; ++ ovlimit = POSDIFF(num_queued - dql->num_completed, limit); ++ inprogress = num_queued - completed; ++ prev_inprogress = dql->prev_num_queued - dql->num_completed; ++ all_prev_completed = AFTER_EQ(completed, dql->prev_num_queued); ++ ++ if ((ovlimit && !inprogress) || ++ (dql->prev_ovlimit && all_prev_completed)) { ++ /* ++ * Queue considered starved if: ++ * - The queue was over-limit in the last interval, ++ * and there is no more data in the queue. ++ * OR ++ * - The queue was over-limit in the previous interval and ++ * when enqueuing it was possible that all queued data ++ * had been consumed. This covers the case when queue ++ * may have becomes starved between completion processing ++ * running and next time enqueue was scheduled. ++ * ++ * When queue is starved increase the limit by the amount ++ * of bytes both sent and completed in the last interval, ++ * plus any previous over-limit. ++ */ ++ limit += POSDIFF(completed, dql->prev_num_queued) + ++ dql->prev_ovlimit; ++ dql->slack_start_time = jiffies; ++ dql->lowest_slack = UINT_MAX; ++ } else if (inprogress && prev_inprogress && !all_prev_completed) { ++ /* ++ * Queue was not starved, check if the limit can be decreased. ++ * A decrease is only considered if the queue has been busy in ++ * the whole interval (the check above). ++ * ++ * If there is slack, the amount of execess data queued above ++ * the the amount needed to prevent starvation, the queue limit ++ * can be decreased. To avoid hysteresis we consider the ++ * minimum amount of slack found over several iterations of the ++ * completion routine. ++ */ ++ unsigned int slack, slack_last_objs; ++ ++ /* ++ * Slack is the maximum of ++ * - The queue limit plus previous over-limit minus twice ++ * the number of objects completed. Note that two times ++ * number of completed bytes is a basis for an upper bound ++ * of the limit. ++ * - Portion of objects in the last queuing operation that ++ * was not part of non-zero previous over-limit. That is ++ * "round down" by non-overlimit portion of the last ++ * queueing operation. ++ */ ++ slack = POSDIFF(limit + dql->prev_ovlimit, ++ 2 * (completed - dql->num_completed)); ++ slack_last_objs = dql->prev_ovlimit ? ++ POSDIFF(dql->prev_last_obj_cnt, dql->prev_ovlimit) : 0; ++ ++ slack = max(slack, slack_last_objs); ++ ++ if (slack < dql->lowest_slack) ++ dql->lowest_slack = slack; ++ ++ if (time_after(jiffies, ++ dql->slack_start_time + dql->slack_hold_time)) { ++ limit = POSDIFF(limit, dql->lowest_slack); ++ dql->slack_start_time = jiffies; ++ dql->lowest_slack = UINT_MAX; ++ } ++ } ++ ++ /* Enforce bounds on limit */ ++ limit = clamp(limit, dql->min_limit, dql->max_limit); ++ ++ if (limit != dql->limit) { ++ dql->limit = limit; ++ ovlimit = 0; ++ } ++ ++ dql->adj_limit = limit + completed; ++ dql->prev_ovlimit = ovlimit; ++ dql->prev_last_obj_cnt = dql->last_obj_cnt; ++ dql->num_completed = completed; ++ dql->prev_num_queued = num_queued; ++} ++EXPORT_SYMBOL(dql_completed); ++ ++void dql_reset(struct dql *dql) ++{ ++ /* Reset all dynamic values */ ++ dql->limit = 0; ++ dql->num_queued = 0; ++ dql->num_completed = 0; ++ dql->last_obj_cnt = 0; ++ dql->prev_num_queued = 0; ++ dql->prev_last_obj_cnt = 0; ++ dql->prev_ovlimit = 0; ++ dql->lowest_slack = UINT_MAX; ++ dql->slack_start_time = jiffies; ++} ++EXPORT_SYMBOL(dql_reset); ++ ++int dql_init(struct dql *dql, unsigned hold_time) ++{ ++ dql->max_limit = DQL_MAX_LIMIT; ++ dql->min_limit = 0; ++ dql->slack_hold_time = hold_time; ++ dql_reset(dql); ++ return 0; ++} ++EXPORT_SYMBOL(dql_init); +diff --git a/lib/nlattr.c b/lib/nlattr.c +index be25e35..e7c6bca 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch b/packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch new file mode 100644 index 00000000..5f85fc54 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_nlattr.c.patch @@ -0,0 +1,15 @@ +--- a/lib/nlattr.c ++++ b/lib/nlattr.c +@@ -12,8 +12,10 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include + #include ++#endif + #include + #include + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 99093b3..058935e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch b/packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch new file mode 100644 index 00000000..4444356a --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/lib_swiotlb.c.patch @@ -0,0 +1,26 @@ +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -110,11 +110,11 @@ setup_io_tlb_npages(char *str) + __setup("swiotlb=", setup_io_tlb_npages); + /* make io_tlb_overflow tunable too? */ + +-unsigned long swioltb_nr_tbl(void) ++unsigned long swiotlb_nr_tbl(void) + { + return io_tlb_nslabs; + } +- ++EXPORT_SYMBOL_GPL(swiotlb_nr_tbl); + /* Note that this doesn't work with highmem page */ + static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, + volatile void *address) +@@ -321,6 +321,7 @@ void __init swiotlb_free(void) + free_bootmem_late(__pa(io_tlb_start), + PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); + } ++ io_tlb_nslabs = 0; + } + + static int is_swiotlb_buffer(phys_addr_t paddr) +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 2b49dd2..de77b4f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch new file mode 100644 index 00000000..25bd27c7 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_backing-dev.c.patch @@ -0,0 +1,13 @@ +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -225,7 +225,7 @@ static ssize_t max_ratio_store(struct device *dev, + } + BDI_SHOW(max_ratio, bdi->max_ratio) + +-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) ++//#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) + + static struct device_attribute bdi_dev_attrs[] = { + __ATTR_RW(read_ahead_kb), +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 204de6a..ebaebf8 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch new file mode 100644 index 00000000..374ecd05 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_memcontrol.c.patch @@ -0,0 +1,14 @@ +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5561,6 +5561,9 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, + + struct cgroup_subsys mem_cgroup_subsys = { + .name = "memory", ++#ifdef CONFIG_CGROUP_MEM_RES_CTLR_DISABLED ++ .disabled = 1, ++#endif + .subsys_id = mem_cgroup_subsys_id, + .create = mem_cgroup_create, + .pre_destroy = mem_cgroup_pre_destroy, +diff --git a/mm/rmap.c b/mm/rmap.c +index 98f0bf7..242fb4c 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch new file mode 100644 index 00000000..835e394d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_rmap.c.patch @@ -0,0 +1,14 @@ +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -56,7 +56,9 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include ++#endif + + #include + +diff --git a/mm/slab.c b/mm/slab.c +index aea5e42..7c11f1f 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch new file mode 100644 index 00000000..e8477483 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_slab.c.patch @@ -0,0 +1,13 @@ +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -121,6 +121,8 @@ + #include + #include + ++#include ++ + /* + * DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON. + * 0 for faster, smaller code (especially in the critical paths). +diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c +index 1b7e22a..22b7e18 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch new file mode 100644 index 00000000..136b3d2d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_sparse-vmemmap.c.patch @@ -0,0 +1,20 @@ +--- a/mm/sparse-vmemmap.c ++++ b/mm/sparse-vmemmap.c +@@ -53,10 +53,12 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node) + struct page *page; + + if (node_state(node, N_HIGH_MEMORY)) +- page = alloc_pages_node(node, +- GFP_KERNEL | __GFP_ZERO, get_order(size)); ++ page = alloc_pages_node( ++ node, GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT, ++ get_order(size)); + else +- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, ++ page = alloc_pages( ++ GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT, + get_order(size)); + if (page) + return page_address(page); +diff --git a/mm/swap.c b/mm/swap.c +index a4b9016..6f3642b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch new file mode 100644 index 00000000..329c1c8d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_swap.c.patch @@ -0,0 +1,14 @@ +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -31,7 +31,9 @@ + #include + #include + #include ++#ifndef __GENKSYMS__ + #include ++#endif + + #include "internal.h" + +diff --git a/mm/truncate.c b/mm/truncate.c +index 143883a..3915b9e 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch new file mode 100644 index 00000000..ee561779 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_truncate.c.patch @@ -0,0 +1,14 @@ +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -20,7 +20,9 @@ + #include /* grr. try_to_release_page, + do_invalidatepage */ + #include ++#ifndef __GENKSYMS__ + #include ++#endif + #include "internal.h" + + +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index 1431458..bfe67ef 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch new file mode 100644 index 00000000..93d1bb93 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_vmalloc.c.patch @@ -0,0 +1,47 @@ +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -1124,6 +1124,32 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro + EXPORT_SYMBOL(vm_map_ram); + + /** ++ * vm_area_add_early - add vmap area early during boot ++ * @vm: vm_struct to add ++ * ++ * This function is used to add fixed kernel vm area to vmlist before ++ * vmalloc_init() is called. @vm->addr, @vm->size, and @vm->flags ++ * should contain proper values and the other fields should be zero. ++ * ++ * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING. ++ */ ++void __init vm_area_add_early(struct vm_struct *vm) ++{ ++ struct vm_struct *tmp, **p; ++ ++ BUG_ON(vmap_initialized); ++ for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) { ++ if (tmp->addr >= vm->addr) { ++ BUG_ON(tmp->addr < vm->addr + vm->size); ++ break; ++ } else ++ BUG_ON(tmp->addr + tmp->size > vm->addr); ++ } ++ vm->next = *p; ++ *p = vm; ++} ++ ++/** + * vm_area_register_early - register vmap area early during boot + * @vm: vm_struct to register + * @align: requested alignment +@@ -1145,8 +1171,7 @@ void __init vm_area_register_early(struct vm_struct *vm, size_t align) + + vm->addr = (void *)addr; + +- vm->next = vmlist; +- vmlist = vm; ++ vm_area_add_early(vm); + } + + void __init vmalloc_init(void) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index ab98dc6..f206e4b 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch b/packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch new file mode 100644 index 00000000..7046e44d --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/mm_vmscan.c.patch @@ -0,0 +1,13 @@ +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3496,7 +3496,7 @@ void check_move_unevictable_pages(struct page **pages, int nr_pages) + + static void warn_scan_unevictable_pages(void) + { +- printk_once(KERN_WARNING ++ printk_once(KERN_DEBUG + "The scan_unevictable_pages sysctl/node-interface has been " + "disabled for lack of a legitimate use case. If you have " + "one, please send an email to linux-mm@kvack.org.\n"); +diff --git a/net/8021q/Kconfig b/net/8021q/Kconfig +index fa073a5..4232018 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch b/packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch new file mode 100644 index 00000000..e5af6d21 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/overlayfs_notify.patch @@ -0,0 +1,264 @@ +Fix issues with OverlayFS not interacting correctly with the notify system + +diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig +index b981fc0..137d3fa 100644 +--- a/fs/notify/inotify/Kconfig ++++ b/fs/notify/inotify/Kconfig +@@ -15,3 +15,13 @@ config INOTIFY_USER + For more information, see + + If unsure, say Y. ++ ++ ++config INOTIFY_STACKFS ++ bool "Inotify support for stackable filesystem" ++ select INOTIFY_USER ++ default y ++ ---help--- ++ Say Y here to enable inotify support for stackable filesystem. ++ ++ If unsure, say N. +diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c +index f255d37..e555ac5 100644 +--- a/fs/notify/inotify/inotify_user.c ++++ b/fs/notify/inotify/inotify_user.c +@@ -24,6 +24,7 @@ + + #include + #include /* struct inode */ ++#include + #include + #include + #include /* module_init */ +@@ -86,6 +87,93 @@ ctl_table inotify_table[] = { + }; + #endif /* CONFIG_SYSCTL */ + ++#ifdef CONFIG_INOTIFY_STACKFS ++ ++static DEFINE_RWLOCK(inotify_fs_lock); ++static LIST_HEAD(inotify_fs_list); ++ ++static inline struct file_system_type* peek_fs_type(struct path *path) ++{ ++ return path->mnt->mnt_sb->s_type; ++} ++ ++static struct inotify_stackfs* inotify_get_stackfs(struct path *path) ++{ ++ struct file_system_type *fs; ++ struct inotify_stackfs *fse, *ret = NULL; ++ ++ fs = peek_fs_type(path); ++ ++ read_lock(&inotify_fs_lock); ++ list_for_each_entry(fse, &inotify_fs_list, list) { ++ if (fse->fs_type == fs) { ++ ret = fse; ++ break; ++ } ++ } ++ read_unlock(&inotify_fs_lock); ++ ++ return ret; ++} ++ ++static inline void inotify_put_stackfs(struct inotify_stackfs *fs) ++{ ++} ++ ++int inotify_register_stackfs(struct inotify_stackfs *fs) ++{ ++ int ret = 0; ++ struct inotify_stackfs *fse; ++ ++ BUG_ON(IS_ERR_OR_NULL(fs->fs_type)); ++ BUG_ON(IS_ERR_OR_NULL(fs->func)); ++ ++ INIT_LIST_HEAD(&fs->list); ++ ++ write_lock(&inotify_fs_lock); ++ list_for_each_entry(fse, &inotify_fs_list, list) { ++ if (fse->fs_type == fs->fs_type) { ++ write_unlock(&inotify_fs_lock); ++ ret = -EBUSY; ++ goto out; ++ } ++ } ++ list_add_tail(&fs->list, &inotify_fs_list); ++ write_unlock(&inotify_fs_lock); ++ ++out: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(inotify_register_stackfs); ++ ++void inotify_unregister_stackfs(struct inotify_stackfs *fs) ++{ ++ struct inotify_stackfs *fse, *n; ++ ++ write_lock(&inotify_fs_lock); ++ list_for_each_entry_safe(fse, n, &inotify_fs_list, list) { ++ if (fse == fs) { ++ list_del(&fse->list); ++ break; ++ } ++ } ++ write_unlock(&inotify_fs_lock); ++} ++EXPORT_SYMBOL_GPL(inotify_unregister_stackfs); ++ ++#else ++ ++static inline struct inotify_stackfs* inotify_get_stackfs(struct path *path) ++{ ++ return NULL; ++} ++ ++static inline void inotify_put_stackfs(struct inotify_stackfs *fs) ++{ ++} ++ ++#endif /* CONFIG_INOTIFY_STACKFS */ ++ + static inline __u32 inotify_arg_to_mask(u32 arg) + { + __u32 mask; +@@ -348,7 +436,7 @@ static const struct file_operations inotify_fops = { + /* + * find_inode - resolve a user-given path to a specific inode + */ +-static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) ++static inline int __inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) + { + int error; + +@@ -362,6 +450,27 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns + return error; + } + ++static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) ++{ ++ int ret; ++ struct path tpath; ++ struct inotify_stackfs *fse; ++ ++ ret = __inotify_find_inode(dirname, &tpath, flags); ++ if (ret) ++ return ret; ++ fse = inotify_get_stackfs(&tpath); ++ if (fse == NULL) { ++ *path = tpath; ++ return 0; ++ } ++ ret = fse->func(path, &tpath); ++ inotify_put_stackfs(fse); ++ path_put(&tpath); ++ ++ return ret; ++} ++ + static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock, + int *last_wd, + struct inotify_inode_mark *i_mark) +diff --git a/overlayfs/super.c b/fs/overlayfs/super.c +index 508cf19..cb39ec9 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include "overlayfs.h" + + MODULE_AUTHOR("Miklos Szeredi "); +@@ -642,14 +643,40 @@ static struct file_system_type ovl_fs_type = { + .kill_sb = kill_anon_super, + }; + ++static int ovl_inotify_path(struct path *dst, struct path *src) ++{ ++ ovl_path_real(src->dentry, dst); ++ ++ path_get(dst); ++ ++ return 0; ++} ++ ++static struct inotify_stackfs ovl_inotify = { ++ .fs_type = &ovl_fs_type, ++ .func = ovl_inotify_path, ++}; ++ + static int __init ovl_init(void) + { +- return register_filesystem(&ovl_fs_type); ++ int ret; ++ ++ ret = register_filesystem(&ovl_fs_type); ++ if (ret) ++ return ret; ++ ret = inotify_register_stackfs(&ovl_inotify); ++ if (ret) { ++ pr_err("overlayfs: hook inotify error\n"); ++ unregister_filesystem(&ovl_fs_type); ++ } ++ ++ return ret; + } + + static void __exit ovl_exit(void) + { +- unregister_filesystem(&ovl_fs_type); ++ inotify_unregister_stackfs(&ovl_inotify); ++ unregister_filesystem(&ovl_fs_type); + } + + module_init(ovl_init); +diff --git a/include/linux/inotify.h b/include/linux/inotify.h +index d33041e..9d7e36f 100644 +--- a/include/linux/inotify.h ++++ b/include/linux/inotify.h +@@ -10,6 +10,8 @@ + /* For O_CLOEXEC and O_NONBLOCK */ + #include + #include ++#include ++#include + + /* + * struct inotify_event - structure read from the inotify device for each event +@@ -82,6 +84,32 @@ extern struct ctl_table inotify_table[]; /* for sysctl */ + IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \ + IN_ISDIR | IN_ONESHOT) + ++typedef int (*inotify_path_proc)(struct path *dst, struct path *src); ++ ++struct inotify_stackfs { ++ struct list_head list; /* entry in inotify_fs_list */ ++ struct file_system_type *fs_type; /* registed file_system_type */ ++ inotify_path_proc func; /* registed callback function */ ++}; ++ ++#ifdef CONFIG_INOTIFY_STACKFS ++ ++extern int inotify_register_stackfs(struct inotify_stackfs *fs); ++extern void inotify_unregister_stackfs(struct inotify_stackfs *fs); ++ ++#else ++ ++static inline int inotify_register_stackfs(struct inotify_stackfs *fs) ++{ ++ return 0; ++} ++ ++static inline void inotify_unregister_stackfs(struct inotify_stackfs *fs) ++{ ++} ++ ++#endif /* CONFIG_INOTIFY_STACKFS */ ++ + #endif + + #endif /* _LINUX_INOTIFY_H */ diff --git a/packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch b/packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch new file mode 100644 index 00000000..66ba4882 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/platform-accton-as4610-device-drivers.patch @@ -0,0 +1,3932 @@ +Device driver patches for accton as4610 54 (fan/psu/cpld/led/sfp) + +diff --git a/arch/arm/boot/dts/accton_as4610_54.dts b/arch/arm/boot/dts/accton_as4610_54.dts +index 9276c0a..8848f8c 100644 +--- a/arch/arm/boot/dts/accton_as4610_54.dts ++++ b/arch/arm/boot/dts/accton_as4610_54.dts +@@ -105,46 +105,46 @@ + }; + + i2c0: i2c@18038000 { +- compatible = "iproc-smb"; +- reg = <0x18038000 0x1000>; ++ compatible = "iproc-smb"; ++ reg = <0x18038000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = < 127 >; ++ clock-frequency = <400000>; ++ cpld@1,0 { + #address-cells = <1>; +- #size-cells = <0>; +- interrupts = < 127 >; +- clock-frequency = <400000>; +- cpld@1,0 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "accton,as4610-54-cpld"; +- label = "cpld"; +- reg = <0x30>; +- }; ++ #size-cells = <1>; ++ compatible = "accton,as4610_54_cpld"; ++ label = "cpld"; ++ reg = <0x30>; ++ }; + }; + + i2c1: i2c@1803b000 { +- compatible = "iproc-smb"; +- reg = <0x1803b000 0x1000>; ++ compatible = "iproc-smb"; ++ reg = <0x1803b000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = < 128 >; ++ clock-frequency = <100000>; ++ mux@70 { ++ compatible = "ti,pca9548"; ++ reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; +- interrupts = < 128 >; +- clock-frequency = <100000>; +- mux@70 { +- compatible = "ti,pca9548"; +- reg = <0x70>; ++ deselect-on-exit; ++ ++ // SFP+ 1 ++ i2c@0 { + #address-cells = <1>; + #size-cells = <0>; +- deselect-on-exit; +- +- // SFP+ 1 +- i2c@0 { +- #address-cells = <1>; +- #size-cells = <0>; +- reg = <0>; +- sfp_eeprom@50 { +- compatible = "at,24c04"; +- reg = <0x50>; +- label = "port49"; +- }; ++ reg = <0>; ++ sfp_eeprom@50 { ++ compatible = "at,as4610_sfp1"; ++ reg = <0x50>; ++ label = "port49"; + }; ++ }; + + // SFP+ 2 + i2c@1 { +@@ -152,7 +152,7 @@ + #size-cells = <0>; + reg = <1>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp2"; + reg = <0x50>; + label = "port50"; + }; +@@ -164,7 +164,7 @@ + #size-cells = <0>; + reg = <2>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp3"; + reg = <0x50>; + label = "port51"; + }; +@@ -176,7 +176,7 @@ + #size-cells = <0>; + reg = <3>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp4"; + reg = <0x50>; + label = "port52"; + }; +@@ -188,7 +188,7 @@ + #size-cells = <0>; + reg = <4>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp5"; + reg = <0x50>; + }; + }; +@@ -199,7 +199,7 @@ + #size-cells = <0>; + reg = <5>; + sfp_eeprom@50 { +- compatible = "at,24c04"; ++ compatible = "accton,as4610_sfp6"; + reg = <0x50>; + }; + }; +@@ -209,17 +209,21 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; +- psu_eeprom@50 { +- compatible = "at,24c02"; ++ psu1_eeprom@50 { ++ compatible = "accton,as4610_psu1"; + reg = <0x50>; +- label = "psu1_eeprom"; +- read-only; + }; +- psu_eeprom@51 { +- compatible = "at,24c02"; ++ psu1_pmbus@58 { ++ compatible = "3y-power,ym1921"; ++ reg = <0x58>; ++ }; ++ psu2_eeprom@51 { ++ compatible = "accton,as4610_psu2"; + reg = <0x51>; +- label = "psu2_eeprom"; +- read-only; ++ }; ++ psu2_pmbus@59 { ++ compatible = "3y-power,ym1921"; ++ reg = <0x59>; + }; + }; + +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 5c984a6..df89e25 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1412,6 +1412,43 @@ config SENSORS_MC13783_ADC + help + Support for the A/D converter on MC13783 PMIC. + ++config SENSORS_ACCTON_I2C_CPLD ++ tristate "Accton i2c cpld" ++ depends on I2C ++ help ++ If you say yes here you get support for Accton i2c cpld. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_i2c_cpld. ++ ++config SENSORS_ACCTON_AS4610_FAN ++ tristate "Accton as4610 fan" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 fan. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_fan. ++ ++config SENSORS_ACCTON_AS4610_PSU ++ tristate "Accton as4610 psu" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 psu. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_psu. ++ ++config SENSORS_YM2651Y ++ tristate "3Y Power (YM-2651Y, YM1921Y) Power Module" ++ depends on I2C ++ help ++ If you say yes here you get support for 3Y Power YM-2651Y and YM1921Y ++ Power Module. ++ ++ This driver can also be built as a module. If so, the module will ++ be called ym2651y. ++ + if ACPI + + comment "ACPI drivers" +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index ff3a18e..39c9888 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -21,6 +21,9 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o + + obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o + obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o ++obj-$(CONFIG_SENSORS_ACCTON_I2C_CPLD) += accton_i2c_cpld.o ++obj-$(CONFIG_SENSORS_ACCTON_AS4610_FAN) += accton_as4610_fan.o ++obj-$(CONFIG_SENSORS_ACCTON_AS4610_PSU) += accton_as4610_psu.o + obj-$(CONFIG_SENSORS_AD7314) += ad7314.o + obj-$(CONFIG_SENSORS_AD7414) += ad7414.o + obj-$(CONFIG_SENSORS_AD7418) += ad7418.o +@@ -130,6 +133,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o + obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o + obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o + obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o ++obj-$(CONFIG_SENSORS_YM2651Y) += ym2651y.o + + obj-$(CONFIG_PMBUS) += pmbus/ + +diff --git a/drivers/hwmon/accton_as4610_fan.c b/drivers/hwmon/accton_as4610_fan.c +new file mode 100644 +index 0000000..3934bcd +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_fan.c +@@ -0,0 +1,344 @@ ++/* ++ * A hwmon driver for the Accton as4610 fan ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRVNAME "as4610_fan" ++ ++static struct as4610_fan_data *as4610_fan_update_device(struct device *dev); ++static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count); ++ ++/* fan related data, the index should match sysfs_fan_attributes ++ */ ++static const u8 fan_reg[] = { ++ 0x2B, /* fan PWM(for all fan) */ ++ 0x2D, /* fan 1 speed(rpm) */ ++ 0x2C, /* fan 2 speed(rpm) */ ++ 0x11, /* fan1-2 operating status */ ++}; ++ ++static struct as4610_fan_data *fan_data = NULL; ++ ++/* Each client has this additional data */ ++struct as4610_fan_data { ++ struct platform_device *pdev; ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* != 0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ ++}; ++ ++enum fan_id { ++ FAN1_ID, ++ FAN2_ID ++}; ++ ++enum sysfs_fan_attributes { ++ FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ ++ FAN1_SPEED_RPM, ++ FAN2_SPEED_RPM, ++ FAN_FAULT, ++ FAN1_FAULT, ++ FAN2_FAULT ++}; ++ ++/* Define attributes ++ */ ++#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) ++#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr ++ ++#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) ++#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr ++ ++#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_SPEED_RPM) ++#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_speed_rpm.dev_attr.attr ++ ++/* fan fault attributes in this platform */ ++DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); ++DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); ++/* fan speed(rpm) attributes in this platform */ ++DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); ++DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); ++/* 1 fan duty cycle attribute in this platform */ ++DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); ++ ++static struct attribute *as4610_fan_attributes[] = { ++ /* fan related attributes */ ++ DECLARE_FAN_FAULT_ATTR(1), ++ DECLARE_FAN_FAULT_ATTR(2), ++ DECLARE_FAN_SPEED_RPM_ATTR(1), ++ DECLARE_FAN_SPEED_RPM_ATTR(2), ++ DECLARE_FAN_DUTY_CYCLE_ATTR(), ++ NULL ++}; ++ ++#define FAN_DUTY_CYCLE_REG_MASK 0xF ++#define FAN_MAX_DUTY_CYCLE 100 ++#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 ++ ++static int as4610_fan_read_value(u8 reg) ++{ ++ return accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, reg); ++} ++ ++static int as4610_fan_write_value(u8 reg, u8 value) ++{ ++ return accton_i2c_cpld_write(AS4610_CPLD_SLAVE_ADDR, reg, value); ++} ++ ++/* fan utility functions ++ */ ++static u32 reg_val_to_duty_cycle(u8 reg_val) ++{ ++ reg_val &= FAN_DUTY_CYCLE_REG_MASK; ++ return (u32)((reg_val * 125 + 5)/10); ++} ++ ++static u8 duty_cycle_to_reg_val(u8 duty_cycle) ++{ ++ return ((u32)duty_cycle * 10 / 125); ++} ++ ++static u32 reg_val_to_speed_rpm(u8 reg_val) ++{ ++ /* Count Frequency is 1.515KHz= 0.66ms ++ * Count Period = 400 cycle = 400*0.66ms = 264ms ++ * R.P.M value = read value x3.79*60/2 ++ * 3.79 = 1000ms/264ms ++ * 60 = 1min =60s ++ * 2 = 1 rotation of fan has two pulses. ++ */ ++ return (u32)reg_val * 379 * 60 / 2 / 100; ++} ++ ++static u8 is_fan_fault(struct as4610_fan_data *data, enum fan_id id) ++{ ++ u8 mask = (id == FAN1_ID) ? 0x20 : 0x10; ++ ++ return !(data->reg_val[FAN_FAULT] & mask); ++} ++ ++static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ int error, value; ++ ++ error = kstrtoint(buf, 10, &value); ++ if (error) ++ return error; ++ ++ if (value < 0 || value > FAN_MAX_DUTY_CYCLE) ++ return -EINVAL; ++ ++ as4610_fan_write_value(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); ++ return count; ++} ++ ++static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct as4610_fan_data *data = as4610_fan_update_device(dev); ++ ssize_t ret = 0; ++ ++ if (data->valid) { ++ switch (attr->index) { ++ case FAN_DUTY_CYCLE_PERCENTAGE: ++ { ++ u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[attr->index]); ++ ret = sprintf(buf, "%u\n", duty_cycle); ++ break; ++ } ++ case FAN1_SPEED_RPM: ++ case FAN2_SPEED_RPM: ++ ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); ++ break; ++ case FAN1_FAULT: ++ case FAN2_FAULT: ++ ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static const struct attribute_group as4610_fan_group = { ++ .attrs = as4610_fan_attributes, ++}; ++ ++static struct as4610_fan_data *as4610_fan_update_device(struct device *dev) ++{ ++ mutex_lock(&fan_data->update_lock); ++ ++ if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || ++ !fan_data->valid) { ++ int i; ++ ++ dev_dbg(fan_data->hwmon_dev, "Starting as4610_fan update\n"); ++ fan_data->valid = 0; ++ ++ /* Update fan data ++ */ ++ for (i = 0; i < ARRAY_SIZE(fan_data->reg_val); i++) { ++ int status = as4610_fan_read_value(fan_reg[i]); ++ ++ if (status < 0) { ++ fan_data->valid = 0; ++ mutex_unlock(&fan_data->update_lock); ++ dev_dbg(fan_data->hwmon_dev, "reg %d, err %d\n", fan_reg[i], status); ++ return fan_data; ++ } ++ else { ++ fan_data->reg_val[i] = status; ++ } ++ } ++ ++ fan_data->last_updated = jiffies; ++ fan_data->valid = 1; ++ } ++ ++ mutex_unlock(&fan_data->update_lock); ++ ++ return fan_data; ++} ++ ++static int as4610_fan_probe(struct platform_device *pdev) ++{ ++ int status = -1; ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&pdev->dev.kobj, &as4610_fan_group); ++ if (status) { ++ goto exit; ++ ++ } ++ ++ fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); ++ if (IS_ERR(fan_data->hwmon_dev)) { ++ status = PTR_ERR(fan_data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&pdev->dev, "accton_as4610_fan\n"); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++exit: ++ return status; ++} ++ ++static int as4610_fan_remove(struct platform_device *pdev) ++{ ++ hwmon_device_unregister(fan_data->hwmon_dev); ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id as4610_fan_id[] = { ++ { "as4610_fan", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_fan_id); ++ ++static struct platform_driver as4610_fan_driver = { ++ .probe = as4610_fan_probe, ++ .remove = as4610_fan_remove, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init as4610_fan_init(void) ++{ ++ int ret; ++ ++ if (as4610_number_of_system_fan() == 0) { ++ return -ENODEV; ++ } ++ ++ ret = platform_driver_register(&as4610_fan_driver); ++ if (ret < 0) { ++ goto exit; ++ } ++ ++ fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL); ++ if (!fan_data) { ++ ret = -ENOMEM; ++ platform_driver_unregister(&as4610_fan_driver); ++ goto exit; ++ } ++ ++ mutex_init(&fan_data->update_lock); ++ fan_data->valid = 0; ++ ++ fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); ++ if (IS_ERR(fan_data->pdev)) { ++ ret = PTR_ERR(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); ++ goto exit; ++ } ++ ++exit: ++ return ret; ++} ++ ++static void __exit as4610_fan_exit(void) ++{ ++ if (!fan_data) { ++ return; ++ } ++ ++ platform_device_unregister(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); ++} ++ ++late_initcall(as4610_fan_init); ++module_exit(as4610_fan_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_fan driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/hwmon/accton_as4610_psu.c b/drivers/hwmon/accton_as4610_psu.c +new file mode 100644 +index 0000000..1f0d79d +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_psu.c +@@ -0,0 +1,286 @@ ++/* ++ * An hwmon driver for accton as4610 Power Module ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); ++static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data,int data_len); ++extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; ++ ++/* Each client has this additional data ++ */ ++struct as4610_psu_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 index; /* PSU index */ ++ u8 status; /* Status(present/power_good) register read from CPLD */ ++ char model_name[9]; /* Model name, read from eeprom */ ++}; ++ ++static struct as4610_psu_data *as4610_psu_update_device(struct device *dev); ++ ++enum as4610_psu_sysfs_attributes { ++ PSU_PRESENT, ++ PSU_MODEL_NAME, ++ PSU_POWER_GOOD ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); ++static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); ++static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); ++ ++static struct attribute *as4610_psu_attributes[] = { ++ &sensor_dev_attr_psu_present.dev_attr.attr, ++ &sensor_dev_attr_psu_model_name.dev_attr.attr, ++ &sensor_dev_attr_psu_power_good.dev_attr.attr, ++ NULL ++}; ++ ++static ssize_t show_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ u8 status = 0; ++ ++ if (attr->index == PSU_PRESENT) { ++ status = (data->status >> (data->index*2) & 0x1); ++ } ++ else { /* PSU_POWER_GOOD */ ++ status = (data->status >> (data->index*2 + 1) & 0x1); ++ } ++ ++ return sprintf(buf, "%d\n", status); ++} ++ ++static ssize_t show_model_name(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ ++ return sprintf(buf, "%s\n", data->model_name); ++} ++ ++static const struct attribute_group as4610_psu_group = { ++ .attrs = as4610_psu_attributes, ++}; ++ ++static int as4610_psu_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct as4610_psu_data *data; ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ data = kzalloc(sizeof(struct as4610_psu_data), GFP_KERNEL); ++ if (!data) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_set_clientdata(client, data); ++ data->valid = 0; ++ data->index = dev_id->driver_data; ++ mutex_init(&data->update_lock); ++ ++ dev_info(&client->dev, "chip found\n"); ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &as4610_psu_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++exit_free: ++ kfree(data); ++exit: ++ ++ return status; ++} ++ ++static int as4610_psu_remove(struct i2c_client *client) ++{ ++ struct as4610_psu_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++ kfree(data); ++ ++ return 0; ++} ++ ++enum psu_index ++{ ++ as4610_psu1, ++ as4610_psu2 ++}; ++ ++static const struct i2c_device_id as4610_psu_id[] = { ++ { "as4610_psu1", as4610_psu1 }, ++ { "as4610_psu2", as4610_psu2 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_psu_id); ++ ++static struct i2c_driver as4610_psu_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "as4610_psu", ++ }, ++ .probe = as4610_psu_probe, ++ .remove = as4610_psu_remove, ++ .id_table = as4610_psu_id, ++ .address_list = normal_i2c, ++}; ++ ++static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data, ++ int count) ++{ ++ int status = 0; ++ ++ while (count) { ++ status = i2c_smbus_read_byte_data(client, command); ++ if (unlikely(status < 0)) { ++ break; ++ } ++ ++ *data = (u8)status; ++ data += 1; ++ command += 1; ++ count -= 1; ++ } ++ ++ return status; ++} ++ ++static struct as4610_psu_data *as4610_psu_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct as4610_psu_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ int status; ++ int present = 0; ++ ++ data->valid = 0; ++ data->status = 0; ++ dev_dbg(&client->dev, "Starting as4610 update\n"); ++ ++ /* Read psu status */ ++ status = accton_i2c_cpld_read(0x30, 0x11); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status); ++ goto exit; ++ } ++ else { ++ data->status = status; ++ } ++ ++ /* Read model name */ ++ memset(data->model_name, 0, sizeof(data->model_name)); ++ present = (data->status >> (data->index*2) & 0x1); ++ ++ if (present) { ++ int len = ARRAY_SIZE(data->model_name)-1; ++ ++ status = as4610_psu_read_data(client, 0x20, data->model_name, ++ ARRAY_SIZE(data->model_name)-1); ++ ++ if (status < 0) { ++ data->model_name[0] = '\0'; ++ dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); ++ goto exit; ++ } ++ else { ++ data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; ++ } ++ } ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init as4610_psu_init(void) ++{ ++ return i2c_add_driver(&as4610_psu_driver); ++} ++ ++static void __exit as4610_psu_exit(void) ++{ ++ i2c_del_driver(&as4610_psu_driver); ++} ++ ++module_init(as4610_psu_init); ++module_exit(as4610_psu_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_psu driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/hwmon/accton_i2c_cpld.c b/drivers/hwmon/accton_i2c_cpld.c +new file mode 100644 +index 0000000..0b9762e +--- /dev/null ++++ b/drivers/hwmon/accton_i2c_cpld.c +@@ -0,0 +1,285 @@ ++/* ++ * A hwmon driver for the accton_i2c_cpld ++ * ++ * Copyright (C) 2013 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static LIST_HEAD(cpld_client_list); ++static struct mutex list_lock; ++ ++enum cpld_device_id { ++ as4610_30_cpld, ++ as4610_54_cpld ++}; ++ ++struct cpld_data { ++ enum cpld_device_id id; ++}; ++ ++struct cpld_client_node { ++ struct i2c_client *client; ++ struct list_head list; ++}; ++ ++/* Addresses scanned for accton_i2c_cpld ++ */ ++static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; ++ ++static u8 cpld_product_id_offset(enum cpld_device_id id) ++{ ++ switch (id) { ++ case as4610_30_cpld: ++ case as4610_54_cpld: ++ return 0x1; ++ } ++ ++ return 0; ++} ++ ++static int cpld_has_product_id(const struct i2c_device_id *dev_id) ++{ ++ return (dev_id->driver_data == as4610_30_cpld) || ++ (dev_id->driver_data == as4610_54_cpld); ++} ++ ++static ssize_t show_cpld_product_id(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ int val = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cpld_data *data = i2c_get_clientdata(client); ++ ++ val = i2c_smbus_read_byte_data(client, cpld_product_id_offset(data->id)); ++ if (val < 0) { ++ dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", client->addr, cpld_product_id_offset(data->id), val); ++ } ++ ++ return sprintf(buf, "%d\n", (val & 0xF)); ++} ++ ++static u8 cpld_version_offset(enum cpld_device_id id) ++{ ++ switch (id) { ++ case as4610_30_cpld: ++ case as4610_54_cpld: ++ return 0xB; ++ } ++ ++ return 0; ++} ++ ++static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ int val = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct cpld_data *data = i2c_get_clientdata(client); ++ ++ val = i2c_smbus_read_byte_data(client, cpld_version_offset(data->id)); ++ if (val < 0) { ++ dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); ++ } ++ ++ return sprintf(buf, "%d\n", val); ++} ++ ++static void accton_i2c_cpld_add_client(struct i2c_client *client, enum cpld_device_id id) ++{ ++ struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); ++ struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); ++ ++ if (!node) { ++ dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); ++ return; ++ } ++ ++ if (!data) { ++ dev_dbg(&client->dev, "Can't allocate cpld_client_data (0x%x)\n", client->addr); ++ return; ++ } ++ ++ data->id = id; ++ i2c_set_clientdata(client, data); ++ node->client = client; ++ ++ mutex_lock(&list_lock); ++ list_add(&node->list, &cpld_client_list); ++ mutex_unlock(&list_lock); ++} ++ ++static void accton_i2c_cpld_remove_client(struct i2c_client *client) ++{ ++ struct list_head *list_node = NULL; ++ struct cpld_client_node *cpld_node = NULL; ++ int found = 0; ++ ++ mutex_lock(&list_lock); ++ ++ list_for_each(list_node, &cpld_client_list) ++ { ++ cpld_node = list_entry(list_node, struct cpld_client_node, list); ++ ++ if (cpld_node->client == client) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (found) { ++ list_del(list_node); ++ kfree(cpld_node); ++ } ++ ++ mutex_unlock(&list_lock); ++} ++ ++static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); ++static struct device_attribute pid = __ATTR(product_id, 0600, show_cpld_product_id, NULL); ++ ++static int accton_i2c_cpld_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); ++ status = -EIO; ++ goto exit; ++ } ++ ++ status = sysfs_create_file(&client->dev.kobj, &ver.attr); ++ if (status) { ++ goto exit; ++ } ++ ++ if (cpld_has_product_id(dev_id)) { ++ status = sysfs_create_file(&client->dev.kobj, &pid.attr); ++ if (status) { ++ goto exit; ++ } ++ } ++ ++ dev_info(&client->dev, "chip found\n"); ++ accton_i2c_cpld_add_client(client, (enum cpld_device_id)dev_id->driver_data); ++ ++ return 0; ++ ++exit: ++ return status; ++} ++ ++static int accton_i2c_cpld_remove(struct i2c_client *client) ++{ ++ sysfs_remove_file(&client->dev.kobj, &ver.attr); ++ accton_i2c_cpld_remove_client(client); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id accton_i2c_cpld_id[] = { ++ { "as4610_30_cpld", as4610_30_cpld }, ++ { "as4610_54_cpld", as4610_54_cpld }, ++ { /* LIST END */} ++}; ++MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); ++ ++static struct i2c_driver accton_i2c_cpld_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "accton_i2c_cpld", ++ }, ++ .probe = accton_i2c_cpld_probe, ++ .remove = accton_i2c_cpld_remove, ++ .id_table = accton_i2c_cpld_id, ++ .address_list = normal_i2c, ++}; ++ ++int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) ++{ ++ struct list_head *list_node = NULL; ++ struct cpld_client_node *cpld_node = NULL; ++ int ret = -EPERM; ++ ++ mutex_lock(&list_lock); ++ ++ list_for_each(list_node, &cpld_client_list) ++ { ++ cpld_node = list_entry(list_node, struct cpld_client_node, list); ++ ++ if (cpld_node->client->addr == cpld_addr) { ++ ret = i2c_smbus_read_byte_data(cpld_node->client, reg); ++ break; ++ } ++ } ++ ++ mutex_unlock(&list_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(accton_i2c_cpld_read); ++ ++int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) ++{ ++ struct list_head *list_node = NULL; ++ struct cpld_client_node *cpld_node = NULL; ++ int ret = -EIO; ++ ++ mutex_lock(&list_lock); ++ ++ list_for_each(list_node, &cpld_client_list) ++ { ++ cpld_node = list_entry(list_node, struct cpld_client_node, list); ++ ++ if (cpld_node->client->addr == cpld_addr) { ++ ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); ++ break; ++ } ++ } ++ ++ mutex_unlock(&list_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(accton_i2c_cpld_write); ++ ++static int __init accton_i2c_cpld_init(void) ++{ ++ mutex_init(&list_lock); ++ return i2c_add_driver(&accton_i2c_cpld_driver); ++} ++ ++static void __exit accton_i2c_cpld_exit(void) ++{ ++ i2c_del_driver(&accton_i2c_cpld_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("accton_i2c_cpld driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(accton_i2c_cpld_init); ++module_exit(accton_i2c_cpld_exit); ++ +diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c +index 8dfc678..b9eafcf 100644 +--- a/drivers/hwmon/lm77.c ++++ b/drivers/hwmon/lm77.c +@@ -36,7 +36,7 @@ + #include + + /* Addresses to scan */ +-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, ++static const unsigned short normal_i2c[] = { /*0x48,*/ 0x49, 0x4a, 0x4b, + I2C_CLIENT_END }; + + /* The LM77 registers */ +diff --git a/drivers/hwmon/ym2651y.c b/drivers/hwmon/ym2651y.c +new file mode 100644 +index 0000000..e761a74 +--- /dev/null ++++ b/drivers/hwmon/ym2651y.c +@@ -0,0 +1,651 @@ ++/* ++ * An hwmon driver for the 3Y Power YM-2651Y Power Module ++ * ++ * Copyright (C) Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define USE_I2C_BLOCK_READ 0 ++#if USE_I2C_BLOCK_READ ++ #define I2C_FUNCTION (I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA | \ ++ I2C_FUNC_SMBUS_I2C_BLOCK) ++#else ++ #define I2C_FUNCTION (I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA) ++#endif ++ ++#define MAX_FAN_DUTY_CYCLE 100 ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; ++ ++/* Each client has this additional data ++ */ ++struct ym2651y_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 capability; /* Register value */ ++ u16 status_word; /* Register value */ ++ u8 fan_fault; /* Register value */ ++ u8 over_temp; /* Register value */ ++ u16 v_out; /* Register value */ ++ u16 i_out; /* Register value */ ++ u16 p_out; /* Register value */ ++ u16 temp; /* Register value */ ++ u16 fan_speed; /* Register value */ ++ u16 fan_duty_cycle[2]; /* Register value */ ++ u8 pmbus_revision; /* Register value */ ++ u16 mfr_vin_min; /* Register value */ ++ u16 mfr_vin_max; /* Register value */ ++ u16 mfr_iin_max; /* Register value */ ++ u16 mfr_iout_max; /* Register value */ ++ u16 mfr_pin_max; /* Register value */ ++ u16 mfr_pout_max; /* Register value */ ++ u16 mfr_vout_min; /* Register value */ ++ u16 mfr_vout_max; /* Register value */ ++#if USE_I2C_BLOCK_READ ++ u8 fan_dir[4]; /* Register value */ ++ u8 mfr_id[10]; /* Register value */ ++ u8 mfr_model[10]; /* Register value */ ++ u8 mfr_revsion[3]; /* Register value */ ++#endif ++ ++}; ++ ++static ssize_t show_byte(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_word(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_linear(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_ascii(struct device *dev, struct device_attribute *da, ++ char *buf); ++static struct ym2651y_data *ym2651y_update_device(struct device *dev); ++static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count); ++static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); ++ ++enum ym2651y_sysfs_attributes { ++ PSU_POWER_ON = 0, ++ PSU_TEMP_FAULT, ++ PSU_POWER_GOOD, ++ PSU_FAN1_FAULT, ++ PSU_FAN_DIRECTION, ++ PSU_OVER_TEMP, ++ PSU_V_OUT, ++ PSU_I_OUT, ++ PSU_P_OUT, ++ PSU_TEMP1_INPUT, ++ PSU_FAN1_SPEED, ++ PSU_FAN1_DUTY_CYCLE, ++ PSU_PMBUS_REVISION, ++ PSU_MFR_ID, ++ PSU_MFR_MODEL, ++ PSU_MFR_REVISION, ++ PSU_MFR_VIN_MIN, ++ PSU_MFR_VIN_MAX, ++ PSU_MFR_VOUT_MIN, ++ PSU_MFR_VOUT_MAX, ++ PSU_MFR_IIN_MAX, ++ PSU_MFR_IOUT_MAX, ++ PSU_MFR_PIN_MAX, ++ PSU_MFR_POUT_MAX ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); ++static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); ++static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); ++static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); ++static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); ++static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); ++static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); ++static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); ++static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); ++static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); ++static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); ++static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); ++static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); ++static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); ++static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); ++#if USE_I2C_BLOCK_READ ++static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); ++static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); ++static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); ++static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); ++#endif ++ ++ ++static struct attribute *ym2651y_attributes[] = { ++ &sensor_dev_attr_psu_power_on.dev_attr.attr, ++ &sensor_dev_attr_psu_temp_fault.dev_attr.attr, ++ &sensor_dev_attr_psu_power_good.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, ++ &sensor_dev_attr_psu_over_temp.dev_attr.attr, ++ &sensor_dev_attr_psu_v_out.dev_attr.attr, ++ &sensor_dev_attr_psu_i_out.dev_attr.attr, ++ &sensor_dev_attr_psu_p_out.dev_attr.attr, ++ &sensor_dev_attr_psu_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, ++ &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, ++#if USE_I2C_BLOCK_READ ++ &sensor_dev_attr_psu_fan_dir.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_id.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_model.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, ++#endif ++ NULL ++}; ++ ++static ssize_t show_byte(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : ++ sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_word(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ u16 status = 0; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ ++ status = (data->status_word & 0x40) ? 0 : 1; ++ break; ++ case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ ++ status = (data->status_word & 0x4) >> 2; ++ break; ++ case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ ++ status = (data->status_word & 0x800) ? 0 : 1; ++ break; ++ } ++ ++ return sprintf(buf, "%d\n", status); ++} ++ ++static int two_complement_to_int(u16 data, u8 valid_bit, int mask) ++{ ++ u16 valid_data = data & mask; ++ bool is_negative = valid_data >> (valid_bit - 1); ++ ++ return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; ++} ++ ++static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; ++ long speed; ++ int error; ++ ++ error = kstrtol(buf, 10, &speed); ++ if (error) ++ return error; ++ ++ if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ data->fan_duty_cycle[nr] = speed; ++ ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t show_linear(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ u16 value = 0; ++ int exponent, mantissa; ++ int multiplier = 1000; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_V_OUT: ++ value = data->v_out; ++ break; ++ case PSU_I_OUT: ++ value = data->i_out; ++ break; ++ case PSU_P_OUT: ++ value = data->p_out; ++ break; ++ case PSU_TEMP1_INPUT: ++ value = data->temp; ++ break; ++ case PSU_FAN1_SPEED: ++ value = data->fan_speed; ++ multiplier = 1; ++ break; ++ case PSU_FAN1_DUTY_CYCLE: ++ value = data->fan_duty_cycle[0]; ++ multiplier = 1; ++ break; ++ case PSU_MFR_VIN_MIN: ++ value = data->mfr_vin_min; ++ break; ++ case PSU_MFR_VIN_MAX: ++ value = data->mfr_vin_max; ++ break; ++ case PSU_MFR_VOUT_MIN: ++ value = data->mfr_vout_min; ++ break; ++ case PSU_MFR_VOUT_MAX: ++ value = data->mfr_vout_max; ++ break; ++ case PSU_MFR_PIN_MAX: ++ value = data->mfr_pin_max; ++ break; ++ case PSU_MFR_POUT_MAX: ++ value = data->mfr_pout_max; ++ break; ++ case PSU_MFR_IOUT_MAX: ++ value = data->mfr_iout_max; ++ break; ++ case PSU_MFR_IIN_MAX: ++ value = data->mfr_iin_max; ++ break; ++ } ++ ++ exponent = two_complement_to_int(value >> 11, 5, 0x1f); ++ mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); ++ ++ return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : ++ sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); ++} ++ ++static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return sprintf(buf, "%d\n", data->fan_fault >> shift); ++} ++ ++static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return sprintf(buf, "%d\n", data->over_temp >> 7); ++} ++ ++#if USE_I2C_BLOCK_READ ++static ssize_t show_ascii(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ u8 *ptr = NULL; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_FAN_DIRECTION: /* psu_fan_dir */ ++ ptr = data->fan_dir; ++ break; ++ case PSU_MFR_ID: /* psu_mfr_id */ ++ ptr = data->mfr_id; ++ break; ++ case PSU_MFR_MODEL: /* psu_mfr_model */ ++ ptr = data->mfr_model; ++ break; ++ case PSU_MFR_REVISION: /* psu_mfr_revision */ ++ ptr = data->mfr_revsion; ++ break; ++ default: ++ return 0; ++ } ++ ++ return sprintf(buf, "%s\n", ptr); ++} ++#endif ++ ++static const struct attribute_group ym2651y_group = { ++ .attrs = ym2651y_attributes, ++}; ++ ++static int ym2651y_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct ym2651y_data *data; ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNCTION)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); ++ if (!data) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ dev_info(&client->dev, "chip found\n"); ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &ym2651y_group); ++exit_free: ++ kfree(data); ++exit: ++ ++ return status; ++} ++ ++static int ym2651y_remove(struct i2c_client *client) ++{ ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &ym2651y_group); ++ kfree(data); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ym2651y_id[] = { ++ { "ym2651", 0 }, ++ { "ym1921", 1 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ym2651y_id); ++ ++static struct i2c_driver ym2651y_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "ym2651", ++ }, ++ .probe = ym2651y_probe, ++ .remove = ym2651y_remove, ++ .id_table = ym2651y_id, ++ .address_list = normal_i2c, ++}; ++ ++static int ym2651y_read_byte(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++static int ym2651y_read_word(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_word_data(client, reg); ++} ++ ++static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) ++{ ++ return i2c_smbus_write_word_data(client, reg, value); ++} ++ ++#if USE_I2C_BLOCK_READ ++static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, ++ int data_len) ++{ ++ int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); ++ ++ if (unlikely(result < 0)) ++ goto abort; ++ if (unlikely(result != data_len)) { ++ result = -EIO; ++ goto abort; ++ } ++ ++ result = 0; ++ ++abort: ++ return result; ++} ++#endif ++ ++struct reg_data_byte { ++ u8 reg; ++ u8 *value; ++}; ++ ++struct reg_data_word { ++ u8 reg; ++ u16 *value; ++}; ++ ++static struct ym2651y_data *ym2651y_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ int i, status; ++ u8 command; ++ u8 fan_dir[5] = {0}; ++ struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, ++ {0x7d, &data->over_temp}, ++ {0x81, &data->fan_fault}, ++ {0x98, &data->pmbus_revision}}; ++ struct reg_data_word regs_word[] = { {0x79, &data->status_word}, ++ {0x8b, &data->v_out}, ++ {0x8c, &data->i_out}, ++ {0x96, &data->p_out}, ++ {0x8d, &data->temp}, ++ {0x3b, &(data->fan_duty_cycle[0])}, ++ {0x3c, &(data->fan_duty_cycle[1])}, ++ {0x90, &data->fan_speed}, ++ {0xa0, &data->mfr_vin_min}, ++ {0xa1, &data->mfr_vin_max}, ++ {0xa2, &data->mfr_iin_max}, ++ {0xa3, &data->mfr_pin_max}, ++ {0xa4, &data->mfr_vout_min}, ++ {0xa5, &data->mfr_vout_max}, ++ {0xa6, &data->mfr_iout_max}, ++ {0xa7, &data->mfr_pout_max}}; ++ ++ dev_dbg(&client->dev, "Starting ym2651 update\n"); ++ data->valid = 0; ++ ++ /* Read byte data */ ++ for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { ++ status = ym2651y_read_byte(client, regs_byte[i].reg); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", regs_byte[i].reg, status); ++ goto exit; ++ } ++ else { ++ *(regs_byte[i].value) = status; ++ } ++ } ++ ++ /* Read word data */ ++ for (i = 0; i < ARRAY_SIZE(regs_word); i++) { ++ status = ym2651y_read_word(client, regs_word[i].reg); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", regs_word[i].reg, status); ++ goto exit; ++ } ++ else { ++ *(regs_word[i].value) = status; ++ } ++ } ++ ++#if USE_I2C_BLOCK_READ ++ /* Read fan_direction */ ++ command = 0xC3; ++ status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); ++ data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; ++ ++ /* Read mfr_id */ ++ command = 0x99; ++ status = ym2651y_read_block(client, command, data->mfr_id, ++ ARRAY_SIZE(data->mfr_id)-1); ++ data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ /* Read mfr_model */ ++ command = 0x9a; ++ status = ym2651y_read_block(client, command, data->mfr_model, ++ ARRAY_SIZE(data->mfr_model)-1); ++ data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ /* Read mfr_revsion */ ++ command = 0x9b; ++ status = ym2651y_read_block(client, command, data->mfr_revsion, ++ ARRAY_SIZE(data->mfr_revsion)-1); ++ data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++#endif ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init ym2651y_init(void) ++{ ++ return i2c_add_driver(&ym2651y_driver); ++} ++ ++static void __exit ym2651y_exit(void) ++{ ++ i2c_del_driver(&ym2651y_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(ym2651y_init); ++module_exit(ym2651y_exit); ++ +diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig +index ff203a4..97d4d54 100644 +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -387,6 +387,13 @@ config LEDS_RENESAS_TPU + pin function. The latter to support brightness control. + Brightness control is supported but hardware blinking is not. + ++config LEDS_ACCTON_AS4610 ++ tristate "LED support for the Accton as4610" ++ depends on LEDS_CLASS && SENSORS_ACCTON_I2C_CPLD ++ help ++ This option enables support for the LEDs on the Accton as4610. ++ Say Y to enable LEDs on the Accton as4610. ++ + config LEDS_TRIGGERS + bool "LED Trigger support" + depends on LEDS_CLASS +diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile +index e4f6bf5..db2dab8 100644 +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o + obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o + obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o + obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o ++obj-$(CONFIG_LEDS_ACCTON_AS4610) += leds-accton_as4610.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o +diff --git a/drivers/leds/leds-accton_as4610.c b/drivers/leds/leds-accton_as4610.c +new file mode 100644 +index 0000000..0c4b535 +--- /dev/null ++++ b/drivers/leds/leds-accton_as4610.c +@@ -0,0 +1,678 @@ ++/* ++ * A LED driver for the accton_as4610_led ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++/*#define DEBUG*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern int accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg); ++extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++ ++extern void led_classdev_unregister(struct led_classdev *led_cdev); ++extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); ++ ++#define DRVNAME "as4610_led" ++ ++struct as4610_led_data { ++ struct platform_device *pdev; ++ struct mutex update_lock; ++ char valid; /* != 0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ int led_map; ++ u8 reg_val[5]; /* Register value, 0 = (0x1A) Blinking function ++ 1 = (0x30) 7-seg 2 ++ 2 = (0x31) 7-seg 1 ++ 3 = (0x32) SYS/PRI/PSU1-2 LED ++ 4 = (0x33) STK1-2/Fan/PoE/Alarm LED */ ++}; ++ ++static struct as4610_led_data *ledctl = NULL; ++ ++/* LED related data ++ */ ++#define LED_7SEG_REG_MASK 0x0F ++#define LED_7SEG_POINT_REG_MASK 0x10 ++ ++#define LED_NORMAL_MASK 0x03 ++#define LED_NORMAL_GREEN_VALUE 0x02 ++#define LED_NORMAL_AMBER_VALUE 0x01 ++#define LED_NORMAL_OFF_VALUE 0x00 ++ ++#define LED_TYPE_SYS_REG_MASK 0xC0 ++#define LED_MODE_SYS_BLINK_MASK 0x80 ++ ++#define LED_TYPE_PRI_REG_MASK 0x30 ++#define LED_MODE_PRI_BLINK_MASK 0x40 ++ ++#define LED_TYPE_PSU1_REG_MASK 0x0C ++#define LED_MODE_PSU1_BLINK_MASK 0x20 ++ ++#define LED_TYPE_PSU2_REG_MASK 0x03 ++#define LED_MODE_PSU2_BLINK_MASK 0x10 ++ ++#define LED_TYPE_STK1_REG_MASK 0xC0 ++#define LED_MODE_STK1_BLINK_MASK 0x08 ++ ++#define LED_TYPE_STK2_REG_MASK 0x30 ++#define LED_MODE_STK2_BLINK_MASK 0x04 ++ ++#define LED_TYPE_FAN_REG_MASK 0x0C ++#define LED_MODE_FAN_BLINK_MASK 0x02 ++ ++#define LED_TYPE_POE_ALARM_REG_MASK 0x03 ++#define LED_MODE_POE_ALARM_BLINK_MASK 0x01 ++ ++static const u8 led_reg[] = { ++ 0x1A, /* Blinking function */ ++ 0x30, /* 7-seg 1 */ ++ 0x31, /* 7-seg 2 */ ++ 0x32, /* SYS/PRI/PSU1-2 LED */ ++ 0x33, /* STK1-2/Fan/PoE/Alarm LED */ ++}; ++ ++enum led_type { ++ LED_TYPE_SYS, ++ LED_TYPE_PRI, ++ LED_TYPE_PSU1, ++ LED_TYPE_PSU2, ++ LED_TYPE_STK1, ++ LED_TYPE_STK2, ++ LED_TYPE_7SEG_TENS, ++ LED_TYPE_7SEG_TENS_POINT, ++ LED_TYPE_7SEG_DIGITS, ++ LED_TYPE_7SEG_DIGITS_POINT, ++ LED_TYPE_FAN, ++ LED_TYPE_POE, ++ LED_TYPE_ALARM, ++ NUM_OF_LED ++}; ++ ++#define AS4610_COMMON_LED_MAP (BIT(LED_TYPE_SYS) | BIT(LED_TYPE_PRI) | BIT(LED_TYPE_PSU1) | \ ++ BIT(LED_TYPE_PSU2)| BIT(LED_TYPE_STK1)| BIT(LED_TYPE_STK2)) ++#define AS4610_NPOE_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_7SEG_TENS) | \ ++ BIT(LED_TYPE_7SEG_TENS_POINT) | BIT(LED_TYPE_7SEG_DIGITS) | \ ++ BIT(LED_TYPE_7SEG_DIGITS_POINT)) ++#define AS4610_POE_LED_MAP (AS4610_NPOE_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_POE)) ++#define AS4610_54T_B_LED_MAP (AS4610_COMMON_LED_MAP | BIT(LED_TYPE_FAN) | BIT(LED_TYPE_ALARM)) ++ ++static int as4610_ledmaps[] = { ++ [PID_AS4610_30T] = AS4610_NPOE_LED_MAP, ++ [PID_AS4610_30P] = AS4610_POE_LED_MAP, ++ [PID_AS4610_54T] = AS4610_NPOE_LED_MAP, ++ [PID_AS4610_54P] = AS4610_POE_LED_MAP, ++ [PID_AS4610_54T_B] = AS4610_54T_B_LED_MAP, ++ [PID_RESERVED] = 0, ++}; ++ ++enum led_light_mode { ++ LED_MODE_OFF = 0, ++ LED_MODE_GREEN, ++ LED_MODE_GREEN_BLINK, ++ LED_MODE_AMBER, ++ LED_MODE_AMBER_BLINK, ++ LED_MODE_RED, ++ LED_MODE_RED_BLINK, ++ LED_MODE_BLUE, ++ LED_MODE_BLUE_BLINK, ++ LED_MODE_AUTO, ++ LED_MODE_AUTO_BLINKING, ++ LED_MODE_UNKNOWN, ++ LED_MODE_SEVEN_SEGMENT_MAX = 9, ++}; ++ ++static int as4610_led_read_value(u8 reg) ++{ ++ return accton_i2c_cpld_read(0x30, reg); ++} ++ ++static int as4610_led_write_value(u8 reg, u8 value) ++{ ++ return accton_i2c_cpld_write(0x30, reg, value); ++} ++ ++static void as4610_led_update(void) ++{ ++ mutex_lock(&ledctl->update_lock); ++ ++ if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) ++ || !ledctl->valid) { ++ int i; ++ ++ dev_dbg(&ledctl->pdev->dev, "Starting as4610_led update\n"); ++ ++ /* Update LED data ++ */ ++ for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { ++ int status = as4610_led_read_value(led_reg[i]); ++ ++ if (status < 0) { ++ ledctl->valid = 0; ++ dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); ++ goto exit; ++ } ++ else ++ { ++ ledctl->reg_val[i] = status; ++ } ++ } ++ ++ ledctl->last_updated = jiffies; ++ ledctl->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&ledctl->update_lock); ++} ++ ++static enum led_brightness seven_segment_get(struct led_classdev *cdev, u8 reg_id) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[reg_id] & LED_7SEG_REG_MASK); ++} ++ ++static void seven_segment_set(struct led_classdev *cdev, enum led_brightness mode, u8 reg_id) ++{ ++ if (mode > cdev->max_brightness) { ++ return; ++ } ++ ++ ledctl->reg_val[reg_id] &= 0xF0; ++ ledctl->reg_val[reg_id] |= mode; ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness seven_segment_digits_get(struct led_classdev *cdev) ++{ ++ return seven_segment_get(cdev, 1); ++} ++ ++static void seven_segment_digits_set(struct led_classdev *cdev, enum led_brightness mode) ++{ ++ seven_segment_set(cdev, mode, 1); ++} ++ ++static enum led_brightness seven_segment_tens_get(struct led_classdev *cdev) ++{ ++ return seven_segment_get(cdev, 2); ++} ++ ++static void seven_segment_tens_set(struct led_classdev *cdev, enum led_brightness mode) ++{ ++ seven_segment_set(cdev, mode, 2); ++} ++ ++static enum led_brightness seven_segment_point_get(struct led_classdev *cdev, u8 reg_id) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[reg_id] & LED_7SEG_POINT_REG_MASK) ? LED_MODE_GREEN : LED_MODE_OFF; ++} ++ ++static void seven_segment_point_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 reg_id) ++{ ++ /* Validate brightness */ ++ if ((int)mode < LED_MODE_OFF || mode > cdev->max_brightness) { ++ return; ++ } ++ ++ if ((int)mode == (int)LED_MODE_OFF) { ++ ledctl->reg_val[reg_id] &= ~LED_7SEG_POINT_REG_MASK; ++ } ++ else { /* LED_MODE_GREEN */ ++ ledctl->reg_val[reg_id] |= LED_7SEG_POINT_REG_MASK; ++ } ++ ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness seven_segment_tens_point_get(struct led_classdev *cdev) ++{ ++ return seven_segment_point_get(cdev, 2); ++} ++ ++static void seven_segment_tens_point_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ seven_segment_point_set(cdev, mode, 2); ++} ++ ++static enum led_brightness seven_segment_digits_point_get(struct led_classdev *cdev) ++{ ++ return seven_segment_point_get(cdev, 1); ++} ++ ++static void seven_segment_digits_point_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ seven_segment_point_set(cdev, mode, 1); ++} ++ ++static u8 led_is_blinking_mode(enum led_brightness mode) ++{ ++ return ((int)mode == (int)LED_MODE_GREEN_BLINK || ++ (int)mode == (int)LED_MODE_AMBER_BLINK || ++ (int)mode == (int)LED_MODE_AUTO_BLINKING); ++} ++ ++static enum led_brightness as4610_led_auto_get(u8 blink_mask) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[0] & blink_mask) ? LED_MODE_AUTO_BLINKING : LED_MODE_AUTO; ++} ++ ++static void as4610_led_auto_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 blink_mask) ++{ ++ /* Validate brightness */ ++ if ((int)mode < (int)LED_MODE_AUTO || mode > cdev->max_brightness) { ++ return; ++ } ++ ++ /* Set blinking */ ++ if (led_is_blinking_mode(mode)) { ++ ledctl->reg_val[0] |= blink_mask; ++ } ++ else { ++ ledctl->reg_val[0] &= ~blink_mask; ++ } ++ as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); ++} ++ ++static enum led_brightness as4610_led_psu1_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_PSU1_BLINK_MASK); ++} ++ ++static void as4610_led_psu1_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(cdev, mode, LED_MODE_PSU1_BLINK_MASK); ++} ++ ++static enum led_brightness as4610_led_psu2_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_PSU2_BLINK_MASK); ++} ++ ++static void as4610_led_psu2_set(struct led_classdev *led_cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(led_cdev, mode, LED_MODE_PSU2_BLINK_MASK); ++} ++ ++static enum led_brightness as4610_led_fan_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_FAN_BLINK_MASK); ++} ++ ++static void as4610_led_fan_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(cdev, mode, LED_MODE_FAN_BLINK_MASK); ++} ++ ++static u8 led_normal_light_mode_to_reg_val(enum led_brightness mode) ++{ ++ if (led_is_blinking_mode(mode)) { ++ mode -= 1; /* convert blinking mode to non-blinking mode */ ++ } ++ ++ if ((int)mode == (int)LED_MODE_GREEN) { ++ return LED_NORMAL_GREEN_VALUE; ++ } ++ else if ((int)mode == (int)LED_MODE_AMBER) { ++ return LED_NORMAL_AMBER_VALUE; ++ } ++ ++ return LED_NORMAL_OFF_VALUE; ++} ++ ++static enum led_brightness led_normal_reg_val_to_light_mode(u8 reg_val) ++{ ++ reg_val &= LED_NORMAL_MASK; ++ ++ if (reg_val & LED_NORMAL_GREEN_VALUE) { ++ return LED_MODE_GREEN; ++ } ++ else if (reg_val & LED_NORMAL_AMBER_VALUE) { ++ return LED_MODE_AMBER; ++ } ++ ++ return LED_MODE_OFF; ++} ++ ++static void as4610_led_normal_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 blink_mask, u8 reg_id, u8 reg_mask, u8 shift) ++{ ++ /* Validate brightness */ ++ if (mode > cdev->max_brightness) { ++ return; ++ } ++ ++ /* Set blinking */ ++ if (led_is_blinking_mode(mode)) { ++ ledctl->reg_val[0] |= blink_mask; ++ } ++ else { ++ ledctl->reg_val[0] &= ~blink_mask; ++ } ++ as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); ++ ++ /* Set color */ ++ ledctl->reg_val[reg_id] &= ~reg_mask; ++ ledctl->reg_val[reg_id] |= (led_normal_light_mode_to_reg_val(mode) << shift); ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness as4610_led_normal_get(u8 reg_id, u8 blink_mask, u8 shift) ++{ ++ u8 blinking = 0; ++ enum led_brightness mode; ++ ++ as4610_led_update(); ++ ++ mode = led_normal_reg_val_to_light_mode(ledctl->reg_val[reg_id] >> shift); ++ if ((int)mode == (int)LED_MODE_OFF) { ++ return mode; ++ } ++ ++ /* Checking blinking */ ++ if (ledctl->reg_val[0] & blink_mask) { ++ blinking = 1; ++ } ++ ++ return blinking ? (mode+1) : mode; ++} ++ ++static void as4610_led_sys_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_SYS_BLINK_MASK, ++ 3, LED_TYPE_SYS_REG_MASK, 6); ++} ++ ++static enum led_brightness as4610_led_sys_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(3, LED_MODE_SYS_BLINK_MASK, 6); ++} ++ ++static void as4610_led_pri_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_PRI_BLINK_MASK, ++ 3, LED_TYPE_PRI_REG_MASK, 4); ++} ++ ++static enum led_brightness as4610_led_pri_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(3, LED_MODE_PRI_BLINK_MASK, 4); ++} ++ ++static void as4610_led_poe_alarm_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_POE_ALARM_BLINK_MASK, ++ 4, LED_TYPE_POE_ALARM_REG_MASK, 0); ++} ++ ++static enum led_brightness as4610_led_poe_alarm_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_POE_ALARM_BLINK_MASK, 0); ++} ++ ++static void as4610_led_stk1_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_STK1_BLINK_MASK, ++ 4, LED_TYPE_STK1_REG_MASK, 6); ++} ++ ++static enum led_brightness as4610_led_stk1_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_STK1_BLINK_MASK, 6); ++} ++ ++static void as4610_led_stk2_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_STK2_BLINK_MASK, ++ 4, LED_TYPE_STK2_REG_MASK, 4); ++} ++ ++static enum led_brightness as4610_led_stk2_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_STK2_BLINK_MASK, 4); ++} ++ ++static struct led_classdev as4610_leds[] = { ++ [LED_TYPE_SYS] = { ++ .name = "as4610::sys", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_sys_set, ++ .brightness_get = as4610_led_sys_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_PRI] = { ++ .name = "as4610::pri", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_pri_set, ++ .brightness_get = as4610_led_pri_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_PSU1] = { ++ .name = "as4610::psu1", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_psu1_set, ++ .brightness_get = as4610_led_psu1_get, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_PSU2] = { ++ .name = "as4610::psu2", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_psu2_set, ++ .brightness_get = as4610_led_psu2_get, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_STK1] = { ++ .name = "as4610::stk1", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_stk1_set, ++ .brightness_get = as4610_led_stk1_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_STK2] = { ++ .name = "as4610::stk2", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_stk2_set, ++ .brightness_get = as4610_led_stk2_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_7SEG_TENS] = { ++ .name = "as4610::7seg_tens", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_tens_set, ++ .brightness_get = seven_segment_tens_get, ++ .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, ++ }, ++ [LED_TYPE_7SEG_TENS_POINT] = { ++ .name = "as4610::7seg_tens_point", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_tens_point_set, ++ .brightness_get = seven_segment_tens_point_get, ++ .max_brightness = LED_MODE_GREEN, ++ }, ++ [LED_TYPE_7SEG_DIGITS] = { ++ .name = "as4610::7seg_digits", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_digits_set, ++ .brightness_get = seven_segment_digits_get, ++ .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, ++ }, ++ [LED_TYPE_7SEG_DIGITS_POINT] = { ++ .name = "as4610::7seg_digits_point", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_digits_point_set, ++ .brightness_get = seven_segment_digits_point_get, ++ .max_brightness = LED_MODE_GREEN, ++ }, ++ [LED_TYPE_FAN] = { ++ .name = "as4610::fan", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_fan_set, ++ .brightness_get = as4610_led_fan_get, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_POE] = { ++ .name = "as4610::poe", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_poe_alarm_set, ++ .brightness_get = as4610_led_poe_alarm_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_ALARM] = { ++ .name = "as4610::alarm", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_poe_alarm_set, ++ .brightness_get = as4610_led_poe_alarm_get, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++}; ++ ++static int as4610_led_probe(struct platform_device *pdev) ++{ ++ int ret = 0, i; ++ ++ for (i = 0; i < NUM_OF_LED; i++) { ++ if (!(ledctl->led_map & BIT(i))) { ++ continue; ++ } ++ ++ ret = led_classdev_register(&pdev->dev, &as4610_leds[i]); ++ if (ret < 0) { ++ goto error; ++ } ++ } ++ ++ return 0; ++ ++error: ++ for (i = i-1; i >= 0; i--) { ++ /* only unregister the LEDs that were successfully registered */ ++ if (!(ledctl->led_map & BIT(i))) { ++ continue; ++ } ++ ++ led_classdev_unregister(&as4610_leds[i]); ++ } ++ ++ return ret; ++} ++ ++static int as4610_led_remove(struct platform_device *pdev) ++{ ++ int i; ++ ++ for (i = 0; i < NUM_OF_LED; i++) { ++ if (!(ledctl->led_map & BIT(i))) { ++ continue; ++ } ++ ++ led_classdev_unregister(&as4610_leds[i]); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver as4610_led_driver = { ++ .probe = as4610_led_probe, ++ .remove = as4610_led_remove, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init as4610_led_init(void) ++{ ++ int ret, pid; ++ ++ if (as4610_product_id() == PID_UNKNOWN) { ++ return -ENODEV; ++ } ++ ++ ret = platform_driver_register(&as4610_led_driver); ++ if (ret < 0) { ++ goto exit; ++ } ++ ++ ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL); ++ if (!ledctl) { ++ ret = -ENOMEM; ++ platform_driver_unregister(&as4610_led_driver); ++ goto exit; ++ } ++ ++ pid = as4610_product_id(); ++ if (pid == PID_UNKNOWN) { ++ return -ENODEV; ++ } ++ ++ ledctl->led_map = as4610_ledmaps[pid]; ++ mutex_init(&ledctl->update_lock); ++ ++ ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); ++ if (IS_ERR(ledctl->pdev)) { ++ ret = PTR_ERR(ledctl->pdev); ++ platform_driver_unregister(&as4610_led_driver); ++ kfree(ledctl); ++ goto exit; ++ } ++ ++exit: ++ return ret; ++} ++ ++static void __exit as4610_led_exit(void) ++{ ++ if (!ledctl) { ++ return; ++ } ++ ++ platform_device_unregister(ledctl->pdev); ++ platform_driver_unregister(&as4610_led_driver); ++ kfree(ledctl); ++} ++ ++late_initcall(as4610_led_init); ++module_exit(as4610_led_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_led driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig +index 7c7b208..1c62b33 100644 +--- a/drivers/misc/eeprom/Kconfig ++++ b/drivers/misc/eeprom/Kconfig +@@ -117,5 +117,14 @@ config EEPROM_SFF_8436 + + This driver can also be built as a module. If so, the module + will be called sff_8436. ++ ++config EEPROM_ACCTON_AS4610_SFP ++ tristate "Accton as4610 sfp" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 sfp. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_sfp. + + endmenu +diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile +index 9edd559..12f7cae 100644 +--- a/drivers/misc/eeprom/Makefile ++++ b/drivers/misc/eeprom/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o + obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o + obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o + obj-$(CONFIG_EEPROM_SFF_8436) += sff_8436_eeprom.o ++obj-$(CONFIG_EEPROM_ACCTON_AS4610_SFP) += accton_as4610_sfp.o +diff --git a/drivers/misc/eeprom/accton_as4610_sfp.c b/drivers/misc/eeprom/accton_as4610_sfp.c +new file mode 100644 +index 0000000..39c17ec +--- /dev/null ++++ b/drivers/misc/eeprom/accton_as4610_sfp.c +@@ -0,0 +1,1269 @@ ++/* ++ * SFP driver for accton as4610 sfp ++ * ++ * Copyright (C) Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "as4610_sfp" /* Platform dependent */ ++ ++#define DEBUG_MODE 0 ++ ++#if (DEBUG_MODE == 1) ++ #define DEBUG_PRINT(fmt, args...) \ ++ printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) ++#else ++ #define DEBUG_PRINT(fmt, args...) ++#endif ++ ++#define NUM_OF_SFP_PORT 32 ++#define EEPROM_NAME "sfp_eeprom" ++#define EEPROM_SIZE 256 /* 256 byte eeprom */ ++#define BIT_INDEX(i) (1ULL << (i)) ++#define USE_I2C_BLOCK_READ 0 /* Platform dependent */ ++#define I2C_RW_RETRY_COUNT 3 ++#define I2C_RW_RETRY_INTERVAL 100 /* ms */ ++ ++#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) ++#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) ++ ++#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 ++#define SFF8024_DEVICE_ID_SFP 0x3 ++#define SFF8024_DEVICE_ID_QSFP 0xC ++#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD ++#define SFF8024_DEVICE_ID_QSFP28 0x11 ++ ++#define SFF8472_DIAG_MON_TYPE_ADDR 92 ++#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 ++#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 ++#define SFF8472_10G_BASE_MASK 0xF0 ++ ++#define SFF8436_RX_LOS_ADDR 3 ++#define SFF8436_TX_FAULT_ADDR 4 ++#define SFF8436_TX_DISABLE_ADDR 86 ++ ++static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); ++static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; ++static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); ++static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); ++static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); ++extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++ ++enum sfp_sysfs_attributes { ++ PRESENT, ++ PRESENT_ALL, ++ PORT_NUMBER, ++ PORT_TYPE, ++ DDM_IMPLEMENTED, ++ TX_FAULT, ++ TX_FAULT1, ++ TX_FAULT2, ++ TX_FAULT3, ++ TX_FAULT4, ++ TX_DISABLE, ++ TX_DISABLE1, ++ TX_DISABLE2, ++ TX_DISABLE3, ++ TX_DISABLE4, ++ RX_LOS, ++ RX_LOS1, ++ RX_LOS2, ++ RX_LOS3, ++ RX_LOS4, ++ RX_LOS_ALL ++}; ++ ++/* SFP/QSFP common attributes for sysfs */ ++static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); ++static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); ++static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); ++static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); ++static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); ++ ++/* QSFP attributes for sysfs */ ++static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); ++static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); ++static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); ++static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); ++static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); ++static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); ++static struct attribute *qsfp_attributes[] = { ++ &sensor_dev_attr_sfp_port_number.dev_attr.attr, ++ &sensor_dev_attr_sfp_port_type.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, ++ NULL ++}; ++ ++/* SFP msa attributes for sysfs */ ++static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); ++static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); ++static struct attribute *sfp_msa_attributes[] = { ++ &sensor_dev_attr_sfp_port_number.dev_attr.attr, ++ &sensor_dev_attr_sfp_port_type.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present.dev_attr.attr, ++ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, ++ &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los.dev_attr.attr, ++ &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, ++ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, ++ NULL ++}; ++ ++/* SFP ddm attributes for sysfs */ ++static struct attribute *sfp_ddm_attributes[] = { ++ NULL ++}; ++ ++/* Platform dependent +++ */ ++enum port_numbers { ++as4610_sfp1, /* Port 25 for as4610_30, Port 49 for as4610_54 */ ++as4610_sfp2, /* Port 26 for as4610_30, Port 50 for as4610_54 */ ++as4610_sfp3, /* Port 27 for as4610_30, Port 51 for as4610_54 */ ++as4610_sfp4, /* Port 28 for as4610_30, Port 52 for as4610_54 */ ++as4610_sfp5, /* Port 29 for as4610_30, Port 53 for as4610_54 */ ++as4610_sfp6, /* Port 30 for as4610_30, Port 54 for as4610_54 */ ++}; ++ ++static const struct i2c_device_id sfp_device_id[] = { ++{"as4610_sfp1", as4610_sfp1}, ++{"as4610_sfp2", as4610_sfp2}, ++{"as4610_sfp3", as4610_sfp3}, ++{"as4610_sfp4", as4610_sfp4}, ++{"as4610_sfp5", as4610_sfp5}, ++{"as4610_sfp6", as4610_sfp6}, ++{ /* LIST END */ } ++}; ++MODULE_DEVICE_TABLE(i2c, sfp_device_id); ++/* Platform dependent --- */ ++ ++/* ++ * list of valid port types ++ * note OOM_PORT_TYPE_NOT_PRESENT to indicate no ++ * module is present in this port ++ */ ++typedef enum oom_driver_port_type_e { ++ OOM_DRIVER_PORT_TYPE_INVALID, ++ OOM_DRIVER_PORT_TYPE_NOT_PRESENT, ++ OOM_DRIVER_PORT_TYPE_SFP, ++ OOM_DRIVER_PORT_TYPE_SFP_PLUS, ++ OOM_DRIVER_PORT_TYPE_QSFP, ++ OOM_DRIVER_PORT_TYPE_QSFP_PLUS, ++ OOM_DRIVER_PORT_TYPE_QSFP28 ++} oom_driver_port_type_t; ++ ++enum driver_type_e { ++ DRIVER_TYPE_SFP_MSA, ++ DRIVER_TYPE_SFP_DDM, ++ DRIVER_TYPE_QSFP ++}; ++ ++/* Each client has this additional data ++ */ ++struct eeprom_data { ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ struct bin_attribute bin; /* eeprom data */ ++}; ++ ++struct sfp_msa_data { ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u64 status[6]; /* bit0:port0, bit1:port1 and so on */ ++ /* index 0 => tx_fail ++ 1 => tx_disable ++ 2 => rx_loss ++ 3 => device id ++ 4 => 10G Ethernet Compliance Codes ++ to distinguish SFP or SFP+ ++ 5 => DIAGNOSTIC MONITORING TYPE */ ++ struct eeprom_data eeprom; ++}; ++ ++struct sfp_ddm_data { ++ struct eeprom_data eeprom; ++}; ++ ++struct qsfp_data { ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 status[3]; /* bit0:port0, bit1:port1 and so on */ ++ /* index 0 => tx_fail ++ 1 => tx_disable ++ 2 => rx_loss */ ++ ++ u8 device_id; ++ struct eeprom_data eeprom; ++}; ++ ++struct sfp_port_data { ++ struct mutex update_lock; ++ enum driver_type_e driver_type; ++ int port; /* CPLD port index */ ++ oom_driver_port_type_t port_type; ++ u64 present; /* present status, bit0:port0, bit1:port1 and so on */ ++ ++ struct sfp_msa_data *msa; ++ struct sfp_ddm_data *ddm; ++ struct qsfp_data *qsfp; ++ ++ struct i2c_client *client; ++}; ++ ++static ssize_t show_port_number(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ return sprintf(buf, "sfp %d\n", data->port); ++} ++ ++/* Platform dependent +++ */ ++static struct sfp_port_data *sfp_update_present(struct i2c_client *client) ++{ ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int i = 0; ++ int status = -1; ++ u8 regs[] = {0x2, 0x3, 0x21}; ++ ++ DEBUG_PRINT("Starting sfp present status update"); ++ mutex_lock(&data->update_lock); ++ ++ /* Read present status of port 49~54 */ ++ data->present = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ status = accton_i2c_cpld_read(0x30, regs[i]); ++ ++ if (status < 0) { ++ DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); ++ goto exit; ++ } ++ ++ DEBUG_PRINT("Present status = 0x%lx", data->present); ++ switch (i) { ++ case 0: ++ data->present |= (status & BIT_INDEX(6)) >> 6; /* port 25/49 */ ++ data->present |= (status & BIT_INDEX(2)) >> 1; /* port 26/50 */ ++ break; ++ case 1: ++ data->present |= (status & BIT_INDEX(6)) >> 4; /* port 27/51 */ ++ data->present |= (status & BIT_INDEX(2)) << 1; /* port 28/52 */ ++ break; ++ case 2: ++ data->present |= (status & BIT_INDEX(0)) << 4; /* port 29/53 */ ++ data->present |= (status & BIT_INDEX(4)) << 1; /* port 30/54 */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ DEBUG_PRINT("Present status = 0x%lx", data->present); ++exit: ++ mutex_unlock(&data->update_lock); ++ return (status < 0) ? ERR_PTR(status) : data; ++} ++ ++static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int i = 0; ++ int status = -1; ++ u8 regs[] = {0x2, 0x3, 0x21}; ++ ++ if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { ++ return data; ++ } ++ ++ DEBUG_PRINT("Starting as4610 sfp tx rx status update"); ++ mutex_lock(&data->update_lock); ++ data->msa->valid = 0; ++ memset(data->msa->status, 0, sizeof(data->msa->status)); ++ ++ /* Read status of port 49~52(SFP port) */ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ status = accton_i2c_cpld_read(0x30, regs[i]); ++ ++ if (status < 0) { ++ DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); ++ goto exit; ++ } ++ ++ DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", ++ data->msa->status[0], data->msa->status[1], data->msa->status[2]); ++ switch (i) { ++ case 0: ++ /* port 25/49 */ ++ data->msa->status[0] |= (status & BIT_INDEX(5)) >> 5; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(4)) >> 4; /* rx_los */ ++ /* port 26/50 */ ++ data->msa->status[0] |= (status & BIT_INDEX(1)) << 0; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(0)) << 1; /* rx_los */ ++ break; ++ case 1: ++ /* port 27/51 */ ++ data->msa->status[0] |= (status & BIT_INDEX(5)) >> 3; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(4)) >> 2; /* rx_los */ ++ /* port 28/52 */ ++ data->msa->status[0] |= (status & BIT_INDEX(1)) << 1; /* tx_fail */ ++ data->msa->status[2] |= (status & BIT_INDEX(0)) << 2; /* rx_los */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", ++ data->msa->status[0], data->msa->status[1], data->msa->status[2]); ++ data->msa->valid = 1; ++ data->msa->last_updated = jiffies; ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return data; ++} ++/* Platform dependent --- */ ++ ++static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ if (data->driver_type == DRIVER_TYPE_QSFP) { ++ return qsfp_set_tx_disable(dev, da, buf, count); ++ } ++ ++ return 0; ++} ++ ++static int sfp_is_port_present(struct i2c_client *client, int port) ++{ ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ data = sfp_update_present(client); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ return (data->present & BIT_INDEX(data->port)) ? 1 : 0; /* Platform dependent */ ++} ++ ++/* Platform dependent +++ */ ++static ssize_t show_present(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ if (PRESENT_ALL == attr->index) { ++ struct sfp_port_data *data = sfp_update_present(client); ++ ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ /* Return values 25/49 -> 30/54 in order */ ++ return sprintf(buf, "%.2x\n", (u8)(data->present)); ++ } ++ else { ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int present = sfp_is_port_present(client, data->port); ++ ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ /* PRESENT */ ++ return sprintf(buf, "%d\n", present); ++ } ++} ++/* Platform dependent --- */ ++ ++static struct sfp_port_data *sfp_update_port_type(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ u8 buf = 0; ++ int status; ++ ++ mutex_lock(&data->update_lock); ++ ++ switch (data->driver_type) { ++ case DRIVER_TYPE_SFP_MSA: ++ { ++ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ if (buf != SFF8024_DEVICE_ID_SFP) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); ++ data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; ++ break; ++ } ++ case DRIVER_TYPE_QSFP: ++ { ++ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); ++ switch (buf) { ++ case SFF8024_DEVICE_ID_QSFP: ++ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; ++ break; ++ case SFF8024_DEVICE_ID_QSFP_PLUS: ++ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; ++ break; ++ case SFF8024_DEVICE_ID_QSFP28: ++ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; ++ break; ++ default: ++ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; ++ break; ++ } ++ ++ break; ++ } ++ default: ++ break; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return data; ++} ++ ++static ssize_t show_port_type(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int present = sfp_is_port_present(client, data->port); ++ ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (!present) { ++ return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); ++ } ++ ++ sfp_update_port_type(dev); ++ return sprintf(buf, "%d\n", data->port_type); ++} ++ ++static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ int i, status = -1; ++ u8 buf = 0; ++ u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; ++ ++ if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { ++ return data; ++ } ++ ++ DEBUG_PRINT("Starting sfp tx rx status update"); ++ mutex_lock(&data->update_lock); ++ data->qsfp->valid = 0; ++ memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); ++ ++ /* Notify device to update tx fault/ tx disable/ rx los status */ ++ for (i = 0; i < ARRAY_SIZE(reg); i++) { ++ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ goto exit; ++ } ++ } ++ msleep(200); ++ ++ /* Read actual tx fault/ tx disable/ rx los status */ ++ for (i = 0; i < ARRAY_SIZE(reg); i++) { ++ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); ++ if (unlikely(status < 0)) { ++ goto exit; ++ } ++ ++ DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); ++ data->qsfp->status[i] = (buf & 0xF); ++ } ++ ++ data->qsfp->valid = 1; ++ data->qsfp->last_updated = jiffies; ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return (status < 0) ? ERR_PTR(status) : data; ++} ++ ++static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int present; ++ u8 val = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ present = sfp_is_port_present(client, data->port); ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (present == 0) { ++ /* port is not present */ ++ return -ENXIO; ++ } ++ ++ data = qsfp_update_tx_rx_status(dev); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ switch (attr->index) { ++ case TX_FAULT: ++ val = !!(data->qsfp->status[2] & 0xF); ++ break; ++ case TX_FAULT1: ++ case TX_FAULT2: ++ case TX_FAULT3: ++ case TX_FAULT4: ++ val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); ++ break; ++ case TX_DISABLE: ++ val = data->qsfp->status[1] & 0xF; ++ break; ++ case TX_DISABLE1: ++ case TX_DISABLE2: ++ case TX_DISABLE3: ++ case TX_DISABLE4: ++ val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); ++ break; ++ case RX_LOS: ++ val = !!(data->qsfp->status[0] & 0xF); ++ break; ++ case RX_LOS1: ++ case RX_LOS2: ++ case RX_LOS3: ++ case RX_LOS4: ++ val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); ++ break; ++ default: ++ break; ++ } ++ ++ return sprintf(buf, "%d\n", val); ++} ++ ++static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ long disable; ++ int status; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ status = sfp_is_port_present(client, data->port); ++ if (IS_ERR_VALUE(status)) { ++ return status; ++ } ++ ++ if (!status) { ++ /* port is not present */ ++ return -ENXIO; ++ } ++ ++ status = kstrtol(buf, 10, &disable); ++ if (status) { ++ return status; ++ } ++ ++ data = qsfp_update_tx_rx_status(dev); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ mutex_lock(&data->update_lock); ++ ++ if (attr->index == TX_DISABLE) { ++ data->qsfp->status[1] = disable & 0xF; ++ } ++ else {/* TX_DISABLE1 ~ TX_DISABLE4*/ ++ if (disable) { ++ data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); ++ } ++ else { ++ data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); ++ } ++ } ++ ++ DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); ++ status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); ++ if (unlikely(status < 0)) { ++ count = status; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int status; ++ char ddm; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ status = sfp_is_port_present(client, data->port); ++ if (IS_ERR_VALUE(status)) { ++ return status; ++ } ++ ++ if (status == 0) { ++ /* port is not present */ ++ return -ENODEV; ++ } ++ ++ status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); ++ if (unlikely(status < 0)) { ++ return status; ++ } ++ ++ return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); ++} ++ ++/* Platform dependent +++ */ ++static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ u8 val = 0, index = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ ++ if (data->driver_type == DRIVER_TYPE_QSFP) { ++ return qsfp_show_tx_rx_status(dev, da, buf); ++ } ++ ++ data = sfp_update_tx_rx_status(dev); ++ if (IS_ERR(data)) { ++ return PTR_ERR(data); ++ } ++ ++ if(attr->index == RX_LOS_ALL) { ++ /** Return values 25/49 -> 28/52 in order */ ++ return sprintf(buf, "%.2x\n", (u8)(data->msa->status[2])); ++ } ++ ++ switch (attr->index) { ++ case TX_FAULT: ++ index = 0; ++ break; ++ case TX_DISABLE: ++ index = 1; ++ break; ++ case RX_LOS: ++ index = 2; ++ break; ++ default: ++ return 0; ++ } ++ ++ val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; ++ return sprintf(buf, "%d\n", val); ++} ++/* Platform dependent --- */ ++static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, ++ int data_len) ++{ ++#if USE_I2C_BLOCK_READ ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ if (data_len > I2C_SMBUS_BLOCK_MAX) { ++ data_len = I2C_SMBUS_BLOCK_MAX; ++ } ++ ++ while (retry) { ++ status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ return status; ++ } ++ ++ return data_len; ++#else ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ while (retry) { ++ status = i2c_smbus_write_byte_data(client, command, *data); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ return status; ++ } ++ ++ return 1; ++#endif ++ ++ ++} ++ ++static ssize_t sfp_port_write(struct sfp_port_data *data, ++ const char *buf, loff_t off, size_t count) ++{ ++ ssize_t retval = 0; ++ ++ if (unlikely(!count)) { ++ return count; ++ } ++ ++ /* ++ * Write data to chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&data->update_lock); ++ ++ while (count) { ++ ssize_t status; ++ ++ status = sfp_eeprom_write(data->client, off, buf, count); ++ if (status <= 0) { ++ if (retval == 0) { ++ retval = status; ++ } ++ break; ++ } ++ buf += status; ++ off += status; ++ count -= status; ++ retval += status; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return retval; ++} ++ ++ ++static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ int present; ++ struct sfp_port_data *data; ++ DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); ++ data = dev_get_drvdata(container_of(kobj, struct device, kobj)); ++ ++ present = sfp_is_port_present(data->client, data->port); ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (present == 0) { ++ /* port is not present */ ++ return -ENODEV; ++ } ++ ++ return sfp_port_write(data, buf, off, count); ++} ++ ++static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, ++ int data_len) ++{ ++#if USE_I2C_BLOCK_READ ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ if (data_len > I2C_SMBUS_BLOCK_MAX) { ++ data_len = I2C_SMBUS_BLOCK_MAX; ++ } ++ ++ while (retry) { ++ status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ goto abort; ++ } ++ if (unlikely(status != data_len)) { ++ status = -EIO; ++ goto abort; ++ } ++ ++ //result = data_len; ++ ++abort: ++ return status; ++#else ++ int status, retry = I2C_RW_RETRY_COUNT; ++ ++ while (retry) { ++ status = i2c_smbus_read_byte_data(client, command); ++ if (unlikely(status < 0)) { ++ msleep(I2C_RW_RETRY_INTERVAL); ++ retry--; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (unlikely(status < 0)) { ++ dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); ++ goto abort; ++ } ++ ++ *data = (u8)status; ++ status = 1; ++ ++abort: ++ return status; ++#endif ++} ++ ++static ssize_t sfp_port_read(struct sfp_port_data *data, ++ char *buf, loff_t off, size_t count) ++{ ++ ssize_t retval = 0; ++ ++ if (unlikely(!count)) { ++ DEBUG_PRINT("Count = 0, return"); ++ return count; ++ } ++ ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&data->update_lock); ++ ++ while (count) { ++ ssize_t status; ++ ++ status = sfp_eeprom_read(data->client, off, buf, count); ++ if (status <= 0) { ++ if (retval == 0) { ++ retval = status; ++ } ++ break; ++ } ++ ++ buf += status; ++ off += status; ++ count -= status; ++ retval += status; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return retval; ++ ++} ++ ++static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ int present; ++ struct sfp_port_data *data; ++ DEBUG_PRINT("offset = (%d), count = (%d)", off, count); ++ data = dev_get_drvdata(container_of(kobj, struct device, kobj)); ++ ++ present = sfp_is_port_present(data->client, data->port); ++ if (IS_ERR_VALUE(present)) { ++ return present; ++ } ++ ++ if (present == 0) { ++ /* port is not present */ ++ return -ENODEV; ++ } ++ ++ return sfp_port_read(data, buf, off, count); ++} ++ ++static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) ++{ ++ int err; ++ ++ sysfs_bin_attr_init(eeprom); ++ eeprom->attr.name = EEPROM_NAME; ++ eeprom->attr.mode = S_IWUSR | S_IRUGO; ++ eeprom->read = sfp_bin_read; ++ eeprom->write = sfp_bin_write; ++ eeprom->size = EEPROM_SIZE; ++ ++ /* Create eeprom file */ ++ err = sysfs_create_bin_file(kobj, eeprom); ++ if (err) { ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) ++{ ++ sysfs_remove_bin_file(kobj, eeprom); ++ return 0; ++} ++ ++static const struct attribute_group sfp_msa_group = { ++ .attrs = sfp_msa_attributes, ++}; ++ ++static int sfp_i2c_check_functionality(struct i2c_client *client) ++{ ++#if USE_I2C_BLOCK_READ ++ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); ++#else ++ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); ++#endif ++} ++ ++static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, ++ struct sfp_msa_data **data) ++{ ++ int status; ++ struct sfp_msa_data *msa; ++ ++ if (!sfp_i2c_check_functionality(client)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); ++ if (!msa) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ /* init eeprom */ ++ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); ++ if (status) { ++ goto exit_remove; ++ } ++ ++ *data = msa; ++ dev_info(&client->dev, "sfp msa '%s'\n", client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); ++exit_free: ++ kfree(msa); ++exit: ++ ++ return status; ++} ++ ++static const struct attribute_group sfp_ddm_group = { ++ .attrs = sfp_ddm_attributes, ++}; ++ ++static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, ++ struct sfp_ddm_data **data) ++{ ++ int status; ++ struct sfp_ddm_data *ddm; ++ ++ if (!sfp_i2c_check_functionality(client)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); ++ if (!ddm) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ /* init eeprom */ ++ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); ++ if (status) { ++ goto exit_remove; ++ } ++ ++ *data = ddm; ++ dev_info(&client->dev, "sfp ddm '%s'\n", client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); ++exit_free: ++ kfree(ddm); ++exit: ++ ++ return status; ++} ++ ++static const struct attribute_group qsfp_group = { ++ .attrs = qsfp_attributes, ++}; ++ ++static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, ++ struct qsfp_data **data) ++{ ++ int status; ++ struct qsfp_data *qsfp; ++ ++ if (!sfp_i2c_check_functionality(client)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); ++ if (!qsfp) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &qsfp_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ /* init eeprom */ ++ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); ++ if (status) { ++ goto exit_remove; ++ } ++ ++ *data = qsfp; ++ dev_info(&client->dev, "qsfp '%s'\n", client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &qsfp_group); ++exit_free: ++ kfree(qsfp); ++exit: ++ ++ return status; ++} ++ ++/* Platform dependent +++ */ ++static int sfp_device_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct sfp_port_data *data = NULL; ++ ++ data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); ++ if (!data) { ++ return -ENOMEM; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ data->port = dev_id->driver_data; ++ data->client = client; ++ ++ if (client->addr != SFP_EEPROM_A0_I2C_ADDR && ++ client->addr != SFP_EEPROM_A2_I2C_ADDR ) { ++ return -ENODEV; ++ } ++ ++ if (dev_id->driver_data >= as4610_sfp1 && dev_id->driver_data <= as4610_sfp4) { ++ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { ++ data->driver_type = DRIVER_TYPE_SFP_MSA; ++ return sfp_msa_probe(client, dev_id, &data->msa); ++ } ++ else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { ++ data->driver_type = DRIVER_TYPE_SFP_DDM; ++ return sfp_ddm_probe(client, dev_id, &data->ddm); ++ } ++ } ++ else if (dev_id->driver_data >= as4610_sfp5 && dev_id->driver_data <= as4610_sfp6) { ++ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { ++ data->driver_type = DRIVER_TYPE_QSFP; ++ return qsfp_probe(client, dev_id, &data->qsfp); ++ } ++ } ++ ++ return -ENODEV; ++} ++/* Platform dependent --- */ ++ ++static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) ++{ ++ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); ++ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); ++ kfree(data); ++ return 0; ++} ++ ++static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) ++{ ++ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); ++ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); ++ kfree(data); ++ return 0; ++} ++ ++static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) ++{ ++ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); ++ sysfs_remove_group(&client->dev.kobj, &qsfp_group); ++ kfree(data); ++ return 0; ++} ++ ++static int sfp_device_remove(struct i2c_client *client) ++{ ++ struct sfp_port_data *data = i2c_get_clientdata(client); ++ ++ switch (data->driver_type) { ++ case DRIVER_TYPE_SFP_MSA: ++ return sfp_msa_remove(client, data->msa); ++ case DRIVER_TYPE_SFP_DDM: ++ return sfp_ddm_remove(client, data->ddm); ++ case DRIVER_TYPE_QSFP: ++ return qfp_remove(client, data->qsfp); ++ } ++ ++ return 0; ++} ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; ++ ++static struct i2c_driver sfp_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ }, ++ .probe = sfp_device_probe, ++ .remove = sfp_device_remove, ++ .id_table = sfp_device_id, ++ .address_list = normal_i2c, ++}; ++ ++static int __init sfp_init(void) ++{ ++ return i2c_add_driver(&sfp_driver); ++} ++ ++static void __exit sfp_exit(void) ++{ ++ i2c_del_driver(&sfp_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("accton as4610_sfp driver"); ++MODULE_LICENSE("GPL"); ++ ++late_initcall(sfp_init); ++module_exit(sfp_exit); ++ +diff --git a/include/linux/accton_i2c_cpld.h b/include/linux/accton_i2c_cpld.h +new file mode 100644 +index 0000000..9b75abd +--- /dev/null ++++ b/include/linux/accton_i2c_cpld.h +@@ -0,0 +1,76 @@ ++/* ++ * A hwmon driver for the accton_i2c_cpld ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++ ++#define AS4610_CPLD_SLAVE_ADDR 0x30 ++#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ ++ ++enum as4610_product_id_e { ++ PID_AS4610_30T, ++ PID_AS4610_30P, ++ PID_AS4610_54T, ++ PID_AS4610_54P, ++ PID_RESERVED, ++ PID_AS4610_54T_B, ++ PID_UNKNOWN ++}; ++ ++static inline int as4610_product_id(void) ++{ ++ int pid = accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); ++ pid &= 0xF; ++ ++ if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) { ++ return PID_UNKNOWN; ++ } ++ ++ return pid; ++} ++ ++static inline int as4610_is_poe_system(void) ++{ ++ int pid = as4610_product_id(); ++ return (pid == PID_AS4610_30P || pid == PID_AS4610_54P); ++} ++ ++static inline int as4610_number_of_system_fan(void) ++{ ++ int nFan = 0; ++ int pid = as4610_product_id(); ++ ++ switch (pid) { ++ case PID_AS4610_30P: ++ case PID_AS4610_54P: ++ nFan = 1; ++ break; ++ case PID_AS4610_54T_B: ++ nFan = 2; ++ break; ++ default: ++ nFan = 0; ++ break; ++ } ++ ++ return nFan; ++} ++ + diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch new file mode 100644 index 00000000..bd9fa7d8 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_Makefile.fwinst.patch @@ -0,0 +1,13 @@ +--- a/scripts/Makefile.fwinst ++++ b/scripts/Makefile.fwinst +@@ -13,7 +13,7 @@ src := $(obj) + -include $(objtree)/.config + + include scripts/Kbuild.include +-include $(srctree)/$(obj)/Makefile ++-include $(srctree)/$(obj)/Makefile + + include scripts/Makefile.host + +diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c +index f208f90..78dd083 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch new file mode 100644 index 00000000..05823a6f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_conf.c.patch @@ -0,0 +1,121 @@ +--- a/scripts/kconfig/conf.c ++++ b/scripts/kconfig/conf.c +@@ -36,6 +36,7 @@ enum input_mode { + } input_mode = oldaskconfig; + + static int indent = 1; ++static int tty_stdio; + static int valid_stdin = 1; + static int sync_kconfig; + static int conf_cnt; +@@ -108,6 +109,8 @@ static int conf_askvalue(struct symbol *sym, const char *def) + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); ++ if (!tty_stdio) ++ printf("\n"); + return 1; + default: + break; +@@ -364,7 +367,6 @@ static void conf(struct menu *menu) + switch (prop->type) { + case P_MENU: + if ((input_mode == silentoldconfig || +- input_mode == listnewconfig || + input_mode == oldnoconfig) && + rootEntry != menu) { + check_conf(menu); +@@ -425,11 +427,7 @@ static void check_conf(struct menu *menu) + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { +- if (input_mode == listnewconfig) { +- if (sym->name && !sym_is_choice_value(sym)) { +- printf("%s%s\n", CONFIG_, sym->name); +- } +- } else if (input_mode != oldnoconfig) { ++ if (input_mode != oldnoconfig) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); +@@ -442,6 +440,30 @@ static void check_conf(struct menu *menu) + check_conf(child); + } + ++static void report_conf(struct menu *menu, bool verbose) ++{ ++ struct symbol *sym; ++ struct menu *child; ++ ++ if (!menu_is_visible(menu)) ++ return; ++ ++ if (verbose && menu == &rootmenu) { ++ printf("\n#\n" ++ "# Changes:\n" ++ "#\n"); ++ } ++ ++ sym = menu->sym; ++ if (sym && (sym->flags & SYMBOL_NEW) && ++ sym_is_changable(sym) && sym->name && !sym_is_choice_value(sym)) { ++ conf_write_new_symbol(stdout, sym, verbose); ++ } ++ ++ for (child = menu->list; child; child = child->next) ++ report_conf(child, verbose); ++} ++ + static struct option long_opts[] = { + {"oldaskconfig", no_argument, NULL, oldaskconfig}, + {"oldconfig", no_argument, NULL, oldconfig}, +@@ -482,12 +504,15 @@ int main(int ac, char **av) + const char *progname = av[0]; + int opt; + const char *name, *defconfig_file = NULL /* gcc uninit */; ++ const char *value; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + ++ tty_stdio = isatty(0) && isatty(1) && isatty(2); ++ + while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { + input_mode = (enum input_mode)opt; + switch (opt) { +@@ -604,7 +629,7 @@ int main(int ac, char **av) + return 1; + } + } +- valid_stdin = isatty(0) && isatty(1) && isatty(2); ++ valid_stdin = tty_stdio; + } + + switch (input_mode) { +@@ -634,16 +659,18 @@ int main(int ac, char **av) + input_mode = silentoldconfig; + /* fall through */ + case oldconfig: +- case listnewconfig: + case oldnoconfig: + case silentoldconfig: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); +- } while (conf_cnt && +- (input_mode != listnewconfig && +- input_mode != oldnoconfig)); ++ } while (conf_cnt && input_mode != oldnoconfig); ++ break; ++ case listnewconfig: ++ conf_set_all_new_symbols(def_default); ++ value = getenv("KBUILD_VERBOSE"); ++ report_conf(&rootmenu, value && atoi(value)); + break; + } + +diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c +index 5a58965..3e71295 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch new file mode 100644 index 00000000..37a7f3be --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_confdata.c.patch @@ -0,0 +1,27 @@ +--- a/scripts/kconfig/confdata.c ++++ b/scripts/kconfig/confdata.c +@@ -713,6 +713,14 @@ next_menu: + return 0; + } + ++void conf_write_new_symbol(FILE *fp, struct symbol *sym, bool verbose) ++{ ++ if (verbose) ++ conf_write_symbol(fp, sym, &kconfig_printer_cb, NULL); ++ else ++ fprintf(fp, "%s%s\n", CONFIG_, sym->name); ++} ++ + int conf_write(const char *name) + { + FILE *out; +@@ -1102,6 +1110,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) + for_all_symbols(i, sym) { + if (sym_has_value(sym)) + continue; ++ sym->flags |= SYMBOL_NEW; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: +diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h +index 80fce57..0db77f3 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch new file mode 100644 index 00000000..6562d9fe --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_expr.h.patch @@ -0,0 +1,13 @@ +--- a/scripts/kconfig/expr.h ++++ b/scripts/kconfig/expr.h +@@ -104,6 +104,8 @@ struct symbol { + #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ + #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + ++#define SYMBOL_NEW 0x100000 /* symbol is new (loaded config did not provide a value) */ ++ + #define SYMBOL_MAXLENGTH 256 + #define SYMBOL_HASHSIZE 9973 + +diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h +index 47fe9c3..dd0024a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch new file mode 100644 index 00000000..0b603bbe --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_kconfig_lkc_proto.h.patch @@ -0,0 +1,12 @@ +--- a/scripts/kconfig/lkc_proto.h ++++ b/scripts/kconfig/lkc_proto.h +@@ -7,6 +7,7 @@ P(conf_read_simple,int,(const char *name, int)); + P(conf_write_defconfig,int,(const char *name)); + P(conf_write,int,(const char *name)); + P(conf_write_autoconf,int,(void)); ++P(conf_write_new_symbol, void,(FILE*, struct symbol*, bool)); + P(conf_get_changed,bool,(void)); + P(conf_set_changed_callback, void,(void (*fn)(void))); + P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); +diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c +index 98ff331..1c30f8a 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch new file mode 100644 index 00000000..a4bcf76e --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_mod_file2alias.c.patch @@ -0,0 +1,46 @@ +--- a/scripts/mod/file2alias.c ++++ b/scripts/mod/file2alias.c +@@ -880,6 +880,30 @@ static int do_isapnp_entry(const char *filename, + return 1; + } + ++/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,* ++ * All fields are numbers. It would be nicer to use strings for vendor ++ * and feature, but getting those out of the build system here is too ++ * complicated. ++ */ ++ ++static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id, ++ char *alias) ++{ ++ id->feature = TO_NATIVE(id->feature); ++ id->family = TO_NATIVE(id->family); ++ id->model = TO_NATIVE(id->model); ++ id->vendor = TO_NATIVE(id->vendor); ++ ++ strcpy(alias, "x86cpu:"); ++ ADD(alias, "vendor:", id->vendor != X86_VENDOR_ANY, id->vendor); ++ ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family); ++ ADD(alias, ":model:", id->model != X86_MODEL_ANY, id->model); ++ strcat(alias, ":feature:*"); ++ if (id->feature != X86_FEATURE_ANY) ++ sprintf(alias + strlen(alias), "%04X*", id->feature); ++ return 1; ++} ++ + /* Ignore any prefix, eg. some architectures prepend _ */ + static inline int sym_is(const char *symbol, const char *name) + { +@@ -1051,6 +1075,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + do_table(symval, sym->st_size, + sizeof(struct isapnp_device_id), "isa", + do_isapnp_entry, mod); ++ else if (sym_is(symname, "__mod_x86cpu_device_table")) ++ do_table(symval, sym->st_size, ++ sizeof(struct x86_cpu_id), "x86cpu", ++ do_x86cpu_entry, mod); + free(zeros); + } + +diff --git a/scripts/package/Makefile b/scripts/package/Makefile +index bc6aa00..b0817f9 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch b/packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch new file mode 100644 index 00000000..3d414ce2 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/scripts_package_Makefile.patch @@ -0,0 +1,31 @@ +--- a/scripts/package/Makefile ++++ b/scripts/package/Makefile +@@ -77,8 +77,8 @@ clean-files += $(objtree)/binkernel.spec + + # Deb target + # --------------------------------------------------------------------------- +-quiet_cmd_builddeb = BUILDDEB +- cmd_builddeb = set -e; \ ++#quiet_cmd_builddeb = BUILDDEB ++# cmd_builddeb = set -e; \ + test `id -u` = 0 || \ + test -n "$(KBUILD_PKG_ROOTCMD)" || { \ + which fakeroot >/dev/null 2>&1 && \ +@@ -95,11 +95,11 @@ quiet_cmd_builddeb = BUILDDEB + $$KBUILD_PKG_ROOTCMD $(CONFIG_SHELL) \ + $(srctree)/scripts/package/builddeb + +-deb-pkg: FORCE +- $(MAKE) KBUILD_SRC= +- $(call cmd,builddeb) ++#deb-pkg: FORCE ++# $(MAKE) KBUILD_SRC= ++# $(call cmd,builddeb) + +-clean-dirs += $(objtree)/debian/ ++#clean-dirs += $(objtree)/debian/ + + + # tarball targets +diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig +index 9b9013b..51ebf96 100644 diff --git a/packages/base/any/kernels/3.2-lts/patches/series b/packages/base/any/kernels/3.2-lts/patches/series new file mode 100644 index 00000000..e2adb686 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/series @@ -0,0 +1,508 @@ +kernel-overlayfs-v11.patch +kernel-fs-overlayfs-inode.patch +overlayfs_notify.patch +Makefile.patch +arch_arm_Kconfig.patch +arch_arm_Makefile.patch +arch_arm_boot_compressed_head.S.patch +arch_arm_boot_dts_accton_as4610_54.dts.patch +arch_arm_boot_dts_dni_3448p.dts.patch +arch_arm_boot_dts_helix4.dtsi.patch +arch_arm_common_gic.c.patch +arch_arm_configs_iproc_defconfig.patch +arch_arm_include_asm_bug.h.patch +arch_arm_include_asm_hardware_gic.h.patch +arch_arm_include_asm_pgtable.h.patch +arch_arm_include_asm_processor.h.patch +arch_arm_kernel_entry-armv.S.patch +arch_arm_kernel_entry-header.S.patch +arch_arm_kernel_head.S.patch +arch_arm_kernel_module.c.patch +arch_arm_kernel_process.c.patch +arch_arm_kernel_smp_scu.c.patch +arch_arm_kernel_smp_twd.c.patch +arch_arm_mach-iproc_Kconfig.patch +arch_arm_mach-iproc_Makefile.patch +arch_arm_mach-iproc_Makefile.boot.patch +arch_arm_mach-iproc_board_bu.c.patch +arch_arm_mach-iproc_common.c.patch +arch_arm_mach-iproc_common.h.patch +arch_arm_mach-iproc_flash.c.patch +arch_arm_mach-iproc_idm.c.patch +arch_arm_mach-iproc_include_mach_io_map.h.patch +arch_arm_mach-iproc_include_mach_iproc_regs.h.patch +arch_arm_mach-iproc_include_mach_nand_iproc.h.patch +arch_arm_mach-iproc_include_mach_qspi_iproc.h.patch +arch_arm_mach-iproc_include_mach_reg_utils.h.patch +arch_arm_mach-iproc_include_mach_socregs_ing_open.h.patch +arch_arm_mach-iproc_include_mach_socregs_ns_open.h.patch +arch_arm_mach-iproc_include_mach_socregs_nsp_open.h.patch +arch_arm_mach-iproc_include_mach_socregs_p7_open.h.patch +arch_arm_mach-iproc_include_mach_vmalloc.h.patch +arch_arm_mach-iproc_io_map.c.patch +arch_arm_mach-iproc_localtimer.c.patch +arch_arm_mach-iproc_northstar.c.patch +arch_arm_mach-iproc_northstar.h.patch +arch_arm_mach-iproc_northstar_dmu.c.patch +arch_arm_mach-iproc_pm.c.patch +arch_arm_mm_Kconfig.patch +arch_arm_mm_init.c.patch +arch_arm_mm_ioremap.c.patch +arch_arm_mm_mm.h.patch +arch_arm_mm_mmap.c.patch +arch_arm_mm_mmu.c.patch +arch_arm_mm_nommu.c.patch +arch_arm_net_Makefile.patch +arch_arm_net_bpf_jit_32.c.patch +arch_arm_net_bpf_jit_32.h.patch +arch_arm_plat-iproc_Kconfig.patch +arch_arm_plat-iproc_Makefile.patch +arch_arm_plat-iproc_bcm5301x.c.patch +arch_arm_plat-iproc_clock.c.patch +arch_arm_plat-iproc_headsmp.S.patch +arch_arm_plat-iproc_hotplug.c.patch +arch_arm_plat-iproc_include_mach_brcm_rdb_rng.h.patch +arch_arm_plat-iproc_include_mach_bridge-regs.h.patch +arch_arm_plat-iproc_include_mach_clkdev.h.patch +arch_arm_plat-iproc_include_mach_clock.h.patch +arch_arm_plat-iproc_include_mach_common.h.patch +arch_arm_plat-iproc_include_mach_debug-macro.S.patch +arch_arm_plat-iproc_include_mach_entry-macro.S.patch +arch_arm_plat-iproc_include_mach_gpio.h.patch +arch_arm_plat-iproc_include_mach_hardware.h.patch +arch_arm_plat-iproc_include_mach_io.h.patch +arch_arm_plat-iproc_include_mach_iproc.h.patch +arch_arm_plat-iproc_include_mach_iproc_timer.h.patch +arch_arm_plat-iproc_include_mach_irqs.h.patch +arch_arm_plat-iproc_include_mach_lm.h.patch +arch_arm_plat-iproc_include_mach_memory.h.patch +arch_arm_plat-iproc_include_mach_sdio_platform.h.patch +arch_arm_plat-iproc_include_mach_smp.h.patch +arch_arm_plat-iproc_include_mach_system.h.patch +arch_arm_plat-iproc_include_mach_timer.h.patch +arch_arm_plat-iproc_include_mach_timex.h.patch +arch_arm_plat-iproc_include_mach_uncompress.h.patch +arch_arm_plat-iproc_include_plat_dma-pl330.h.patch +arch_arm_plat-iproc_include_plat_dma_drv.h.patch +arch_arm_plat-iproc_include_plat_dmux.h.patch +arch_arm_plat-iproc_include_plat_osdal_os.h.patch +arch_arm_plat-iproc_include_plat_shm.h.patch +arch_arm_plat-iproc_include_plat_spi_iproc.h.patch +arch_arm_plat-iproc_include_plat_swreset_rec.h.patch +arch_arm_plat-iproc_include_plat_timer-sp.h.patch +arch_arm_plat-iproc_include_plat_types.h.patch +arch_arm_plat-iproc_iproc-cache.S.patch +arch_arm_plat-iproc_iproc_cru.c.patch +arch_arm_plat-iproc_irq.c.patch +arch_arm_plat-iproc_lm.c.patch +arch_arm_plat-iproc_localtimer.c.patch +arch_arm_plat-iproc_platsmp.c.patch +arch_arm_plat-iproc_shm.c.patch +arch_arm_plat-iproc_swreset_rec.c.patch +arch_arm_plat-iproc_sysfs.c.patch +arch_arm_plat-iproc_timer-sp.c.patch +arch_arm_plat-iproc_timer.c.patch +arch_arm_tools_mach-types.patch +drivers_Kconfig.patch +drivers_Makefile.patch +drivers_base_Kconfig.patch +drivers_base_Makefile.patch +drivers_base_base.h.patch +drivers_base_bus.c.patch +drivers_base_class.c.patch +drivers_base_core.c.patch +drivers_base_cpu.c.patch +drivers_base_init.c.patch +drivers_base_node.c.patch +drivers_base_sys.c.patch +drivers_base_topology.c.patch +drivers_bcma_host_pci.c.patch +drivers_bcmdrivers_Kconfig.patch +drivers_bcmdrivers_Makefile.patch +drivers_bcmdrivers_dma_.gitignore.patch +drivers_bcmdrivers_dma_Kconfig.patch +drivers_bcmdrivers_dma_Makefile.patch +drivers_bcmdrivers_dma_dma-pl330.h.patch +drivers_bcmdrivers_dma_dma.c.patch +drivers_bcmdrivers_dma_dma_drv.h.patch +drivers_bcmdrivers_dma_pl330-pdata.h.patch +drivers_bcmdrivers_gmac_et_.gitignore.patch +drivers_bcmdrivers_gmac_et_Kconfig.patch +drivers_bcmdrivers_gmac_et_Makefile.patch +drivers_bcmdrivers_gmac_hnd_.gitignore.patch +drivers_bcmdrivers_gmac_hnd_Kconfig.patch +drivers_bcmdrivers_gmac_hnd_Makefile.patch +drivers_bcmdrivers_gmac_hnd_shared_ksyms.c.patch +drivers_bcmdrivers_gmac_hnd_shared_ksyms.sh.patch +drivers_bcmdrivers_gmac_src_et_sys_.gitignore.patch +drivers_bcmdrivers_gmac_src_et_sys_et_cfg.h.patch +drivers_bcmdrivers_gmac_src_et_sys_et_dbg.h.patch +drivers_bcmdrivers_gmac_src_et_sys_et_export.h.patch +drivers_bcmdrivers_gmac_src_et_sys_et_linux.c.patch +drivers_bcmdrivers_gmac_src_et_sys_et_linux.h.patch +drivers_bcmdrivers_gmac_src_et_sys_etc.c.patch +drivers_bcmdrivers_gmac_src_et_sys_etc.h.patch +drivers_bcmdrivers_gmac_src_et_sys_etcgmac.c.patch +drivers_bcmdrivers_gmac_src_et_sys_etcgmac.h.patch +drivers_bcmdrivers_gmac_src_include_Makefile.patch +drivers_bcmdrivers_gmac_src_include_aidmp.h.patch +drivers_bcmdrivers_gmac_src_include_arminc.h.patch +drivers_bcmdrivers_gmac_src_include_bcm_cfg.h.patch +drivers_bcmdrivers_gmac_src_include_bcm_mpool_pub.h.patch +drivers_bcmdrivers_gmac_src_include_bcmcdc.h.patch +drivers_bcmdrivers_gmac_src_include_bcmdefs.h.patch +drivers_bcmdrivers_gmac_src_include_bcmdevs.h.patch +drivers_bcmdrivers_gmac_src_include_bcmendian.h.patch +drivers_bcmdrivers_gmac_src_include_bcmenetmib.h.patch +drivers_bcmdrivers_gmac_src_include_bcmenetphy.h.patch +drivers_bcmdrivers_gmac_src_include_bcmenetrxh.h.patch +drivers_bcmdrivers_gmac_src_include_bcmgmacmib.h.patch +drivers_bcmdrivers_gmac_src_include_bcmgmacrxh.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_phy.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5221.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_phy5461s.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_robo_serdes.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes.h.patch +drivers_bcmdrivers_gmac_src_include_bcmiproc_serdes_def.h.patch +drivers_bcmdrivers_gmac_src_include_bcmnvram.h.patch +drivers_bcmdrivers_gmac_src_include_bcmotp.h.patch +drivers_bcmdrivers_gmac_src_include_bcmparams.h.patch +drivers_bcmdrivers_gmac_src_include_bcmperf.h.patch +drivers_bcmdrivers_gmac_src_include_bcmrobo.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsdh.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsdpcm.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsrom.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsrom_fmt.h.patch +drivers_bcmdrivers_gmac_src_include_bcmsrom_tbl.h.patch +drivers_bcmdrivers_gmac_src_include_bcmstdlib.h.patch +drivers_bcmdrivers_gmac_src_include_bcmutils.h.patch +drivers_bcmdrivers_gmac_src_include_bcmwifi.h.patch +drivers_bcmdrivers_gmac_src_include_compvers.sh.patch +drivers_bcmdrivers_gmac_src_include_ctf_ctf_cfg.h.patch +drivers_bcmdrivers_gmac_src_include_ctf_hndctf.h.patch +drivers_bcmdrivers_gmac_src_include_epivers.h.patch +drivers_bcmdrivers_gmac_src_include_epivers.h.in.patch +drivers_bcmdrivers_gmac_src_include_epivers.sh.patch +drivers_bcmdrivers_gmac_src_include_etioctl.h.patch +drivers_bcmdrivers_gmac_src_include_gmac_common.h.patch +drivers_bcmdrivers_gmac_src_include_gmac_core.h.patch +drivers_bcmdrivers_gmac_src_include_hndarm.h.patch +drivers_bcmdrivers_gmac_src_include_hndchipc.h.patch +drivers_bcmdrivers_gmac_src_include_hndcpu.h.patch +drivers_bcmdrivers_gmac_src_include_hnddma.h.patch +drivers_bcmdrivers_gmac_src_include_hndfwd.h.patch +drivers_bcmdrivers_gmac_src_include_hndsoc.h.patch +drivers_bcmdrivers_gmac_src_include_hndtcam.h.patch +drivers_bcmdrivers_gmac_src_include_linux_osl.h.patch +drivers_bcmdrivers_gmac_src_include_linuxver.h.patch +drivers_bcmdrivers_gmac_src_include_osl.h.patch +drivers_bcmdrivers_gmac_src_include_packed_section_end.h.patch +drivers_bcmdrivers_gmac_src_include_packed_section_start.h.patch +drivers_bcmdrivers_gmac_src_include_pcicfg.h.patch +drivers_bcmdrivers_gmac_src_include_proto_802.11.h.patch +drivers_bcmdrivers_gmac_src_include_proto_802.1d.h.patch +drivers_bcmdrivers_gmac_src_include_proto_BOM.patch +drivers_bcmdrivers_gmac_src_include_proto_Makefile.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmeth.h.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmevent.h.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmip.h.patch +drivers_bcmdrivers_gmac_src_include_proto_bcmipv6.h.patch +drivers_bcmdrivers_gmac_src_include_proto_ethernet.h.patch +drivers_bcmdrivers_gmac_src_include_proto_vlan.h.patch +drivers_bcmdrivers_gmac_src_include_proto_wpa.h.patch +drivers_bcmdrivers_gmac_src_include_sbchipc.h.patch +drivers_bcmdrivers_gmac_src_include_sbconfig.h.patch +drivers_bcmdrivers_gmac_src_include_sbhndarm.h.patch +drivers_bcmdrivers_gmac_src_include_sbhnddma.h.patch +drivers_bcmdrivers_gmac_src_include_sbsocram.h.patch +drivers_bcmdrivers_gmac_src_include_siutils.h.patch +drivers_bcmdrivers_gmac_src_include_trxhdr.h.patch +drivers_bcmdrivers_gmac_src_include_typedefs.h.patch +drivers_bcmdrivers_gmac_src_include_wlioctl.h.patch +drivers_bcmdrivers_gmac_src_shared_aiutils.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5221.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_phy5461s.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_robo_serdes.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmiproc_serdes.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmotp.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmrobo.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmsrom.c.patch +drivers_bcmdrivers_gmac_src_shared_bcmutils.c.patch +drivers_bcmdrivers_gmac_src_shared_hnddma.c.patch +drivers_bcmdrivers_gmac_src_shared_hndfwd.c.patch +drivers_bcmdrivers_gmac_src_shared_hr2_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_hr2_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_hx4_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_hx4_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_kt2_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_kt2_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_linux_osl.c.patch +drivers_bcmdrivers_gmac_src_shared_nsp_erom.c.patch +drivers_bcmdrivers_gmac_src_shared_nsp_erom.h.patch +drivers_bcmdrivers_gmac_src_shared_nvramstubs.c.patch +drivers_bcmdrivers_gmac_src_shared_siutils.c.patch +drivers_bcmdrivers_gmac_src_shared_siutils_priv.h.patch +drivers_bcmdrivers_gmac_src_shared_wl_config.patch +drivers_bcmdrivers_gpio_.gitignore.patch +drivers_bcmdrivers_gpio_Kconfig.patch +drivers_bcmdrivers_gpio_Makefile.patch +drivers_bcmdrivers_gpio_gpio.c.patch +drivers_bcmdrivers_gpio_gpio.h.patch +drivers_bcmdrivers_gpio_gpio_cfg.c.patch +drivers_bcmdrivers_gpio_gpio_cfg.h.patch +drivers_bcmdrivers_gpio_gpiolib.c.patch +drivers_bcmdrivers_include_Readme.txt.patch +drivers_bcmdrivers_mdio_.gitignore.patch +drivers_bcmdrivers_mdio_Kconfig.patch +drivers_bcmdrivers_mdio_Makefile.patch +drivers_bcmdrivers_mdio_iproc_mdio.c.patch +drivers_bcmdrivers_mdio_iproc_mdio.h.patch +drivers_bcmdrivers_mdio_iproc_mdio_dev.h.patch +drivers_bcmdrivers_nand_.gitignore.patch +drivers_bcmdrivers_nand_Kconfig.patch +drivers_bcmdrivers_nand_Makefile.patch +drivers_bcmdrivers_nand_nand_iproc.c.patch +drivers_bcmdrivers_pmu_.gitignore.patch +drivers_bcmdrivers_pmu_Kconfig.patch +drivers_bcmdrivers_pmu_Makefile.patch +drivers_bcmdrivers_pmu_iproc-pmu.c.patch +drivers_bcmdrivers_pwm_.gitignore.patch +drivers_bcmdrivers_pwm_Kconfig.patch +drivers_bcmdrivers_pwm_Makefile.patch +drivers_bcmdrivers_pwm_iproc_pwmc.c.patch +drivers_bcmdrivers_pwm_iproc_pwmc_3x.c.patch +drivers_bcmdrivers_qspi_.gitignore.patch +drivers_bcmdrivers_qspi_Kconfig.patch +drivers_bcmdrivers_qspi_Makefile.patch +drivers_bcmdrivers_qspi_qspi_iproc.c.patch +drivers_bcmdrivers_smbus_.gitignore.patch +drivers_bcmdrivers_smbus_Kconfig.patch +drivers_bcmdrivers_smbus_Makefile.patch +drivers_bcmdrivers_smbus_iproc_smbus.c.patch +drivers_bcmdrivers_smbus_iproc_smbus.h.patch +drivers_bcmdrivers_smbus_iproc_smbus_defs.h.patch +drivers_bcmdrivers_smbus_iproc_smbus_regs.h.patch +drivers_bcmdrivers_timer_.gitignore.patch +drivers_bcmdrivers_timer_Kconfig.patch +drivers_bcmdrivers_timer_Makefile.patch +drivers_bcmdrivers_timer_iproc_timer.c.patch +drivers_bcmdrivers_timer_iproc_timer.h.patch +drivers_bcmdrivers_usb2h_.gitignore.patch +drivers_bcmdrivers_usb2h_Kconfig.patch +drivers_bcmdrivers_usb2h_Makefile.patch +drivers_bcmdrivers_usb2h_bcm-iproc.c.patch +drivers_bcmdrivers_usb2h_bcm_usbh.h.patch +drivers_bcmdrivers_usb2h_ehci-bcm.c.patch +drivers_bcmdrivers_usb2h_ohci-bcm.c.patch +drivers_bcmdrivers_usb2h_usbh_cfg.h.patch +drivers_bcmdrivers_wdt_.gitignore.patch +drivers_bcmdrivers_wdt_Kconfig.patch +drivers_bcmdrivers_wdt_Makefile.patch +drivers_bcmdrivers_wdt_iproc_wdt.c.patch +drivers_cpuidle_cpuidle.c.patch +drivers_cpuidle_cpuidle.h.patch +drivers_cpuidle_sysfs.c.patch +drivers_crypto_padlock-aes.c.patch +drivers_crypto_padlock-sha.c.patch +drivers_dma_Kconfig.patch +drivers_dma_imx-sdma.c.patch +drivers_gpio_Kconfig.patch +drivers_gpio_gpio-mpc8xxx.c.patch +drivers_gpio_gpio-pca953x.c.patch +drivers_gpio_gpio-sch.c.patch +drivers_hwmon_Kconfig.patch +drivers_hwmon_Makefile.patch +drivers_hwmon_adt7470.c.patch +drivers_hwmon_adt7475.c.patch +drivers_hwmon_coretemp.c.patch +drivers_hwmon_cy8c3245r1.c.patch +drivers_hwmon_cy8cxx.c.patch +drivers_hwmon_emc2305.c.patch +drivers_hwmon_it87.c.patch +drivers_hwmon_max6620.c.patch +drivers_hwmon_max6639.c.patch +drivers_hwmon_max6697.c.patch +drivers_hwmon_pmbus_Kconfig.patch +drivers_hwmon_pmbus_Makefile.patch +drivers_hwmon_pmbus_cpr4011.c.patch +drivers_hwmon_pmbus_dps460.c.patch +drivers_hwmon_pmbus_pmbus.h.patch +drivers_hwmon_pmbus_pmbus_core.c.patch +drivers_hwmon_pmbus_ps2471.c.patch +drivers_hwmon_via-cputemp.c.patch +drivers_i2c_busses_Kconfig.patch +drivers_i2c_busses_Makefile.patch +drivers_i2c_i2c-mux.c.patch +drivers_i2c_muxes_Kconfig.patch +drivers_i2c_muxes_Makefile.patch +drivers_i2c_muxes_gpio-i2cmux.c.patch +drivers_i2c_muxes_pca9541.c.patch +drivers_i2c_muxes_pca954x.c.patch +drivers_misc_Kconfig.patch +drivers_misc_Makefile.patch +drivers_misc_ds100df410.c.patch +drivers_misc_early_dma_alloc.c.patch +drivers_misc_eeprom_Kconfig.patch +drivers_misc_eeprom_Makefile.patch +drivers_misc_eeprom_at24.c.patch +drivers_misc_eeprom_eeprom_class.c.patch +drivers_misc_eeprom_sff_8436_eeprom.c.patch +drivers_misc_iwmc3200top_fw-download.c.patch +drivers_misc_retimer_class.c.patch +drivers_misc_ti-st_st_kim.c.patch +drivers_mtd_chips_Kconfig.patch +drivers_mtd_chips_cfi_cmdset_0020.c.patch +drivers_mtd_devices_Kconfig.patch +drivers_mtd_devices_m25p80.c.patch +drivers_mtd_maps_physmap_of.c.patch +drivers_mtd_mtdoops.c.patch +drivers_mtd_ubi_build.c.patch +drivers_net_Makefile.patch +drivers_net_can_softing_softing_fw.c.patch +drivers_net_ethernet_broadcom_bnx2.c.patch +drivers_net_ethernet_broadcom_bnx2x_bnx2x_cmn.c.patch +drivers_net_ethernet_broadcom_bnx2x_bnx2x_ethtool.c.patch +drivers_net_ethernet_broadcom_bnx2x_bnx2x_main.c.patch +drivers_net_ethernet_broadcom_tg3.c.patch +drivers_net_phy_mdio_bus.c.patch +drivers_net_phy_phy.c.patch +drivers_net_phy_phy_device.c.patch +drivers_of_of_mdio.c.patch +drivers_of_platform.c.patch +drivers_pci_access.c.patch +drivers_pci_msi.c.patch +drivers_pci_pci.c.patch +drivers_pci_pcie_aspm.c.patch +drivers_pci_probe.c.patch +drivers_pci_quirks.c.patch +drivers_pci_setup-res.c.patch +drivers_rtc_hctosys.c.patch +drivers_rtc_rtc-m41t80.c.patch +drivers_rtc_rtc-mv.c.patch +drivers_rtc_rtc-s35390a.c.patch +drivers_tty_cyclades.c.patch +drivers_tty_moxa.c.patch +drivers_tty_serial_icom.c.patch +drivers_tty_serial_ucc_uart.c.patch +drivers_usb_host_ehci-hcd.c.patch +drivers_usb_host_ehci-hub.c.patch +drivers_usb_host_ohci-hcd.c.patch +drivers_usb_misc_emi26.c.patch +drivers_usb_misc_emi62.c.patch +drivers_usb_serial_io_edgeport.c.patch +drivers_usb_serial_io_ti.c.patch +drivers_usb_serial_keyspan.c.patch +drivers_usb_serial_keyspan_pda.c.patch +drivers_usb_serial_ti_usb_3410_5052.c.patch +drivers_usb_serial_whiteheat.c.patch +drivers_watchdog_Kconfig.patch +drivers_watchdog_Makefile.patch +drivers_watchdog_booke_wdt.c.patch +drivers_watchdog_iTCO_wdt.c.patch +drivers_watchdog_ie6xx_wdt.c.patch +drivers_watchdog_sp5100_tco.c.patch +include_asm-generic_io-64-nonatomic-hi-lo.h.patch +include_asm-generic_io-64-nonatomic-lo-hi.h.patch +include_linux_amba_bus.h.patch +include_linux_audit.h.patch +include_linux_bitops.h.patch +include_linux_ceph_messenger.h.patch +include_linux_connector.h.patch +include_linux_cpu.h.patch +include_linux_dcache.h.patch +include_linux_device-mapper.h.patch +include_linux_device.h.patch +include_linux_dma-mapping.h.patch +include_linux_dmaengine.h.patch +include_linux_dmi.h.patch +include_linux_dynamic_queue_limits.h.patch +include_linux_early_dma_alloc.h.patch +include_linux_eeprom_class.h.patch +include_linux_efi.h.patch +include_linux_ethtool.h.patch +include_linux_ftrace_event.h.patch +include_linux_hashtable.h.patch +include_linux_i2c-mux-gpio.h.patch +include_linux_i2c-mux.h.patch +include_linux_i2c.h.patch +include_linux_i2c_at24.h.patch +include_linux_i2c_pca953x.h.patch +include_linux_i2c_sff-8436.h.patch +include_linux_if_bridge.h.patch +include_linux_if_ether.h.patch +include_linux_if_link.h.patch +include_linux_if_tun.h.patch +include_linux_init.h.patch +include_linux_irqdesc.h.patch +include_linux_jbd2.h.patch +include_linux_jiffies.h.patch +include_linux_kvm_host.h.patch +include_linux_mdio.h.patch +include_linux_mii.h.patch +include_linux_mm_types.h.patch +include_linux_mod_devicetable.h.patch +include_linux_mroute.h.patch +include_linux_msi.h.patch +include_linux_mtd_cfi.h.patch +include_linux_mtd_cfi_endian.h.patch +include_linux_mtd_map.h.patch +include_linux_neighbour.h.patch +include_linux_of_mdio.h.patch +include_linux_pci.h.patch +include_linux_pci_ids.h.patch +include_linux_pci_regs.h.patch +include_linux_percpu.h.patch +include_linux_perf_event.h.patch +include_linux_phy.h.patch +include_linux_pid_namespace.h.patch +include_linux_pkt_sched.h.patch +include_linux_platform_data_max6697.h.patch +include_linux_platform_device.h.patch +include_linux_port.h.patch +include_linux_pps_kernel.h.patch +include_linux_ptrace.h.patch +include_linux_random.h.patch +include_linux_regulator_consumer.h.patch +include_linux_retimer_class.h.patch +include_linux_rmap.h.patch +include_linux_skbuff.h.patch +include_linux_slab_def.h.patch +include_linux_snmp.h.patch +include_linux_swiotlb.h.patch +include_linux_sysctl.h.patch +include_linux_sysfs.h.patch +include_linux_sysrq.h.patch +include_linux_tcp.h.patch +include_linux_u64_stats_sync.h.patch +include_linux_usb.h.patch +include_linux_usb_ehci_def.h.patch +include_linux_usb_hcd.h.patch +include_linux_vmalloc.h.patch +include_linux_watchdog.h.patch +include_trace_syscall.h.patch +init_Kconfig.patch +lib_Kconfig.patch +lib_Kconfig.debug.patch +lib_Makefile.patch +lib_dynamic_queue_limits.c.patch +lib_nlattr.c.patch +lib_swiotlb.c.patch +mm_backing-dev.c.patch +mm_memcontrol.c.patch +mm_rmap.c.patch +mm_slab.c.patch +mm_sparse-vmemmap.c.patch +mm_swap.c.patch +mm_truncate.c.patch +mm_vmalloc.c.patch +mm_vmscan.c.patch +scripts_Makefile.fwinst.patch +scripts_kconfig_conf.c.patch +scripts_kconfig_confdata.c.patch +scripts_kconfig_expr.h.patch +scripts_kconfig_lkc_proto.h.patch +scripts_mod_file2alias.c.patch +scripts_package_Makefile.patch +tools_include_tools_be_byteshift.h.patch +tools_include_tools_le_byteshift.h.patch +platform-accton-as4610-device-drivers.patch diff --git a/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch new file mode 100644 index 00000000..f55db105 --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_be_byteshift.h.patch @@ -0,0 +1,76 @@ +--- /dev/null ++++ b/tools/include/tools/be_byteshift.h +@@ -0,0 +1,70 @@ ++#ifndef _TOOLS_BE_BYTESHIFT_H ++#define _TOOLS_BE_BYTESHIFT_H ++ ++#include ++ ++static inline __u16 __get_unaligned_be16(const __u8 *p) ++{ ++ return p[0] << 8 | p[1]; ++} ++ ++static inline __u32 __get_unaligned_be32(const __u8 *p) ++{ ++ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; ++} ++ ++static inline __u64 __get_unaligned_be64(const __u8 *p) ++{ ++ return (__u64)__get_unaligned_be32(p) << 32 | ++ __get_unaligned_be32(p + 4); ++} ++ ++static inline void __put_unaligned_be16(__u16 val, __u8 *p) ++{ ++ *p++ = val >> 8; ++ *p++ = val; ++} ++ ++static inline void __put_unaligned_be32(__u32 val, __u8 *p) ++{ ++ __put_unaligned_be16(val >> 16, p); ++ __put_unaligned_be16(val, p + 2); ++} ++ ++static inline void __put_unaligned_be64(__u64 val, __u8 *p) ++{ ++ __put_unaligned_be32(val >> 32, p); ++ __put_unaligned_be32(val, p + 4); ++} ++ ++static inline __u16 get_unaligned_be16(const void *p) ++{ ++ return __get_unaligned_be16((const __u8 *)p); ++} ++ ++static inline __u32 get_unaligned_be32(const void *p) ++{ ++ return __get_unaligned_be32((const __u8 *)p); ++} ++ ++static inline __u64 get_unaligned_be64(const void *p) ++{ ++ return __get_unaligned_be64((const __u8 *)p); ++} ++ ++static inline void put_unaligned_be16(__u16 val, void *p) ++{ ++ __put_unaligned_be16(val, p); ++} ++ ++static inline void put_unaligned_be32(__u32 val, void *p) ++{ ++ __put_unaligned_be32(val, p); ++} ++ ++static inline void put_unaligned_be64(__u64 val, void *p) ++{ ++ __put_unaligned_be64(val, p); ++} ++ ++#endif /* _TOOLS_BE_BYTESHIFT_H */ +diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h +new file mode 100644 +index 0000000..c99d45a diff --git a/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch new file mode 100644 index 00000000..d26f3e7f --- /dev/null +++ b/packages/base/any/kernels/3.2-lts/patches/tools_include_tools_le_byteshift.h.patch @@ -0,0 +1,73 @@ +--- /dev/null ++++ b/tools/include/tools/le_byteshift.h +@@ -0,0 +1,70 @@ ++#ifndef _TOOLS_LE_BYTESHIFT_H ++#define _TOOLS_LE_BYTESHIFT_H ++ ++#include ++ ++static inline __u16 __get_unaligned_le16(const __u8 *p) ++{ ++ return p[0] | p[1] << 8; ++} ++ ++static inline __u32 __get_unaligned_le32(const __u8 *p) ++{ ++ return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; ++} ++ ++static inline __u64 __get_unaligned_le64(const __u8 *p) ++{ ++ return (__u64)__get_unaligned_le32(p + 4) << 32 | ++ __get_unaligned_le32(p); ++} ++ ++static inline void __put_unaligned_le16(__u16 val, __u8 *p) ++{ ++ *p++ = val; ++ *p++ = val >> 8; ++} ++ ++static inline void __put_unaligned_le32(__u32 val, __u8 *p) ++{ ++ __put_unaligned_le16(val >> 16, p + 2); ++ __put_unaligned_le16(val, p); ++} ++ ++static inline void __put_unaligned_le64(__u64 val, __u8 *p) ++{ ++ __put_unaligned_le32(val >> 32, p + 4); ++ __put_unaligned_le32(val, p); ++} ++ ++static inline __u16 get_unaligned_le16(const void *p) ++{ ++ return __get_unaligned_le16((const __u8 *)p); ++} ++ ++static inline __u32 get_unaligned_le32(const void *p) ++{ ++ return __get_unaligned_le32((const __u8 *)p); ++} ++ ++static inline __u64 get_unaligned_le64(const void *p) ++{ ++ return __get_unaligned_le64((const __u8 *)p); ++} ++ ++static inline void put_unaligned_le16(__u16 val, void *p) ++{ ++ __put_unaligned_le16(val, p); ++} ++ ++static inline void put_unaligned_le32(__u32 val, void *p) ++{ ++ __put_unaligned_le32(val, p); ++} ++ ++static inline void put_unaligned_le64(__u64 val, void *p) ++{ ++ __put_unaligned_le64(val, p); ++} ++ ++#endif /* _TOOLS_LE_BYTESHIFT_H */