/* * Qualcomm Atheros AP136 reference board support * * Copyright (c) 2012 Qualcomm Atheros * Copyright (c) 2012-2013 Gabor Juhos * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 "dev-spi.h" #include "dev-usb.h" #include "dev-wmac.h" #include "pci.h" static struct spi_board_info qca955x_spi_info[] = { { .bus_num = 0, .chip_select = 0, .max_speed_hz = 25000000, .modalias = "mx25l6405d", } }; static struct ath79_spi_platform_data qca955x_spi_data = { .bus_num = 0, .num_chipselect = 1, }; #ifdef CONFIG_PCI static __init void qca955x_pci_pll_init(void) { /*----------------------------------------------------------------------*\ * Initialize PCIE PLL and get it out of RESET * reg = 0x18050010 \*----------------------------------------------------------------------*/ // common for rc1 and rc2 ath_reg_wr_nf(AR71XX_PLL_BASE + QCA955X_PLL_PCIE_PLL_DITHER_DIV_MAX, PCIE_PLL_DITHER_DIV_MAX_EN_DITHER_SET(0x1) | PCIE_PLL_DITHER_DIV_MAX_USE_MAX_SET(0x1) | PCIE_PLL_DITHER_DIV_MAX_DIV_MAX_INT_SET(0x14) | PCIE_PLL_DITHER_DIV_MAX_DIV_MAX_FRAC_SET(0x3ff)); ath_reg_wr_nf(AR71XX_PLL_BASE + QCA955X_PLL_PCIE_PLL_DITHER_DIV_MIN, PCIE_PLL_DITHER_DIV_MIN_DIV_MIN_INT_SET(0x14)); ath_reg_wr_nf(AR71XX_PLL_BASE + QCA955X_PLL_PCIE_PLL_CONFIG, PCIE_PLL_CONFIG_REFDIV_SET(1) | PCIE_PLL_CONFIG_BYPASS_SET(1) | PCIE_PLL_CONFIG_PLLPWD_SET(1)); mdelay(10); ath_reg_rmw_clear(AR71XX_PLL_BASE + QCA955X_PLL_PCIE_PLL_CONFIG, PCIE_PLL_CONFIG_PLLPWD_SET(1)); mdelay(1); ath_reg_rmw_clear(AR71XX_PLL_BASE + QCA955X_PLL_PCIE_PLL_CONFIG, PCIE_PLL_CONFIG_BYPASS_SET(1)); } #endif /* CONFIG_PCI */ void __init qca955x_setup(void) { unsigned int usb_clock, switch_source = ath_reg_rd(SWITCH_CLOCK_SPARE_ADDRESS); ath79_register_spi(&qca955x_spi_data, qca955x_spi_info, ARRAY_SIZE(qca955x_spi_info)); ath79_register_usb(); /*--- ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET); ---*/ #ifdef CONFIG_PCI qca955x_pci_pll_init(); ath79_register_pci(); #endif usb_clock = switch_source & SWITCH_CLOCK_SPARE_USB_REFCLK_FREQ_SEL_MASK; switch_source = usb_clock | SWITCH_CLOCK_SPARE_MDIO_CLK_SEL1_1_SET(1); ath_reg_wr(SWITCH_CLOCK_SPARE_ADDRESS, switch_source); }